diff options
Diffstat (limited to 'kernel/rcupdate.c')
| -rw-r--r-- | kernel/rcupdate.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 72a8dc9567f5..4d169835fb36 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
| @@ -114,3 +114,163 @@ int rcu_my_thread_group_empty(void) | |||
| 114 | } | 114 | } |
| 115 | EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty); | 115 | EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty); |
| 116 | #endif /* #ifdef CONFIG_PROVE_RCU */ | 116 | #endif /* #ifdef CONFIG_PROVE_RCU */ |
| 117 | |||
| 118 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD | ||
| 119 | static inline void debug_init_rcu_head(struct rcu_head *head) | ||
| 120 | { | ||
| 121 | debug_object_init(head, &rcuhead_debug_descr); | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline void debug_rcu_head_free(struct rcu_head *head) | ||
| 125 | { | ||
| 126 | debug_object_free(head, &rcuhead_debug_descr); | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * fixup_init is called when: | ||
| 131 | * - an active object is initialized | ||
| 132 | */ | ||
| 133 | static int rcuhead_fixup_init(void *addr, enum debug_obj_state state) | ||
| 134 | { | ||
| 135 | struct rcu_head *head = addr; | ||
| 136 | |||
| 137 | switch (state) { | ||
| 138 | case ODEBUG_STATE_ACTIVE: | ||
| 139 | /* | ||
| 140 | * Ensure that queued callbacks are all executed. | ||
| 141 | * If we detect that we are nested in a RCU read-side critical | ||
| 142 | * section, we should simply fail, otherwise we would deadlock. | ||
| 143 | */ | ||
| 144 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
| 145 | irqs_disabled()) { | ||
| 146 | WARN_ON(1); | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | rcu_barrier(); | ||
| 150 | rcu_barrier_sched(); | ||
| 151 | rcu_barrier_bh(); | ||
| 152 | debug_object_init(head, &rcuhead_debug_descr); | ||
| 153 | return 1; | ||
| 154 | default: | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * fixup_activate is called when: | ||
| 161 | * - an active object is activated | ||
| 162 | * - an unknown object is activated (might be a statically initialized object) | ||
| 163 | * Activation is performed internally by call_rcu(). | ||
| 164 | */ | ||
| 165 | static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state) | ||
| 166 | { | ||
| 167 | struct rcu_head *head = addr; | ||
| 168 | |||
| 169 | switch (state) { | ||
| 170 | |||
| 171 | case ODEBUG_STATE_NOTAVAILABLE: | ||
| 172 | /* | ||
| 173 | * This is not really a fixup. We just make sure that it is | ||
| 174 | * tracked in the object tracker. | ||
| 175 | */ | ||
| 176 | debug_object_init(head, &rcuhead_debug_descr); | ||
| 177 | debug_object_activate(head, &rcuhead_debug_descr); | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | case ODEBUG_STATE_ACTIVE: | ||
| 181 | /* | ||
| 182 | * Ensure that queued callbacks are all executed. | ||
| 183 | * If we detect that we are nested in a RCU read-side critical | ||
| 184 | * section, we should simply fail, otherwise we would deadlock. | ||
| 185 | */ | ||
| 186 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
| 187 | irqs_disabled()) { | ||
| 188 | WARN_ON(1); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | rcu_barrier(); | ||
| 192 | rcu_barrier_sched(); | ||
| 193 | rcu_barrier_bh(); | ||
| 194 | debug_object_activate(head, &rcuhead_debug_descr); | ||
| 195 | return 1; | ||
| 196 | default: | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /* | ||
| 202 | * fixup_free is called when: | ||
| 203 | * - an active object is freed | ||
| 204 | */ | ||
| 205 | static int rcuhead_fixup_free(void *addr, enum debug_obj_state state) | ||
| 206 | { | ||
| 207 | struct rcu_head *head = addr; | ||
| 208 | |||
| 209 | switch (state) { | ||
| 210 | case ODEBUG_STATE_ACTIVE: | ||
| 211 | /* | ||
| 212 | * Ensure that queued callbacks are all executed. | ||
| 213 | * If we detect that we are nested in a RCU read-side critical | ||
| 214 | * section, we should simply fail, otherwise we would deadlock. | ||
| 215 | */ | ||
| 216 | #ifndef CONFIG_PREEMPT | ||
| 217 | WARN_ON(1); | ||
| 218 | return 0; | ||
| 219 | #else | ||
| 220 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
| 221 | irqs_disabled()) { | ||
| 222 | WARN_ON(1); | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | rcu_barrier(); | ||
| 226 | rcu_barrier_sched(); | ||
| 227 | rcu_barrier_bh(); | ||
| 228 | debug_object_free(head, &rcuhead_debug_descr); | ||
| 229 | return 1; | ||
| 230 | #endif | ||
| 231 | default: | ||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /** | ||
| 237 | * init_rcu_head_on_stack() - initialize on-stack rcu_head for debugobjects | ||
| 238 | * @head: pointer to rcu_head structure to be initialized | ||
| 239 | * | ||
| 240 | * This function informs debugobjects of a new rcu_head structure that | ||
| 241 | * has been allocated as an auto variable on the stack. This function | ||
| 242 | * is not required for rcu_head structures that are statically defined or | ||
| 243 | * that are dynamically allocated on the heap. This function has no | ||
| 244 | * effect for !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds. | ||
| 245 | */ | ||
| 246 | void init_rcu_head_on_stack(struct rcu_head *head) | ||
| 247 | { | ||
| 248 | debug_object_init_on_stack(head, &rcuhead_debug_descr); | ||
| 249 | } | ||
| 250 | EXPORT_SYMBOL_GPL(init_rcu_head_on_stack); | ||
| 251 | |||
| 252 | /** | ||
| 253 | * destroy_rcu_head_on_stack() - destroy on-stack rcu_head for debugobjects | ||
| 254 | * @head: pointer to rcu_head structure to be initialized | ||
| 255 | * | ||
| 256 | * This function informs debugobjects that an on-stack rcu_head structure | ||
| 257 | * is about to go out of scope. As with init_rcu_head_on_stack(), this | ||
| 258 | * function is not required for rcu_head structures that are statically | ||
| 259 | * defined or that are dynamically allocated on the heap. Also as with | ||
| 260 | * init_rcu_head_on_stack(), this function has no effect for | ||
| 261 | * !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds. | ||
| 262 | */ | ||
| 263 | void destroy_rcu_head_on_stack(struct rcu_head *head) | ||
| 264 | { | ||
| 265 | debug_object_free(head, &rcuhead_debug_descr); | ||
| 266 | } | ||
| 267 | EXPORT_SYMBOL_GPL(destroy_rcu_head_on_stack); | ||
| 268 | |||
| 269 | struct debug_obj_descr rcuhead_debug_descr = { | ||
| 270 | .name = "rcu_head", | ||
| 271 | .fixup_init = rcuhead_fixup_init, | ||
| 272 | .fixup_activate = rcuhead_fixup_activate, | ||
| 273 | .fixup_free = rcuhead_fixup_free, | ||
| 274 | }; | ||
| 275 | EXPORT_SYMBOL_GPL(rcuhead_debug_descr); | ||
| 276 | #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | ||
