1*4882a593Smuzhiyun.. _rcu_barrier: 2*4882a593Smuzhiyun 3*4882a593SmuzhiyunRCU and Unloadable Modules 4*4882a593Smuzhiyun========================== 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun[Originally published in LWN Jan. 14, 2007: http://lwn.net/Articles/217484/] 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunRCU (read-copy update) is a synchronization mechanism that can be thought 9*4882a593Smuzhiyunof as a replacement for read-writer locking (among other things), but with 10*4882a593Smuzhiyunvery low-overhead readers that are immune to deadlock, priority inversion, 11*4882a593Smuzhiyunand unbounded latency. RCU read-side critical sections are delimited 12*4882a593Smuzhiyunby rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPT 13*4882a593Smuzhiyunkernels, generate no code whatsoever. 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunThis means that RCU writers are unaware of the presence of concurrent 16*4882a593Smuzhiyunreaders, so that RCU updates to shared data must be undertaken quite 17*4882a593Smuzhiyuncarefully, leaving an old version of the data structure in place until all 18*4882a593Smuzhiyunpre-existing readers have finished. These old versions are needed because 19*4882a593Smuzhiyunsuch readers might hold a reference to them. RCU updates can therefore be 20*4882a593Smuzhiyunrather expensive, and RCU is thus best suited for read-mostly situations. 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunHow can an RCU writer possibly determine when all readers are finished, 23*4882a593Smuzhiyungiven that readers might well leave absolutely no trace of their 24*4882a593Smuzhiyunpresence? There is a synchronize_rcu() primitive that blocks until all 25*4882a593Smuzhiyunpre-existing readers have completed. An updater wishing to delete an 26*4882a593Smuzhiyunelement p from a linked list might do the following, while holding an 27*4882a593Smuzhiyunappropriate lock, of course:: 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun list_del_rcu(p); 30*4882a593Smuzhiyun synchronize_rcu(); 31*4882a593Smuzhiyun kfree(p); 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunBut the above code cannot be used in IRQ context -- the call_rcu() 34*4882a593Smuzhiyunprimitive must be used instead. This primitive takes a pointer to an 35*4882a593Smuzhiyunrcu_head struct placed within the RCU-protected data structure and 36*4882a593Smuzhiyunanother pointer to a function that may be invoked later to free that 37*4882a593Smuzhiyunstructure. Code to delete an element p from the linked list from IRQ 38*4882a593Smuzhiyuncontext might then be as follows:: 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun list_del_rcu(p); 41*4882a593Smuzhiyun call_rcu(&p->rcu, p_callback); 42*4882a593Smuzhiyun 43*4882a593SmuzhiyunSince call_rcu() never blocks, this code can safely be used from within 44*4882a593SmuzhiyunIRQ context. The function p_callback() might be defined as follows:: 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun static void p_callback(struct rcu_head *rp) 47*4882a593Smuzhiyun { 48*4882a593Smuzhiyun struct pstruct *p = container_of(rp, struct pstruct, rcu); 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun kfree(p); 51*4882a593Smuzhiyun } 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun 54*4882a593SmuzhiyunUnloading Modules That Use call_rcu() 55*4882a593Smuzhiyun------------------------------------- 56*4882a593Smuzhiyun 57*4882a593SmuzhiyunBut what if p_callback is defined in an unloadable module? 58*4882a593Smuzhiyun 59*4882a593SmuzhiyunIf we unload the module while some RCU callbacks are pending, 60*4882a593Smuzhiyunthe CPUs executing these callbacks are going to be severely 61*4882a593Smuzhiyundisappointed when they are later invoked, as fancifully depicted at 62*4882a593Smuzhiyunhttp://lwn.net/images/ns/kernel/rcu-drop.jpg. 63*4882a593Smuzhiyun 64*4882a593SmuzhiyunWe could try placing a synchronize_rcu() in the module-exit code path, 65*4882a593Smuzhiyunbut this is not sufficient. Although synchronize_rcu() does wait for a 66*4882a593Smuzhiyungrace period to elapse, it does not wait for the callbacks to complete. 67*4882a593Smuzhiyun 68*4882a593SmuzhiyunOne might be tempted to try several back-to-back synchronize_rcu() 69*4882a593Smuzhiyuncalls, but this is still not guaranteed to work. If there is a very 70*4882a593Smuzhiyunheavy RCU-callback load, then some of the callbacks might be deferred 71*4882a593Smuzhiyunin order to allow other processing to proceed. Such deferral is required 72*4882a593Smuzhiyunin realtime kernels in order to avoid excessive scheduling latencies. 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun 75*4882a593Smuzhiyunrcu_barrier() 76*4882a593Smuzhiyun------------- 77*4882a593Smuzhiyun 78*4882a593SmuzhiyunWe instead need the rcu_barrier() primitive. Rather than waiting for 79*4882a593Smuzhiyuna grace period to elapse, rcu_barrier() waits for all outstanding RCU 80*4882a593Smuzhiyuncallbacks to complete. Please note that rcu_barrier() does **not** imply 81*4882a593Smuzhiyunsynchronize_rcu(), in particular, if there are no RCU callbacks queued 82*4882a593Smuzhiyunanywhere, rcu_barrier() is within its rights to return immediately, 83*4882a593Smuzhiyunwithout waiting for a grace period to elapse. 84*4882a593Smuzhiyun 85*4882a593SmuzhiyunPseudo-code using rcu_barrier() is as follows: 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun 1. Prevent any new RCU callbacks from being posted. 88*4882a593Smuzhiyun 2. Execute rcu_barrier(). 89*4882a593Smuzhiyun 3. Allow the module to be unloaded. 90*4882a593Smuzhiyun 91*4882a593SmuzhiyunThere is also an srcu_barrier() function for SRCU, and you of course 92*4882a593Smuzhiyunmust match the flavor of rcu_barrier() with that of call_rcu(). If your 93*4882a593Smuzhiyunmodule uses multiple flavors of call_rcu(), then it must also use multiple 94*4882a593Smuzhiyunflavors of rcu_barrier() when unloading that module. For example, if 95*4882a593Smuzhiyunit uses call_rcu(), call_srcu() on srcu_struct_1, and call_srcu() on 96*4882a593Smuzhiyunsrcu_struct_2, then the following three lines of code will be required 97*4882a593Smuzhiyunwhen unloading:: 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun 1 rcu_barrier(); 100*4882a593Smuzhiyun 2 srcu_barrier(&srcu_struct_1); 101*4882a593Smuzhiyun 3 srcu_barrier(&srcu_struct_2); 102*4882a593Smuzhiyun 103*4882a593SmuzhiyunThe rcutorture module makes use of rcu_barrier() in its exit function 104*4882a593Smuzhiyunas follows:: 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun 1 static void 107*4882a593Smuzhiyun 2 rcu_torture_cleanup(void) 108*4882a593Smuzhiyun 3 { 109*4882a593Smuzhiyun 4 int i; 110*4882a593Smuzhiyun 5 111*4882a593Smuzhiyun 6 fullstop = 1; 112*4882a593Smuzhiyun 7 if (shuffler_task != NULL) { 113*4882a593Smuzhiyun 8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task"); 114*4882a593Smuzhiyun 9 kthread_stop(shuffler_task); 115*4882a593Smuzhiyun 10 } 116*4882a593Smuzhiyun 11 shuffler_task = NULL; 117*4882a593Smuzhiyun 12 118*4882a593Smuzhiyun 13 if (writer_task != NULL) { 119*4882a593Smuzhiyun 14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); 120*4882a593Smuzhiyun 15 kthread_stop(writer_task); 121*4882a593Smuzhiyun 16 } 122*4882a593Smuzhiyun 17 writer_task = NULL; 123*4882a593Smuzhiyun 18 124*4882a593Smuzhiyun 19 if (reader_tasks != NULL) { 125*4882a593Smuzhiyun 20 for (i = 0; i < nrealreaders; i++) { 126*4882a593Smuzhiyun 21 if (reader_tasks[i] != NULL) { 127*4882a593Smuzhiyun 22 VERBOSE_PRINTK_STRING( 128*4882a593Smuzhiyun 23 "Stopping rcu_torture_reader task"); 129*4882a593Smuzhiyun 24 kthread_stop(reader_tasks[i]); 130*4882a593Smuzhiyun 25 } 131*4882a593Smuzhiyun 26 reader_tasks[i] = NULL; 132*4882a593Smuzhiyun 27 } 133*4882a593Smuzhiyun 28 kfree(reader_tasks); 134*4882a593Smuzhiyun 29 reader_tasks = NULL; 135*4882a593Smuzhiyun 30 } 136*4882a593Smuzhiyun 31 rcu_torture_current = NULL; 137*4882a593Smuzhiyun 32 138*4882a593Smuzhiyun 33 if (fakewriter_tasks != NULL) { 139*4882a593Smuzhiyun 34 for (i = 0; i < nfakewriters; i++) { 140*4882a593Smuzhiyun 35 if (fakewriter_tasks[i] != NULL) { 141*4882a593Smuzhiyun 36 VERBOSE_PRINTK_STRING( 142*4882a593Smuzhiyun 37 "Stopping rcu_torture_fakewriter task"); 143*4882a593Smuzhiyun 38 kthread_stop(fakewriter_tasks[i]); 144*4882a593Smuzhiyun 39 } 145*4882a593Smuzhiyun 40 fakewriter_tasks[i] = NULL; 146*4882a593Smuzhiyun 41 } 147*4882a593Smuzhiyun 42 kfree(fakewriter_tasks); 148*4882a593Smuzhiyun 43 fakewriter_tasks = NULL; 149*4882a593Smuzhiyun 44 } 150*4882a593Smuzhiyun 45 151*4882a593Smuzhiyun 46 if (stats_task != NULL) { 152*4882a593Smuzhiyun 47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task"); 153*4882a593Smuzhiyun 48 kthread_stop(stats_task); 154*4882a593Smuzhiyun 49 } 155*4882a593Smuzhiyun 50 stats_task = NULL; 156*4882a593Smuzhiyun 51 157*4882a593Smuzhiyun 52 /* Wait for all RCU callbacks to fire. */ 158*4882a593Smuzhiyun 53 rcu_barrier(); 159*4882a593Smuzhiyun 54 160*4882a593Smuzhiyun 55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ 161*4882a593Smuzhiyun 56 162*4882a593Smuzhiyun 57 if (cur_ops->cleanup != NULL) 163*4882a593Smuzhiyun 58 cur_ops->cleanup(); 164*4882a593Smuzhiyun 59 if (atomic_read(&n_rcu_torture_error)) 165*4882a593Smuzhiyun 60 rcu_torture_print_module_parms("End of test: FAILURE"); 166*4882a593Smuzhiyun 61 else 167*4882a593Smuzhiyun 62 rcu_torture_print_module_parms("End of test: SUCCESS"); 168*4882a593Smuzhiyun 63 } 169*4882a593Smuzhiyun 170*4882a593SmuzhiyunLine 6 sets a global variable that prevents any RCU callbacks from 171*4882a593Smuzhiyunre-posting themselves. This will not be necessary in most cases, since 172*4882a593SmuzhiyunRCU callbacks rarely include calls to call_rcu(). However, the rcutorture 173*4882a593Smuzhiyunmodule is an exception to this rule, and therefore needs to set this 174*4882a593Smuzhiyunglobal variable. 175*4882a593Smuzhiyun 176*4882a593SmuzhiyunLines 7-50 stop all the kernel tasks associated with the rcutorture 177*4882a593Smuzhiyunmodule. Therefore, once execution reaches line 53, no more rcutorture 178*4882a593SmuzhiyunRCU callbacks will be posted. The rcu_barrier() call on line 53 waits 179*4882a593Smuzhiyunfor any pre-existing callbacks to complete. 180*4882a593Smuzhiyun 181*4882a593SmuzhiyunThen lines 55-62 print status and do operation-specific cleanup, and 182*4882a593Smuzhiyunthen return, permitting the module-unload operation to be completed. 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun.. _rcubarrier_quiz_1: 185*4882a593Smuzhiyun 186*4882a593SmuzhiyunQuick Quiz #1: 187*4882a593Smuzhiyun Is there any other situation where rcu_barrier() might 188*4882a593Smuzhiyun be required? 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun:ref:`Answer to Quick Quiz #1 <answer_rcubarrier_quiz_1>` 191*4882a593Smuzhiyun 192*4882a593SmuzhiyunYour module might have additional complications. For example, if your 193*4882a593Smuzhiyunmodule invokes call_rcu() from timers, you will need to first cancel all 194*4882a593Smuzhiyunthe timers, and only then invoke rcu_barrier() to wait for any remaining 195*4882a593SmuzhiyunRCU callbacks to complete. 196*4882a593Smuzhiyun 197*4882a593SmuzhiyunOf course, if you module uses call_rcu(), you will need to invoke 198*4882a593Smuzhiyunrcu_barrier() before unloading. Similarly, if your module uses 199*4882a593Smuzhiyuncall_srcu(), you will need to invoke srcu_barrier() before unloading, 200*4882a593Smuzhiyunand on the same srcu_struct structure. If your module uses call_rcu() 201*4882a593Smuzhiyun**and** call_srcu(), then you will need to invoke rcu_barrier() **and** 202*4882a593Smuzhiyunsrcu_barrier(). 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun 205*4882a593SmuzhiyunImplementing rcu_barrier() 206*4882a593Smuzhiyun-------------------------- 207*4882a593Smuzhiyun 208*4882a593SmuzhiyunDipankar Sarma's implementation of rcu_barrier() makes use of the fact 209*4882a593Smuzhiyunthat RCU callbacks are never reordered once queued on one of the per-CPU 210*4882a593Smuzhiyunqueues. His implementation queues an RCU callback on each of the per-CPU 211*4882a593Smuzhiyuncallback queues, and then waits until they have all started executing, at 212*4882a593Smuzhiyunwhich point, all earlier RCU callbacks are guaranteed to have completed. 213*4882a593Smuzhiyun 214*4882a593SmuzhiyunThe original code for rcu_barrier() was as follows:: 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun 1 void rcu_barrier(void) 217*4882a593Smuzhiyun 2 { 218*4882a593Smuzhiyun 3 BUG_ON(in_interrupt()); 219*4882a593Smuzhiyun 4 /* Take cpucontrol mutex to protect against CPU hotplug */ 220*4882a593Smuzhiyun 5 mutex_lock(&rcu_barrier_mutex); 221*4882a593Smuzhiyun 6 init_completion(&rcu_barrier_completion); 222*4882a593Smuzhiyun 7 atomic_set(&rcu_barrier_cpu_count, 0); 223*4882a593Smuzhiyun 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1); 224*4882a593Smuzhiyun 9 wait_for_completion(&rcu_barrier_completion); 225*4882a593Smuzhiyun 10 mutex_unlock(&rcu_barrier_mutex); 226*4882a593Smuzhiyun 11 } 227*4882a593Smuzhiyun 228*4882a593SmuzhiyunLine 3 verifies that the caller is in process context, and lines 5 and 10 229*4882a593Smuzhiyunuse rcu_barrier_mutex to ensure that only one rcu_barrier() is using the 230*4882a593Smuzhiyunglobal completion and counters at a time, which are initialized on lines 231*4882a593Smuzhiyun6 and 7. Line 8 causes each CPU to invoke rcu_barrier_func(), which is 232*4882a593Smuzhiyunshown below. Note that the final "1" in on_each_cpu()'s argument list 233*4882a593Smuzhiyunensures that all the calls to rcu_barrier_func() will have completed 234*4882a593Smuzhiyunbefore on_each_cpu() returns. Line 9 then waits for the completion. 235*4882a593Smuzhiyun 236*4882a593SmuzhiyunThis code was rewritten in 2008 and several times thereafter, but this 237*4882a593Smuzhiyunstill gives the general idea. 238*4882a593Smuzhiyun 239*4882a593SmuzhiyunThe rcu_barrier_func() runs on each CPU, where it invokes call_rcu() 240*4882a593Smuzhiyunto post an RCU callback, as follows:: 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun 1 static void rcu_barrier_func(void *notused) 243*4882a593Smuzhiyun 2 { 244*4882a593Smuzhiyun 3 int cpu = smp_processor_id(); 245*4882a593Smuzhiyun 4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu); 246*4882a593Smuzhiyun 5 struct rcu_head *head; 247*4882a593Smuzhiyun 6 248*4882a593Smuzhiyun 7 head = &rdp->barrier; 249*4882a593Smuzhiyun 8 atomic_inc(&rcu_barrier_cpu_count); 250*4882a593Smuzhiyun 9 call_rcu(head, rcu_barrier_callback); 251*4882a593Smuzhiyun 10 } 252*4882a593Smuzhiyun 253*4882a593SmuzhiyunLines 3 and 4 locate RCU's internal per-CPU rcu_data structure, 254*4882a593Smuzhiyunwhich contains the struct rcu_head that needed for the later call to 255*4882a593Smuzhiyuncall_rcu(). Line 7 picks up a pointer to this struct rcu_head, and line 256*4882a593Smuzhiyun8 increments a global counter. This counter will later be decremented 257*4882a593Smuzhiyunby the callback. Line 9 then registers the rcu_barrier_callback() on 258*4882a593Smuzhiyunthe current CPU's queue. 259*4882a593Smuzhiyun 260*4882a593SmuzhiyunThe rcu_barrier_callback() function simply atomically decrements the 261*4882a593Smuzhiyunrcu_barrier_cpu_count variable and finalizes the completion when it 262*4882a593Smuzhiyunreaches zero, as follows:: 263*4882a593Smuzhiyun 264*4882a593Smuzhiyun 1 static void rcu_barrier_callback(struct rcu_head *notused) 265*4882a593Smuzhiyun 2 { 266*4882a593Smuzhiyun 3 if (atomic_dec_and_test(&rcu_barrier_cpu_count)) 267*4882a593Smuzhiyun 4 complete(&rcu_barrier_completion); 268*4882a593Smuzhiyun 5 } 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun.. _rcubarrier_quiz_2: 271*4882a593Smuzhiyun 272*4882a593SmuzhiyunQuick Quiz #2: 273*4882a593Smuzhiyun What happens if CPU 0's rcu_barrier_func() executes 274*4882a593Smuzhiyun immediately (thus incrementing rcu_barrier_cpu_count to the 275*4882a593Smuzhiyun value one), but the other CPU's rcu_barrier_func() invocations 276*4882a593Smuzhiyun are delayed for a full grace period? Couldn't this result in 277*4882a593Smuzhiyun rcu_barrier() returning prematurely? 278*4882a593Smuzhiyun 279*4882a593Smuzhiyun:ref:`Answer to Quick Quiz #2 <answer_rcubarrier_quiz_2>` 280*4882a593Smuzhiyun 281*4882a593SmuzhiyunThe current rcu_barrier() implementation is more complex, due to the need 282*4882a593Smuzhiyunto avoid disturbing idle CPUs (especially on battery-powered systems) 283*4882a593Smuzhiyunand the need to minimally disturb non-idle CPUs in real-time systems. 284*4882a593SmuzhiyunHowever, the code above illustrates the concepts. 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun 287*4882a593Smuzhiyunrcu_barrier() Summary 288*4882a593Smuzhiyun--------------------- 289*4882a593Smuzhiyun 290*4882a593SmuzhiyunThe rcu_barrier() primitive has seen relatively little use, since most 291*4882a593Smuzhiyuncode using RCU is in the core kernel rather than in modules. However, if 292*4882a593Smuzhiyunyou are using RCU from an unloadable module, you need to use rcu_barrier() 293*4882a593Smuzhiyunso that your module may be safely unloaded. 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun 296*4882a593SmuzhiyunAnswers to Quick Quizzes 297*4882a593Smuzhiyun------------------------ 298*4882a593Smuzhiyun 299*4882a593Smuzhiyun.. _answer_rcubarrier_quiz_1: 300*4882a593Smuzhiyun 301*4882a593SmuzhiyunQuick Quiz #1: 302*4882a593Smuzhiyun Is there any other situation where rcu_barrier() might 303*4882a593Smuzhiyun be required? 304*4882a593Smuzhiyun 305*4882a593SmuzhiyunAnswer: Interestingly enough, rcu_barrier() was not originally 306*4882a593Smuzhiyun implemented for module unloading. Nikita Danilov was using 307*4882a593Smuzhiyun RCU in a filesystem, which resulted in a similar situation at 308*4882a593Smuzhiyun filesystem-unmount time. Dipankar Sarma coded up rcu_barrier() 309*4882a593Smuzhiyun in response, so that Nikita could invoke it during the 310*4882a593Smuzhiyun filesystem-unmount process. 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun Much later, yours truly hit the RCU module-unload problem when 313*4882a593Smuzhiyun implementing rcutorture, and found that rcu_barrier() solves 314*4882a593Smuzhiyun this problem as well. 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun:ref:`Back to Quick Quiz #1 <rcubarrier_quiz_1>` 317*4882a593Smuzhiyun 318*4882a593Smuzhiyun.. _answer_rcubarrier_quiz_2: 319*4882a593Smuzhiyun 320*4882a593SmuzhiyunQuick Quiz #2: 321*4882a593Smuzhiyun What happens if CPU 0's rcu_barrier_func() executes 322*4882a593Smuzhiyun immediately (thus incrementing rcu_barrier_cpu_count to the 323*4882a593Smuzhiyun value one), but the other CPU's rcu_barrier_func() invocations 324*4882a593Smuzhiyun are delayed for a full grace period? Couldn't this result in 325*4882a593Smuzhiyun rcu_barrier() returning prematurely? 326*4882a593Smuzhiyun 327*4882a593SmuzhiyunAnswer: This cannot happen. The reason is that on_each_cpu() has its last 328*4882a593Smuzhiyun argument, the wait flag, set to "1". This flag is passed through 329*4882a593Smuzhiyun to smp_call_function() and further to smp_call_function_on_cpu(), 330*4882a593Smuzhiyun causing this latter to spin until the cross-CPU invocation of 331*4882a593Smuzhiyun rcu_barrier_func() has completed. This by itself would prevent 332*4882a593Smuzhiyun a grace period from completing on non-CONFIG_PREEMPT kernels, 333*4882a593Smuzhiyun since each CPU must undergo a context switch (or other quiescent 334*4882a593Smuzhiyun state) before the grace period can complete. However, this is 335*4882a593Smuzhiyun of no use in CONFIG_PREEMPT kernels. 336*4882a593Smuzhiyun 337*4882a593Smuzhiyun Therefore, on_each_cpu() disables preemption across its call 338*4882a593Smuzhiyun to smp_call_function() and also across the local call to 339*4882a593Smuzhiyun rcu_barrier_func(). This prevents the local CPU from context 340*4882a593Smuzhiyun switching, again preventing grace periods from completing. This 341*4882a593Smuzhiyun means that all CPUs have executed rcu_barrier_func() before 342*4882a593Smuzhiyun the first rcu_barrier_callback() can possibly execute, in turn 343*4882a593Smuzhiyun preventing rcu_barrier_cpu_count from prematurely reaching zero. 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun Currently, -rt implementations of RCU keep but a single global 346*4882a593Smuzhiyun queue for RCU callbacks, and thus do not suffer from this 347*4882a593Smuzhiyun problem. However, when the -rt RCU eventually does have per-CPU 348*4882a593Smuzhiyun callback queues, things will have to change. One simple change 349*4882a593Smuzhiyun is to add an rcu_read_lock() before line 8 of rcu_barrier() 350*4882a593Smuzhiyun and an rcu_read_unlock() after line 8 of this same function. If 351*4882a593Smuzhiyun you can think of a better change, please let me know! 352*4882a593Smuzhiyun 353*4882a593Smuzhiyun:ref:`Back to Quick Quiz #2 <rcubarrier_quiz_2>` 354