Blame view

kernel/rcupdate.c 5.75 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Read-Copy Update mechanism for mutual exclusion
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
18
   * Copyright IBM Corporation, 2001
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
   *
   * Authors: Dipankar Sarma <dipankar@in.ibm.com>
   *	    Manfred Spraul <manfred@colorfullife.com>
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
22
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
   * Based on the original work by Paul McKenney <paulmck@us.ibm.com>
   * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
   * Papers:
   * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
   * http://lse.sourceforge.net/locking/rclock_OLS.2001.05.01c.sc.pdf (OLS2001)
   *
   * For detailed explanation of Read-Copy Update mechanism see -
a71fca58b   Paul E. McKenney   rcu: Fix whitespa...
30
   *		http://lse.sourceforge.net/locking/rcupdate.html
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
37
38
39
40
41
   *
   */
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/spinlock.h>
  #include <linux/smp.h>
  #include <linux/interrupt.h>
  #include <linux/sched.h>
  #include <asm/atomic.h>
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  #include <linux/percpu.h>
  #include <linux/notifier.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #include <linux/cpu.h>
9331b3157   Ingo Molnar   [PATCH] convert k...
45
  #include <linux/mutex.h>
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
46
  #include <linux/module.h>
a68260483   Paul E. McKenney   rcu: Teach RCU th...
47
  #include <linux/kernel_stat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

162cc2794   Paul E. McKenney   rcu: Fix rcu_lock...
49
50
51
52
53
54
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  static struct lock_class_key rcu_lock_key;
  struct lockdep_map rcu_lock_map =
  	STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key);
  EXPORT_SYMBOL_GPL(rcu_lock_map);
  #endif
a68260483   Paul E. McKenney   rcu: Teach RCU th...
55
  int rcu_scheduler_active __read_mostly;
21a1ea9eb   Dipankar Sarma   [PATCH] rcu batch...
56

fbf6bfca7   Paul E. McKenney   rcupdate: fix com...
57
58
59
60
  /*
   * Awaken the corresponding synchronize_rcu() instance now that a
   * grace period has elapsed.
   */
4446a36ff   Paul E. McKenney   rcu: add call_rcu...
61
  void wakeme_after_rcu(struct rcu_head  *head)
