aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/srcu.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/srcu.h')
-rw-r--r--include/linux/srcu.h60
1 files changed, 37 insertions, 23 deletions
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 55a5c52cbb25..04f4121a23ae 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -16,8 +16,10 @@
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 * 17 *
18 * Copyright (C) IBM Corporation, 2006 18 * Copyright (C) IBM Corporation, 2006
19 * Copyright (C) Fujitsu, 2012
19 * 20 *
20 * Author: Paul McKenney <paulmck@us.ibm.com> 21 * Author: Paul McKenney <paulmck@us.ibm.com>
22 * Lai Jiangshan <laijs@cn.fujitsu.com>
21 * 23 *
22 * For detailed explanation of Read-Copy Update mechanism see - 24 * For detailed explanation of Read-Copy Update mechanism see -
23 * Documentation/RCU/ *.txt 25 * Documentation/RCU/ *.txt
@@ -40,6 +42,8 @@ struct rcu_batch {
40 struct rcu_head *head, **tail; 42 struct rcu_head *head, **tail;
41}; 43};
42 44
45#define RCU_BATCH_INIT(name) { NULL, &(name.head) }
46
43struct srcu_struct { 47struct srcu_struct {
44 unsigned completed; 48 unsigned completed;
45 struct srcu_struct_array __percpu *per_cpu_ref; 49 struct srcu_struct_array __percpu *per_cpu_ref;
@@ -70,12 +74,42 @@ int __init_srcu_struct(struct srcu_struct *sp, const char *name,
70 __init_srcu_struct((sp), #sp, &__srcu_key); \ 74 __init_srcu_struct((sp), #sp, &__srcu_key); \
71}) 75})
72 76
77#define __SRCU_DEP_MAP_INIT(srcu_name) .dep_map = { .name = #srcu_name },
73#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 78#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
74 79
75int init_srcu_struct(struct srcu_struct *sp); 80int init_srcu_struct(struct srcu_struct *sp);
76 81
82#define __SRCU_DEP_MAP_INIT(srcu_name)
77#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 83#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
78 84
85void process_srcu(struct work_struct *work);
86
87#define __SRCU_STRUCT_INIT(name) \
88 { \
89 .completed = -300, \
90 .per_cpu_ref = &name##_srcu_array, \
91 .queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock), \
92 .running = false, \
93 .batch_queue = RCU_BATCH_INIT(name.batch_queue), \
94 .batch_check0 = RCU_BATCH_INIT(name.batch_check0), \
95 .batch_check1 = RCU_BATCH_INIT(name.batch_check1), \
96 .batch_done = RCU_BATCH_INIT(name.batch_done), \
97 .work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
98 __SRCU_DEP_MAP_INIT(name) \
99 }
100
101/*
102 * define and init a srcu struct at build time.
103 * dont't call init_srcu_struct() nor cleanup_srcu_struct() on it.
104 */
105#define DEFINE_SRCU(name) \
106 static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
107 struct srcu_struct name = __SRCU_STRUCT_INIT(name);
108
109#define DEFINE_STATIC_SRCU(name) \
110 static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
111 static struct srcu_struct name = __SRCU_STRUCT_INIT(name);
112
79/** 113/**
80 * call_srcu() - Queue a callback for invocation after an SRCU grace period 114 * call_srcu() - Queue a callback for invocation after an SRCU grace period
81 * @sp: srcu_struct in queue the callback 115 * @sp: srcu_struct in queue the callback
@@ -117,30 +151,14 @@ void srcu_barrier(struct srcu_struct *sp);
117 * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot 151 * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot
118 * and while lockdep is disabled. 152 * and while lockdep is disabled.
119 * 153 *
120 * Note that if the CPU is in the idle loop from an RCU point of view 154 * Note that SRCU is based on its own statemachine and it doesn't
121 * (ie: that we are in the section between rcu_idle_enter() and 155 * relies on normal RCU, it can be called from the CPU which
122 * rcu_idle_exit()) then srcu_read_lock_held() returns false even if 156 * is in the idle loop from an RCU point of view or offline.
123 * the CPU did an srcu_read_lock(). The reason for this is that RCU
124 * ignores CPUs that are in such a section, considering these as in
125 * extended quiescent state, so such a CPU is effectively never in an
126 * RCU read-side critical section regardless of what RCU primitives it
127 * invokes. This state of affairs is required --- we need to keep an
128 * RCU-free window in idle where the CPU may possibly enter into low
129 * power mode. This way we can notice an extended quiescent state to
130 * other CPUs that started a grace period. Otherwise we would delay any
131 * grace period as long as we run in the idle task.
132 *
133 * Similarly, we avoid claiming an SRCU read lock held if the current
134 * CPU is offline.
135 */ 157 */
136static inline int srcu_read_lock_held(struct srcu_struct *sp) 158static inline int srcu_read_lock_held(struct srcu_struct *sp)
137{ 159{
138 if (!debug_lockdep_rcu_enabled()) 160 if (!debug_lockdep_rcu_enabled())
139 return 1; 161 return 1;
140 if (rcu_is_cpu_idle())
141 return 0;
142 if (!rcu_lockdep_current_cpu_online())
143 return 0;
144 return lock_is_held(&sp->dep_map); 162 return lock_is_held(&sp->dep_map);
145} 163}
146 164
@@ -202,8 +220,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
202 int retval = __srcu_read_lock(sp); 220 int retval = __srcu_read_lock(sp);
203 221
204 rcu_lock_acquire(&(sp)->dep_map); 222 rcu_lock_acquire(&(sp)->dep_map);
205 rcu_lockdep_assert(!rcu_is_cpu_idle(),
206 "srcu_read_lock() used illegally while idle");
207 return retval; 223 return retval;
208} 224}
209 225
@@ -217,8 +233,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
217static inline void srcu_read_unlock(struct srcu_struct *sp, int idx) 233static inline void srcu_read_unlock(struct srcu_struct *sp, int idx)
218 __releases(sp) 234 __releases(sp)
219{ 235{
220 rcu_lockdep_assert(!rcu_is_cpu_idle(),
221 "srcu_read_unlock() used illegally while idle");
222 rcu_lock_release(&(sp)->dep_map); 236 rcu_lock_release(&(sp)->dep_map);
223 __srcu_read_unlock(sp, idx); 237 __srcu_read_unlock(sp, idx);
224} 238}