diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/rcupdate.h | 83 | ||||
| -rw-r--r-- | include/linux/rcutiny.h | 10 | ||||
| -rw-r--r-- | include/linux/rcutree.h | 19 | ||||
| -rw-r--r-- | include/linux/sched.h | 3 | ||||
| -rw-r--r-- | include/linux/srcu.h | 15 |
5 files changed, 117 insertions, 13 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 81c04f4348ec..937217425c47 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -190,6 +190,33 @@ extern void rcu_idle_exit(void); | |||
| 190 | extern void rcu_irq_enter(void); | 190 | extern void rcu_irq_enter(void); |
| 191 | extern void rcu_irq_exit(void); | 191 | extern void rcu_irq_exit(void); |
| 192 | 192 | ||
| 193 | /** | ||
| 194 | * RCU_NONIDLE - Indicate idle-loop code that needs RCU readers | ||
| 195 | * @a: Code that RCU needs to pay attention to. | ||
| 196 | * | ||
| 197 | * RCU, RCU-bh, and RCU-sched read-side critical sections are forbidden | ||
| 198 | * in the inner idle loop, that is, between the rcu_idle_enter() and | ||
| 199 | * the rcu_idle_exit() -- RCU will happily ignore any such read-side | ||
| 200 | * critical sections. However, things like powertop need tracepoints | ||
| 201 | * in the inner idle loop. | ||
| 202 | * | ||
| 203 | * This macro provides the way out: RCU_NONIDLE(do_something_with_RCU()) | ||
| 204 | * will tell RCU that it needs to pay attending, invoke its argument | ||
| 205 | * (in this example, a call to the do_something_with_RCU() function), | ||
| 206 | * and then tell RCU to go back to ignoring this CPU. It is permissible | ||
| 207 | * to nest RCU_NONIDLE() wrappers, but the nesting level is currently | ||
| 208 | * quite limited. If deeper nesting is required, it will be necessary | ||
| 209 | * to adjust DYNTICK_TASK_NESTING_VALUE accordingly. | ||
| 210 | * | ||
| 211 | * This macro may be used from process-level code only. | ||
| 212 | */ | ||
| 213 | #define RCU_NONIDLE(a) \ | ||
| 214 | do { \ | ||
| 215 | rcu_idle_exit(); \ | ||
| 216 | do { a; } while (0); \ | ||
| 217 | rcu_idle_enter(); \ | ||
| 218 | } while (0) | ||
| 219 | |||
| 193 | /* | 220 | /* |
| 194 | * Infrastructure to implement the synchronize_() primitives in | 221 | * Infrastructure to implement the synchronize_() primitives in |
| 195 | * TREE_RCU and rcu_barrier_() primitives in TINY_RCU. | 222 | * TREE_RCU and rcu_barrier_() primitives in TINY_RCU. |
| @@ -226,6 +253,15 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head) | |||
| 226 | } | 253 | } |
| 227 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | 254 | #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
| 228 | 255 | ||
| 256 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) | ||
| 257 | bool rcu_lockdep_current_cpu_online(void); | ||
| 258 | #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */ | ||
| 259 | static inline bool rcu_lockdep_current_cpu_online(void) | ||
| 260 | { | ||
| 261 | return 1; | ||
| 262 | } | ||
| 263 | #endif /* #else #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */ | ||
| 264 | |||
| 229 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 265 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 230 | 266 | ||
| 231 | #ifdef CONFIG_PROVE_RCU | 267 | #ifdef CONFIG_PROVE_RCU |
| @@ -239,13 +275,11 @@ static inline int rcu_is_cpu_idle(void) | |||
| 239 | 275 | ||
| 240 | static inline void rcu_lock_acquire(struct lockdep_map *map) | 276 | static inline void rcu_lock_acquire(struct lockdep_map *map) |
| 241 | { | 277 | { |
| 242 | WARN_ON_ONCE(rcu_is_cpu_idle()); | ||
| 243 | lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_); | 278 | lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_); |
| 244 | } | 279 | } |
| 245 | 280 | ||
| 246 | static inline void rcu_lock_release(struct lockdep_map *map) | 281 | static inline void rcu_lock_release(struct lockdep_map *map) |
| 247 | { | 282 | { |
| 248 | WARN_ON_ONCE(rcu_is_cpu_idle()); | ||
| 249 | lock_release(map, 1, _THIS_IP_); | 283 | lock_release(map, 1, _THIS_IP_); |
| 250 | } | 284 | } |
| 251 | 285 | ||
| @@ -270,6 +304,9 @@ extern int debug_lockdep_rcu_enabled(void); | |||
| 270 | * occur in the same context, for example, it is illegal to invoke | 304 | * occur in the same context, for example, it is illegal to invoke |
| 271 | * rcu_read_unlock() in process context if the matching rcu_read_lock() | 305 | * rcu_read_unlock() in process context if the matching rcu_read_lock() |
| 272 | * was invoked from within an irq handler. | 306 | * was invoked from within an irq handler. |
| 307 | * | ||
| 308 | * Note that rcu_read_lock() is disallowed if the CPU is either idle or | ||
| 309 | * offline from an RCU perspective, so check for those as well. | ||
| 273 | */ | 310 | */ |
| 274 | static inline int rcu_read_lock_held(void) | 311 | static inline int rcu_read_lock_held(void) |
| 275 | { | 312 | { |
| @@ -277,6 +314,8 @@ static inline int rcu_read_lock_held(void) | |||
| 277 | return 1; | 314 | return 1; |
| 278 | if (rcu_is_cpu_idle()) | 315 | if (rcu_is_cpu_idle()) |
| 279 | return 0; | 316 | return 0; |
| 317 | if (!rcu_lockdep_current_cpu_online()) | ||
| 318 | return 0; | ||
| 280 | return lock_is_held(&rcu_lock_map); | 319 | return lock_is_held(&rcu_lock_map); |
| 281 | } | 320 | } |
| 282 | 321 | ||
| @@ -313,6 +352,9 @@ extern int rcu_read_lock_bh_held(void); | |||
| 313 | * notice an extended quiescent state to other CPUs that started a grace | 352 | * notice an extended quiescent state to other CPUs that started a grace |
| 314 | * period. Otherwise we would delay any grace period as long as we run in | 353 | * period. Otherwise we would delay any grace period as long as we run in |
| 315 | * the idle task. | 354 | * the idle task. |
| 355 | * | ||
| 356 | * Similarly, we avoid claiming an SRCU read lock held if the current | ||
| 357 | * CPU is offline. | ||
| 316 | */ | 358 | */ |
| 317 | #ifdef CONFIG_PREEMPT_COUNT | 359 | #ifdef CONFIG_PREEMPT_COUNT |
| 318 | static inline int rcu_read_lock_sched_held(void) | 360 | static inline int rcu_read_lock_sched_held(void) |
| @@ -323,6 +365,8 @@ static inline int rcu_read_lock_sched_held(void) | |||
| 323 | return 1; | 365 | return 1; |
| 324 | if (rcu_is_cpu_idle()) | 366 | if (rcu_is_cpu_idle()) |
| 325 | return 0; | 367 | return 0; |
| 368 | if (!rcu_lockdep_current_cpu_online()) | ||
| 369 | return 0; | ||
| 326 | if (debug_locks) | 370 | if (debug_locks) |
| 327 | lockdep_opinion = lock_is_held(&rcu_sched_lock_map); | 371 | lockdep_opinion = lock_is_held(&rcu_sched_lock_map); |
| 328 | return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); | 372 | return lockdep_opinion || preempt_count() != 0 || irqs_disabled(); |
| @@ -381,8 +425,22 @@ extern int rcu_my_thread_group_empty(void); | |||
| 381 | } \ | 425 | } \ |
| 382 | } while (0) | 426 | } while (0) |
| 383 | 427 | ||
| 428 | #if defined(CONFIG_PROVE_RCU) && !defined(CONFIG_PREEMPT_RCU) | ||
| 429 | static inline void rcu_preempt_sleep_check(void) | ||
| 430 | { | ||
| 431 | rcu_lockdep_assert(!lock_is_held(&rcu_lock_map), | ||
| 432 | "Illegal context switch in RCU read-side " | ||
| 433 | "critical section"); | ||
| 434 | } | ||
| 435 | #else /* #ifdef CONFIG_PROVE_RCU */ | ||
| 436 | static inline void rcu_preempt_sleep_check(void) | ||
| 437 | { | ||
| 438 | } | ||
| 439 | #endif /* #else #ifdef CONFIG_PROVE_RCU */ | ||
| 440 | |||
| 384 | #define rcu_sleep_check() \ | 441 | #define rcu_sleep_check() \ |
| 385 | do { \ | 442 | do { \ |
| 443 | rcu_preempt_sleep_check(); \ | ||
| 386 | rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ | 444 | rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ |
| 387 | "Illegal context switch in RCU-bh" \ | 445 | "Illegal context switch in RCU-bh" \ |
| 388 | " read-side critical section"); \ | 446 | " read-side critical section"); \ |
| @@ -470,6 +528,13 @@ extern int rcu_my_thread_group_empty(void); | |||
| 470 | * NULL. Although rcu_access_pointer() may also be used in cases where | 528 | * NULL. Although rcu_access_pointer() may also be used in cases where |
| 471 | * update-side locks prevent the value of the pointer from changing, you | 529 | * update-side locks prevent the value of the pointer from changing, you |
| 472 | * should instead use rcu_dereference_protected() for this use case. | 530 | * should instead use rcu_dereference_protected() for this use case. |
| 531 | * | ||
| 532 | * It is also permissible to use rcu_access_pointer() when read-side | ||
| 533 | * access to the pointer was removed at least one grace period ago, as | ||
| 534 | * is the case in the context of the RCU callback that is freeing up | ||
| 535 | * the data, or after a synchronize_rcu() returns. This can be useful | ||
| 536 | * when tearing down multi-linked structures after a grace period | ||
| 537 | * has elapsed. | ||
| 473 | */ | 538 | */ |
| 474 | #define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu) | 539 | #define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu) |
| 475 | 540 | ||
| @@ -659,6 +724,8 @@ static inline void rcu_read_lock(void) | |||
| 659 | __rcu_read_lock(); | 724 | __rcu_read_lock(); |
| 660 | __acquire(RCU); | 725 | __acquire(RCU); |
| 661 | rcu_lock_acquire(&rcu_lock_map); | 726 | rcu_lock_acquire(&rcu_lock_map); |
| 727 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 728 | "rcu_read_lock() used illegally while idle"); | ||
| 662 | } | 729 | } |
| 663 | 730 | ||
| 664 | /* | 731 | /* |
| @@ -678,6 +745,8 @@ static inline void rcu_read_lock(void) | |||
| 678 | */ | 745 | */ |
| 679 | static inline void rcu_read_unlock(void) | 746 | static inline void rcu_read_unlock(void) |
| 680 | { | 747 | { |
| 748 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 749 | "rcu_read_unlock() used illegally while idle"); | ||
| 681 | rcu_lock_release(&rcu_lock_map); | 750 | rcu_lock_release(&rcu_lock_map); |
| 682 | __release(RCU); | 751 | __release(RCU); |
| 683 | __rcu_read_unlock(); | 752 | __rcu_read_unlock(); |
| @@ -705,6 +774,8 @@ static inline void rcu_read_lock_bh(void) | |||
| 705 | local_bh_disable(); | 774 | local_bh_disable(); |
| 706 | __acquire(RCU_BH); | 775 | __acquire(RCU_BH); |
| 707 | rcu_lock_acquire(&rcu_bh_lock_map); | 776 | rcu_lock_acquire(&rcu_bh_lock_map); |
| 777 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 778 | "rcu_read_lock_bh() used illegally while idle"); | ||
| 708 | } | 779 | } |
| 709 | 780 | ||
| 710 | /* | 781 | /* |
| @@ -714,6 +785,8 @@ static inline void rcu_read_lock_bh(void) | |||
| 714 | */ | 785 | */ |
| 715 | static inline void rcu_read_unlock_bh(void) | 786 | static inline void rcu_read_unlock_bh(void) |
| 716 | { | 787 | { |
| 788 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 789 | "rcu_read_unlock_bh() used illegally while idle"); | ||
| 717 | rcu_lock_release(&rcu_bh_lock_map); | 790 | rcu_lock_release(&rcu_bh_lock_map); |
| 718 | __release(RCU_BH); | 791 | __release(RCU_BH); |
| 719 | local_bh_enable(); | 792 | local_bh_enable(); |
| @@ -737,6 +810,8 @@ static inline void rcu_read_lock_sched(void) | |||
| 737 | preempt_disable(); | 810 | preempt_disable(); |
| 738 | __acquire(RCU_SCHED); | 811 | __acquire(RCU_SCHED); |
| 739 | rcu_lock_acquire(&rcu_sched_lock_map); | 812 | rcu_lock_acquire(&rcu_sched_lock_map); |
| 813 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 814 | "rcu_read_lock_sched() used illegally while idle"); | ||
| 740 | } | 815 | } |
| 741 | 816 | ||
| 742 | /* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */ | 817 | /* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */ |
| @@ -753,6 +828,8 @@ static inline notrace void rcu_read_lock_sched_notrace(void) | |||
| 753 | */ | 828 | */ |
| 754 | static inline void rcu_read_unlock_sched(void) | 829 | static inline void rcu_read_unlock_sched(void) |
| 755 | { | 830 | { |
| 831 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 832 | "rcu_read_unlock_sched() used illegally while idle"); | ||
| 756 | rcu_lock_release(&rcu_sched_lock_map); | 833 | rcu_lock_release(&rcu_sched_lock_map); |
| 757 | __release(RCU_SCHED); | 834 | __release(RCU_SCHED); |
| 758 | preempt_enable(); | 835 | preempt_enable(); |
| @@ -841,7 +918,7 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset) | |||
| 841 | /* See the kfree_rcu() header comment. */ | 918 | /* See the kfree_rcu() header comment. */ |
| 842 | BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); | 919 | BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); |
| 843 | 920 | ||
| 844 | call_rcu(head, (rcu_callback)offset); | 921 | kfree_call_rcu(head, (rcu_callback)offset); |
| 845 | } | 922 | } |
| 846 | 923 | ||
| 847 | /** | 924 | /** |
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 00b7a5e493d2..e93df77176d1 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h | |||
| @@ -27,13 +27,9 @@ | |||
| 27 | 27 | ||
| 28 | #include <linux/cache.h> | 28 | #include <linux/cache.h> |
| 29 | 29 | ||
| 30 | #ifdef CONFIG_RCU_BOOST | ||
| 31 | static inline void rcu_init(void) | 30 | static inline void rcu_init(void) |
| 32 | { | 31 | { |
| 33 | } | 32 | } |
| 34 | #else /* #ifdef CONFIG_RCU_BOOST */ | ||
| 35 | void rcu_init(void); | ||
| 36 | #endif /* #else #ifdef CONFIG_RCU_BOOST */ | ||
| 37 | 33 | ||
| 38 | static inline void rcu_barrier_bh(void) | 34 | static inline void rcu_barrier_bh(void) |
| 39 | { | 35 | { |
| @@ -83,6 +79,12 @@ static inline void synchronize_sched_expedited(void) | |||
| 83 | synchronize_sched(); | 79 | synchronize_sched(); |
| 84 | } | 80 | } |
| 85 | 81 | ||
| 82 | static inline void kfree_call_rcu(struct rcu_head *head, | ||
| 83 | void (*func)(struct rcu_head *rcu)) | ||
| 84 | { | ||
| 85 | call_rcu(head, func); | ||
| 86 | } | ||
| 87 | |||
| 86 | #ifdef CONFIG_TINY_RCU | 88 | #ifdef CONFIG_TINY_RCU |
| 87 | 89 | ||
| 88 | static inline void rcu_preempt_note_context_switch(void) | 90 | static inline void rcu_preempt_note_context_switch(void) |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 67458468f1a8..e8ee5dd0854c 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
| @@ -61,6 +61,24 @@ extern void synchronize_rcu_bh(void); | |||
| 61 | extern void synchronize_sched_expedited(void); | 61 | extern void synchronize_sched_expedited(void); |
| 62 | extern void synchronize_rcu_expedited(void); | 62 | extern void synchronize_rcu_expedited(void); |
| 63 | 63 | ||
| 64 | void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); | ||
| 65 | |||
| 66 | /** | ||
| 67 | * synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period | ||
| 68 | * | ||
| 69 | * Wait for an RCU-bh grace period to elapse, but use a "big hammer" | ||
| 70 | * approach to force the grace period to end quickly. This consumes | ||
| 71 | * significant time on all CPUs and is unfriendly to real-time workloads, | ||
| 72 | * so is thus not recommended for any sort of common-case code. In fact, | ||
| 73 | * if you are using synchronize_rcu_bh_expedited() in a loop, please | ||
| 74 | * restructure your code to batch your updates, and then use a single | ||
| 75 | * synchronize_rcu_bh() instead. | ||
| 76 | * | ||
| 77 | * Note that it is illegal to call this function while holding any lock | ||
| 78 | * that is acquired by a CPU-hotplug notifier. And yes, it is also illegal | ||
| 79 | * to call this function from a CPU-hotplug notifier. Failing to observe | ||
| 80 | * these restriction will result in deadlock. | ||
| 81 | */ | ||
| 64 | static inline void synchronize_rcu_bh_expedited(void) | 82 | static inline void synchronize_rcu_bh_expedited(void) |
| 65 | { | 83 | { |
| 66 | synchronize_sched_expedited(); | 84 | synchronize_sched_expedited(); |
| @@ -83,6 +101,7 @@ extern void rcu_sched_force_quiescent_state(void); | |||
| 83 | /* A context switch is a grace period for RCU-sched and RCU-bh. */ | 101 | /* A context switch is a grace period for RCU-sched and RCU-bh. */ |
| 84 | static inline int rcu_blocking_is_gp(void) | 102 | static inline int rcu_blocking_is_gp(void) |
| 85 | { | 103 | { |
| 104 | might_sleep(); /* Check for RCU read-side critical section. */ | ||
| 86 | return num_online_cpus() == 1; | 105 | return num_online_cpus() == 1; |
| 87 | } | 106 | } |
| 88 | 107 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 0657368bd78f..f58889b8a608 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1863,8 +1863,7 @@ extern void task_clear_jobctl_pending(struct task_struct *task, | |||
| 1863 | #ifdef CONFIG_PREEMPT_RCU | 1863 | #ifdef CONFIG_PREEMPT_RCU |
| 1864 | 1864 | ||
| 1865 | #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */ | 1865 | #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */ |
| 1866 | #define RCU_READ_UNLOCK_BOOSTED (1 << 1) /* boosted while in RCU read-side. */ | 1866 | #define RCU_READ_UNLOCK_NEED_QS (1 << 1) /* RCU core needs CPU response. */ |
| 1867 | #define RCU_READ_UNLOCK_NEED_QS (1 << 2) /* RCU core needs CPU response. */ | ||
| 1868 | 1867 | ||
| 1869 | static inline void rcu_copy_process(struct task_struct *p) | 1868 | static inline void rcu_copy_process(struct task_struct *p) |
| 1870 | { | 1869 | { |
diff --git a/include/linux/srcu.h b/include/linux/srcu.h index e1b005918bbb..d3d5fa54f25e 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h | |||
| @@ -99,15 +99,18 @@ long srcu_batches_completed(struct srcu_struct *sp); | |||
| 99 | * power mode. This way we can notice an extended quiescent state to | 99 | * power mode. This way we can notice an extended quiescent state to |
| 100 | * other CPUs that started a grace period. Otherwise we would delay any | 100 | * other CPUs that started a grace period. Otherwise we would delay any |
| 101 | * grace period as long as we run in the idle task. | 101 | * grace period as long as we run in the idle task. |
| 102 | * | ||
| 103 | * Similarly, we avoid claiming an SRCU read lock held if the current | ||
| 104 | * CPU is offline. | ||
| 102 | */ | 105 | */ |
| 103 | static inline int srcu_read_lock_held(struct srcu_struct *sp) | 106 | static inline int srcu_read_lock_held(struct srcu_struct *sp) |
| 104 | { | 107 | { |
| 105 | if (rcu_is_cpu_idle()) | ||
| 106 | return 0; | ||
| 107 | |||
| 108 | if (!debug_lockdep_rcu_enabled()) | 108 | if (!debug_lockdep_rcu_enabled()) |
| 109 | return 1; | 109 | return 1; |
| 110 | 110 | if (rcu_is_cpu_idle()) | |
| 111 | return 0; | ||
| 112 | if (!rcu_lockdep_current_cpu_online()) | ||
| 113 | return 0; | ||
| 111 | return lock_is_held(&sp->dep_map); | 114 | return lock_is_held(&sp->dep_map); |
| 112 | } | 115 | } |
| 113 | 116 | ||
| @@ -169,6 +172,8 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp) | |||
| 169 | int retval = __srcu_read_lock(sp); | 172 | int retval = __srcu_read_lock(sp); |
| 170 | 173 | ||
| 171 | rcu_lock_acquire(&(sp)->dep_map); | 174 | rcu_lock_acquire(&(sp)->dep_map); |
| 175 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 176 | "srcu_read_lock() used illegally while idle"); | ||
| 172 | return retval; | 177 | return retval; |
| 173 | } | 178 | } |
| 174 | 179 | ||
| @@ -182,6 +187,8 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp) | |||
| 182 | static inline void srcu_read_unlock(struct srcu_struct *sp, int idx) | 187 | static inline void srcu_read_unlock(struct srcu_struct *sp, int idx) |
| 183 | __releases(sp) | 188 | __releases(sp) |
| 184 | { | 189 | { |
| 190 | rcu_lockdep_assert(!rcu_is_cpu_idle(), | ||
| 191 | "srcu_read_unlock() used illegally while idle"); | ||
| 185 | rcu_lock_release(&(sp)->dep_map); | 192 | rcu_lock_release(&(sp)->dep_map); |
| 186 | __srcu_read_unlock(sp, idx); | 193 | __srcu_read_unlock(sp, idx); |
| 187 | } | 194 | } |
