€•'jŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ/translations/zh_CN/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/zh_TW/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/it_IT/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/ja_JP/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/ko_KR/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/pt_BR/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/sp_SP/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒtarget”“”)”}”(hŒ .. _up_doc:”h]”h}”(h]”h ]”h"]”h$]”h&]”Œrefid”Œup-doc”uh1hµh´Khhh²hh³Œ4/var/lib/git/docbuild/linux/Documentation/RCU/UP.rst”ubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒRCU on Uniprocessor Systems”h]”hŒRCU on Uniprocessor Systems”…””}”(hhËh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhhÆh²hh³hÃh´KubhŒ paragraph”“”)”}”(hXÿA common misconception is that, on UP systems, the call_rcu() primitive may immediately invoke its function. The basis of this misconception is that since there is only one CPU, it should not be necessary to wait for anything else to get done, since there are no other CPUs for anything else to be happening on. Although this approach will *sort of* work a surprising amount of the time, it is a very bad idea in general. This document presents three examples that demonstrate exactly how bad an idea this is.”h]”(hXVA common misconception is that, on UP systems, the call_rcu() primitive may immediately invoke its function. The basis of this misconception is that since there is only one CPU, it should not be necessary to wait for anything else to get done, since there are no other CPUs for anything else to be happening on. Although this approach will ”…””}”(hhÛh²hh³Nh´NubhŒemphasis”“”)”}”(hŒ *sort of*”h]”hŒsort of”…””}”(hhåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhhÛubhŒ  work a surprising amount of the time, it is a very bad idea in general. This document presents three examples that demonstrate exactly how bad an idea this is.”…””}”(hhÛh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KhhÆh²hubhÅ)”}”(hhh]”(hÊ)”}”(hŒExample 1: softirq Suicide”h]”hŒExample 1: softirq Suicide”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhhýh²hh³hÃh´KubhÚ)”}”(hXvSuppose that an RCU-based algorithm scans a linked list containing elements A, B, and C in process context, and can delete elements from this same list in softirq context. Suppose that the process-context scan is referencing element B when it is interrupted by softirq processing, which deletes element B, and then invokes call_rcu() to free element B after a grace period.”h]”hXvSuppose that an RCU-based algorithm scans a linked list containing elements A, B, and C in process context, and can delete elements from this same list in softirq context. Suppose that the process-context scan is referencing element B when it is interrupted by softirq processing, which deletes element B, and then invokes call_rcu() to free element B after a grace period.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Khhýh²hubhÚ)”}”(hŒæNow, if call_rcu() were to directly invoke its arguments, then upon return from softirq, the list scan would find itself referencing a newly freed element B. This situation can greatly decrease the life expectancy of your kernel.”h]”hŒæNow, if call_rcu() were to directly invoke its arguments, then upon return from softirq, the list scan would find itself referencing a newly freed element B. This situation can greatly decrease the life expectancy of your kernel.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Khhýh²hubhÚ)”}”(hŒWThis same problem can occur if call_rcu() is invoked from a hardware interrupt handler.”h]”hŒWThis same problem can occur if call_rcu() is invoked from a hardware interrupt handler.”…””}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Khhýh²hubeh}”(h]”Œexample-1-softirq-suicide”ah ]”h"]”Œexample 1: softirq suicide”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´KubhÅ)”}”(hhh]”(hÊ)”}”(hŒ!Example 2: Function-Call Fatality”h]”hŒ!Example 2: Function-Call Fatality”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj@h²hh³hÃh´K"ubhÚ)”}”(hŒÕOf course, one could avert the suicide described in the preceding example by having call_rcu() directly invoke its arguments only if it was called from process context. However, this can fail in a similar manner.”h]”hŒÕOf course, one could avert the suicide described in the preceding example by having call_rcu() directly invoke its arguments only if it was called from process context. However, this can fail in a similar manner.”…””}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K$hj@h²hubhÚ)”}”(hXÈSuppose that an RCU-based algorithm again scans a linked list containing elements A, B, and C in process context, but that it invokes a function on each element as it is scanned. Suppose further that this function deletes element B from the list, then passes it to call_rcu() for deferred freeing. This may be a bit unconventional, but it is perfectly legal RCU usage, since call_rcu() must wait for a grace period to elapse. Therefore, in this case, allowing call_rcu() to immediately invoke its arguments would cause it to fail to make the fundamental guarantee underlying RCU, namely that call_rcu() defers invoking its arguments until all RCU read-side critical sections currently executing have completed.”h]”hXÈSuppose that an RCU-based algorithm again scans a linked list containing elements A, B, and C in process context, but that it invokes a function on each element as it is scanned. Suppose further that this function deletes element B from the list, then passes it to call_rcu() for deferred freeing. This may be a bit unconventional, but it is perfectly legal RCU usage, since call_rcu() must wait for a grace period to elapse. Therefore, in this case, allowing call_rcu() to immediately invoke its arguments would cause it to fail to make the fundamental guarantee underlying RCU, namely that call_rcu() defers invoking its arguments until all RCU read-side critical sections currently executing have completed.”…””}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K(hj@h²hubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hŒOQuick Quiz #1: Why is it *not* legal to invoke synchronize_rcu() in this case? ”h]”(hŒterm”“”)”}”(hŒQuick Quiz #1:”h]”hŒQuick Quiz #1:”…””}”(hjzh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´K4hjtubhŒ definition”“”)”}”(hhh]”hÚ)”}”(hŒ?Why is it *not* legal to invoke synchronize_rcu() in this case?”h]”(hŒ Why is it ”…””}”(hjh²hh³Nh´Nubhä)”}”(hŒ*not*”h]”hŒnot”…””}”(hj•h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjubhŒ0 legal to invoke synchronize_rcu() in this case?”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K4hjŠubah}”(h]”h ]”h"]”h$]”h&]”uh1jˆhjtubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´K4hjoubah}”(h]”h ]”h"]”h$]”h&]”uh1jmhj@h²hh³hÃh´NubhÚ)”}”(hŒ3:ref:`Answers to Quick Quiz `”h]”h)”}”(hjÁh]”hŒinline”“”)”}”(hjÁh]”hŒAnswers to Quick Quiz”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œstd”Œstd-ref”eh"]”h$]”h&]”uh1jÆhjÃubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”ŒRCU/UP”Œ refdomain”jÓŒreftype”Œref”Œ refexplicit”ˆŒrefwarn”ˆŒ reftarget”Œanswer_quick_quiz_up”uh1hh³hÃh´K6hj¿ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K6hj@h²hubeh}”(h]”Œ example-2-function-call-fatality”ah ]”h"]”Œ!example 2: function-call fatality”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´K"ubhÅ)”}”(hhh]”(hÊ)”}”(hŒExample 3: Death by Deadlock”h]”hŒExample 3: Death by Deadlock”…””}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjõh²hh³hÃh´K9ubhÚ)”}”(hX:Suppose that call_rcu() is invoked while holding a lock, and that the callback function must acquire this same lock. In this case, if call_rcu() were to directly invoke the callback, the result would be self-deadlock *even if* this invocation occurred from a later call_rcu() invocation a full grace period later.”h]”(hŒÚSuppose that call_rcu() is invoked while holding a lock, and that the callback function must acquire this same lock. In this case, if call_rcu() were to directly invoke the callback, the result would be self-deadlock ”…””}”(hjh²hh³Nh´Nubhä)”}”(hŒ *even if*”h]”hŒeven if”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjubhŒW this invocation occurred from a later call_rcu() invocation a full grace period later.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K;hjõh²hubhÚ)”}”(hŒ³In some cases, it would possible to restructure to code so that the call_rcu() is delayed until after the lock is released. However, there are cases where this can be quite ugly:”h]”hŒ³In some cases, it would possible to restructure to code so that the call_rcu() is delayed until after the lock is released. However, there are cases where this can be quite ugly:”…””}”(hj&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KAhjõh²hubhŒenumerated_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ½If a number of items need to be passed to call_rcu() within the same critical section, then the code would need to create a list of them, then traverse the list once the lock was released. ”h]”hÚ)”}”(hŒ¼If a number of items need to be passed to call_rcu() within the same critical section, then the code would need to create a list of them, then traverse the list once the lock was released.”h]”hŒ¼If a number of items need to be passed to call_rcu() within the same critical section, then the code would need to create a list of them, then traverse the list once the lock was released.”…””}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KEhj;ubah}”(h]”h ]”h"]”h$]”h&]”uh1j9hj6h²hh³hÃh´Nubj:)”}”(hXaIn some cases, the lock will be held across some kernel API, so that delaying the call_rcu() until the lock is released requires that the data item be passed up via a common API. It is far better to guarantee that callbacks are invoked with no locks held than to have to modify such APIs to allow arbitrary data items to be passed back up through them. ”h]”hÚ)”}”(hX`In some cases, the lock will be held across some kernel API, so that delaying the call_rcu() until the lock is released requires that the data item be passed up via a common API. It is far better to guarantee that callbacks are invoked with no locks held than to have to modify such APIs to allow arbitrary data items to be passed back up through them.”h]”hX`In some cases, the lock will be held across some kernel API, so that delaying the call_rcu() until the lock is released requires that the data item be passed up via a common API. It is far better to guarantee that callbacks are invoked with no locks held than to have to modify such APIs to allow arbitrary data items to be passed back up through them.”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KJhjSubah}”(h]”h ]”h"]”h$]”h&]”uh1j9hj6h²hh³hÃh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1j4hjõh²hh³hÃh´KEubhÚ)”}”(hŒkIf call_rcu() directly invokes the callback, painful locking restrictions or API changes would be required.”h]”hŒkIf call_rcu() directly invokes the callback, painful locking restrictions or API changes would be required.”…””}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KQhjõh²hubjn)”}”(hhh]”js)”}”(hŒDQuick Quiz #2: What locking restriction must RCU callbacks respect? ”h]”(jy)”}”(hŒQuick Quiz #2:”h]”hŒQuick Quiz #2:”…””}”(hj‹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´KUhj‡ubj‰)”}”(hhh]”hÚ)”}”(hŒ4What locking restriction must RCU callbacks respect?”h]”hŒ4What locking restriction must RCU callbacks respect?”…””}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KUhj™ubah}”(h]”h ]”h"]”h$]”h&]”uh1jˆhj‡ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´KUhj„ubah}”(h]”h ]”h"]”h$]”h&]”uh1jmhjõh²hh³hÃh´NubhÚ)”}”(hŒ3:ref:`Answers to Quick Quiz `”h]”h)”}”(hj¾h]”jÇ)”}”(hj¾h]”hŒAnswers to Quick Quiz”…””}”(hjÃh²hh³Nh´Nubah}”(h]”h ]”(jÒŒstd”Œstd-ref”eh"]”h$]”h&]”uh1jÆhjÀubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jߌ refdomain”jÍŒreftype”Œref”Œ refexplicit”ˆŒrefwarn”ˆjåŒanswer_quick_quiz_up”uh1hh³hÃh´KWhj¼ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KWhjõh²hubhÚ)”}”(hXÐIt is important to note that userspace RCU implementations *do* permit call_rcu() to directly invoke callbacks, but only if a full grace period has elapsed since those callbacks were queued. This is the case because some userspace environments are extremely constrained. Nevertheless, people writing userspace RCU implementations are strongly encouraged to avoid invoking callbacks from call_rcu(), thus obtaining the deadlock-avoidance benefits called out above.”h]”(hŒ;It is important to note that userspace RCU implementations ”…””}”(hjåh²hh³Nh´Nubhä)”}”(hŒ*do*”h]”hŒdo”…””}”(hjíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjåubhX‘ permit call_rcu() to directly invoke callbacks, but only if a full grace period has elapsed since those callbacks were queued. This is the case because some userspace environments are extremely constrained. Nevertheless, people writing userspace RCU implementations are strongly encouraged to avoid invoking callbacks from call_rcu(), thus obtaining the deadlock-avoidance benefits called out above.”…””}”(hjåh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KYhjõh²hubeh}”(h]”Œexample-3-death-by-deadlock”ah ]”h"]”Œexample 3: death by deadlock”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´K9ubhÅ)”}”(hhh]”(hÊ)”}”(hŒSummary”h]”hŒSummary”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj h²hh³hÃh´KbubhÚ)”}”(hXPermitting call_rcu() to immediately invoke its arguments breaks RCU, even on a UP system. So do not do it! Even on a UP system, the RCU infrastructure *must* respect grace periods, and *must* invoke callbacks from a known environment in which no locks are held.”h]”(hŒšPermitting call_rcu() to immediately invoke its arguments breaks RCU, even on a UP system. So do not do it! Even on a UP system, the RCU infrastructure ”…””}”(hjh²hh³Nh´Nubhä)”}”(hŒ*must*”h]”hŒmust”…””}”(hj&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjubhŒ respect grace periods, and ”…””}”(hjh²hh³Nh´Nubhä)”}”(hŒ*must*”h]”hŒmust”…””}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjubhŒF invoke callbacks from a known environment in which no locks are held.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Kdhj h²hubhÚ)”}”(hŒ…Note that it *is* safe for synchronize_rcu() to return immediately on UP systems, including PREEMPT SMP builds running on UP systems.”h]”(hŒ Note that it ”…””}”(hjPh²hh³Nh´Nubhä)”}”(hŒ*is*”h]”hŒis”…””}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjPubhŒt safe for synchronize_rcu() to return immediately on UP systems, including PREEMPT SMP builds running on UP systems.”…””}”(hjPh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Kihj h²hubjn)”}”(hhh]”js)”}”(hŒeQuick Quiz #3: Why can't synchronize_rcu() return immediately on UP systems running preemptible RCU? ”h]”(jy)”}”(hŒQuick Quiz #3:”h]”hŒQuick Quiz #3:”…””}”(hjwh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´Knhjsubj‰)”}”(hhh]”hÚ)”}”(hŒUWhy can't synchronize_rcu() return immediately on UP systems running preemptible RCU?”h]”hŒWWhy can’t synchronize_rcu() return immediately on UP systems running preemptible RCU?”…””}”(hjˆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´Kmhj…ubah}”(h]”h ]”h"]”h$]”h&]”uh1jˆhjsubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´Knhjpubah}”(h]”h ]”h"]”h$]”h&]”uh1jmhj h²hh³hÃh´Nubh¶)”}”(hŒ.. _answer_quick_quiz_up:”h]”h}”(h]”h ]”h"]”h$]”h&]”hÁŒanswer-quick-quiz-up”uh1hµh´Kphj h²hh³hÃubjn)”}”(hhh]”(js)”}”(hXUAnswer to Quick Quiz #1: Why is it *not* legal to invoke synchronize_rcu() in this case? Because the calling function is scanning an RCU-protected linked list, and is therefore within an RCU read-side critical section. Therefore, the called function has been invoked within an RCU read-side critical section, and is not permitted to block. ”h]”(jy)”}”(hŒAnswer to Quick Quiz #1:”h]”hŒAnswer to Quick Quiz #1:”…””}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´Kxhj¶ubj‰)”}”(hhh]”(hÚ)”}”(hŒ?Why is it *not* legal to invoke synchronize_rcu() in this case?”h]”(hŒ Why is it ”…””}”(hjËh²hh³Nh´Nubhä)”}”(hŒ*not*”h]”hŒnot”…””}”(hjÓh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjËubhŒ0 legal to invoke synchronize_rcu() in this case?”…””}”(hjËh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KshjÈubhÚ)”}”(hŒúBecause the calling function is scanning an RCU-protected linked list, and is therefore within an RCU read-side critical section. Therefore, the called function has been invoked within an RCU read-side critical section, and is not permitted to block.”h]”hŒúBecause the calling function is scanning an RCU-protected linked list, and is therefore within an RCU read-side critical section. Therefore, the called function has been invoked within an RCU read-side critical section, and is not permitted to block.”…””}”(hjëh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´KuhjÈubeh}”(h]”h ]”h"]”h$]”h&]”uh1jˆhj¶ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´Kxhj³ubjs)”}”(hX£Answer to Quick Quiz #2: What locking restriction must RCU callbacks respect? Any lock that is acquired within an RCU callback must be acquired elsewhere using an _bh variant of the spinlock primitive. For example, if "mylock" is acquired by an RCU callback, then a process-context acquisition of this lock must use something like spin_lock_bh() to acquire the lock. Please note that it is also OK to use _irq variants of spinlocks, for example, spin_lock_irqsave(). If the process-context code were to simply use spin_lock(), then, since RCU callbacks can be invoked from softirq context, the callback might be called from a softirq that interrupted the process-context critical section. This would result in self-deadlock. This restriction might seem gratuitous, since very few RCU callbacks acquire locks directly. However, a great many RCU callbacks do acquire locks *indirectly*, for example, via the kfree() primitive. ”h]”(jy)”}”(hŒAnswer to Quick Quiz #2:”h]”hŒAnswer to Quick Quiz #2:”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´KŽhjubj‰)”}”(hhh]”(hÚ)”}”(hŒ4What locking restriction must RCU callbacks respect?”h]”hŒ4What locking restriction must RCU callbacks respect?”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K{hjubhÚ)”}”(hX…Any lock that is acquired within an RCU callback must be acquired elsewhere using an _bh variant of the spinlock primitive. For example, if "mylock" is acquired by an RCU callback, then a process-context acquisition of this lock must use something like spin_lock_bh() to acquire the lock. Please note that it is also OK to use _irq variants of spinlocks, for example, spin_lock_irqsave().”h]”hX‰Any lock that is acquired within an RCU callback must be acquired elsewhere using an _bh variant of the spinlock primitive. For example, if “mylock†is acquired by an RCU callback, then a process-context acquisition of this lock must use something like spin_lock_bh() to acquire the lock. Please note that it is also OK to use _irq variants of spinlocks, for example, spin_lock_irqsave().”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K}hjubhÚ)”}”(hXIf the process-context code were to simply use spin_lock(), then, since RCU callbacks can be invoked from softirq context, the callback might be called from a softirq that interrupted the process-context critical section. This would result in self-deadlock.”h]”hXIf the process-context code were to simply use spin_lock(), then, since RCU callbacks can be invoked from softirq context, the callback might be called from a softirq that interrupted the process-context critical section. This would result in self-deadlock.”…””}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K…hjubhÚ)”}”(hŒÈThis restriction might seem gratuitous, since very few RCU callbacks acquire locks directly. However, a great many RCU callbacks do acquire locks *indirectly*, for example, via the kfree() primitive.”h]”(hŒ“This restriction might seem gratuitous, since very few RCU callbacks acquire locks directly. However, a great many RCU callbacks do acquire locks ”…””}”(hjDh²hh³Nh´Nubhä)”}”(hŒ *indirectly*”h]”hŒ indirectly”…””}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhjDubhŒ), for example, via the kfree() primitive.”…””}”(hjDh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K‹hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jˆhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´KŽhj³h²hubjs)”}”(hX—Answer to Quick Quiz #3: Why can't synchronize_rcu() return immediately on UP systems running preemptible RCU? Because some other task might have been preempted in the middle of an RCU read-side critical section. If synchronize_rcu() simply immediately returned, it would prematurely signal the end of the grace period, which would come as a nasty shock to that other thread when it started running again.”h]”(jy)”}”(hŒAnswer to Quick Quiz #3:”h]”hŒAnswer to Quick Quiz #3:”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jxh³hÃh´K—hjpubj‰)”}”(hhh]”(hÚ)”}”(hŒUWhy can't synchronize_rcu() return immediately on UP systems running preemptible RCU?”h]”hŒWWhy can’t synchronize_rcu() return immediately on UP systems running preemptible RCU?”…””}”(hj…h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K‘hj‚ubhÚ)”}”(hX'Because some other task might have been preempted in the middle of an RCU read-side critical section. If synchronize_rcu() simply immediately returned, it would prematurely signal the end of the grace period, which would come as a nasty shock to that other thread when it started running again.”h]”hX'Because some other task might have been preempted in the middle of an RCU read-side critical section. If synchronize_rcu() simply immediately returned, it would prematurely signal the end of the grace period, which would come as a nasty shock to that other thread when it started running again.”…””}”(hj“h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙh³hÃh´K”hj‚ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jˆhjpubeh}”(h]”h ]”h"]”h$]”h&]”uh1jrh³hÃh´K—hj³h²hubeh}”(h]”j²ah ]”h"]”Œanswer_quick_quiz_up”ah$]”h&]”uh1jmhj h²hh³hÃh´NŒexpect_referenced_by_name”}”j±j¨sŒexpect_referenced_by_id”}”j²j¨subeh}”(h]”Œsummary”ah ]”h"]”Œsummary”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´Kbubeh}”(h]”(Œrcu-on-uniprocessor-systems”hÂeh ]”h"]”(Œrcu on uniprocessor systems”Œup_doc”eh$]”h&]”uh1hÄhhh²hh³hÃh´Kj´}”jÆh·sj¶}”hÂh·subeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÃuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÉNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jîŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÃŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”(hÂ]”h·aj²]”j¨auŒnameids”}”(jÆhÂjÅjÂj=j:jòjïj jj½jºj±j²uŒ nametypes”}”(jƈjʼnj=‰jò‰j ‰j½‰j±ˆuh}”(hÂhÆjÂhÆj:hýjïj@jjõjºj j²j³uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”(hŒsystem_message”“”)”}”(hhh]”hÚ)”}”(hhh]”hŒ,Hyperlink target "up-doc" is not referenced.”…””}”hjYsbah}”(h]”h ]”h"]”h$]”h&]”uh1hÙhjVubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œsource”hÃŒline”Kuh1jTubjU)”}”(hhh]”hÚ)”}”(hhh]”hŒ:Hyperlink target "answer-quick-quiz-up" is not referenced.”…””}”hjtsbah}”(h]”h ]”h"]”h$]”h&]”uh1hÙhjqubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”jnŒsource”hÃŒline”Kpuh1jTubeŒ transformer”NŒ include_log”]”Œ decoration”Nh²hub.