21a1ea9eb   Dipankar Sarma   [PATCH] rcu batch...
62
  {
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
63
64
65
66
  	struct rcu_synchronize *rcu;
  
  	rcu = container_of(head, struct rcu_synchronize, head);
  	complete(&rcu->completion);
21a1ea9eb   Dipankar Sarma   [PATCH] rcu batch...
67
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68

16e308119   Paul E. McKenney   rcu: Fix synchron...
69
  #ifdef CONFIG_TREE_PREEMPT_RCU
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  /**
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
71
   * synchronize_rcu - wait until a grace period has elapsed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
   *
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
73
74
   * Control will return to the caller some time after a full grace
   * period has elapsed, in other words after all currently executing RCU
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
   * read-side critical sections have completed.  RCU read-side critical
   * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
   * and may be nested.
   */
ea7d3fef4   Paul E. McKenney   rcu: eliminate sy...
79
80
81
  void synchronize_rcu(void)
  {
  	struct rcu_synchronize rcu;
a68260483   Paul E. McKenney   rcu: Teach RCU th...
82

16e308119   Paul E. McKenney   rcu: Fix synchron...
83
  	if (!rcu_scheduler_active)
a68260483   Paul E. McKenney   rcu: Teach RCU th...
84
  		return;
ea7d3fef4   Paul E. McKenney   rcu: eliminate sy...
85
86
87
88
89
90
  	init_completion(&rcu.completion);
  	/* Will wake me after RCU finished. */
  	call_rcu(&rcu.head, wakeme_after_rcu);
  	/* Wait for it. */
  	wait_for_completion(&rcu.completion);
  }
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
91
  EXPORT_SYMBOL_GPL(synchronize_rcu);
c32e06605   Paul E. McKenney   [PATCH] rcutortur...
92

16e308119   Paul E. McKenney   rcu: Fix synchron...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
  
  /**
   * synchronize_sched - wait until an rcu-sched grace period has elapsed.
   *
   * Control will return to the caller some time after a full rcu-sched
   * grace period has elapsed, in other words after all currently executing
   * rcu-sched read-side critical sections have completed.   These read-side
   * critical sections are delimited by rcu_read_lock_sched() and
   * rcu_read_unlock_sched(), and may be nested.  Note that preempt_disable(),
   * local_irq_disable(), and so on may be used in place of
   * rcu_read_lock_sched().
   *
   * This means that all preempt_disable code sequences, including NMI and
   * hardware-interrupt handlers, in progress on entry will have completed
   * before this primitive returns.  However, this does not guarantee that
   * softirq handlers will have completed, since in some kernels, these
   * handlers can run in process context, and can block.
   *
   * This primitive provides the guarantees made by the (now removed)
   * synchronize_kernel() API.  In contrast, synchronize_rcu() only
   * guarantees that rcu_read_lock() sections will have completed.
   * In "classic RCU", these two guarantees happen to be one and
   * the same, but can differ in realtime RCU implementations.
   */
  void synchronize_sched(void)
  {
  	struct rcu_synchronize rcu;
  
  	if (rcu_blocking_is_gp())
  		return;
  
  	init_completion(&rcu.completion);
  	/* Will wake me after RCU finished. */
  	call_rcu_sched(&rcu.head, wakeme_after_rcu);
  	/* Wait for it. */
  	wait_for_completion(&rcu.completion);
  }
  EXPORT_SYMBOL_GPL(synchronize_sched);
03b042bf1   Paul E. McKenney   rcu: Add synchron...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  /**
   * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed.
   *
   * Control will return to the caller some time after a full rcu_bh grace
   * period has elapsed, in other words after all currently executing rcu_bh
   * read-side critical sections have completed.  RCU read-side critical
   * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(),
   * and may be nested.
   */
  void synchronize_rcu_bh(void)
  {
  	struct rcu_synchronize rcu;
  
  	if (rcu_blocking_is_gp())
  		return;
  
  	init_completion(&rcu.completion);
  	/* Will wake me after RCU finished. */
  	call_rcu_bh(&rcu.head, wakeme_after_rcu);
  	/* Wait for it. */
  	wait_for_completion(&rcu.completion);
  }
  EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
f69b17d7e   Lai Jiangshan   rcu: rcu_barrier ...
155
156
157
  static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
  		unsigned long action, void *hcpu)
  {
d0ec774cb   Paul E. McKenney   rcu: Move rcu_bar...
158
  	return rcu_cpu_notify(self, action, hcpu);
f69b17d7e   Lai Jiangshan   rcu: rcu_barrier ...
159
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  void __init rcu_init(void)
  {
2e5975580   Paul E. McKenney   rcu: Simplify RCU...
162
  	int i;
01c1c660f   Paul E. McKenney   Preempt-RCU: reor...
163
  	__rcu_init();
2e5975580   Paul E. McKenney   rcu: Simplify RCU...
164
165
166
167
168
169
170
171
172
  	cpu_notifier(rcu_barrier_cpu_hotplug, 0);
  
  	/*
  	 * We don't need protection against CPU-hotplug here because
  	 * this is called early in boot, before either interrupts
  	 * or the scheduler are operational.
  	 */
  	for_each_online_cpu(i)
  		rcu_barrier_cpu_hotplug(NULL, CPU_UP_PREPARE, (void *)(long)i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  }
a68260483   Paul E. McKenney   rcu: Teach RCU th...
174
175
176
177
178
179
  void rcu_scheduler_starting(void)
  {
  	WARN_ON(num_online_cpus() != 1);
  	WARN_ON(nr_context_switches() > 0);
  	rcu_scheduler_active = 1;
  }