€•urŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”(hhŒparent”hubaŒ 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)”…””}”(hhhh2ubah}”(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”…””}”(hhhhFubah}”(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”…””}”(hhhhZubah}”(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”…””}”(hhhhnubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/ko_KR/RCU/UP”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”(hhhh‚ubah}”(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¹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 ”…””}”(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”…””}”(hhhhÒ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.”…””}”(hŒ  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”…””}”(hhðhhîhž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.”…””}”(hhþhhühž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.”…””}”(hj hj hž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.”…””}”(hjhjhž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”…””}”(hj3hj1hž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.”…””}”(hjAhj?hž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.”…””}”(hjOhjMhž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:”…””}”(hjjhjhhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h K4hjbubhŒ definition”“”)”}”(hhh]”hÆ)”}”(hŒ?Why is it *not* legal to invoke synchronize_rcu() in this case?”h]”(hŒ Why is it ”…””}”(hŒ Why is it ”hj{hžhhŸNh NubhÑ)”}”(hŒ*not*”h]”hŒnot”…””}”(hhhj„hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhj{ubhŒ0 legal to invoke synchronize_rcu() in this case?”…””}”(hŒ0 legal to invoke synchronize_rcu() in this case?”hj{hžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h K4hjxubah}”(h]”h ]”h"]”h$]”h&]”uh1jvhjbubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h K4hj]ubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hj.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”…””}”(hhhj¸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ê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 ”…””}”(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 ”hjöhžhhŸNh NubhÑ)”}”(hŒ *even if*”h]”hŒeven if”…””}”(hhhjÿhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhjöubhŒW this invocation occurred from a later call_rcu() invocation a full grace period later.”…””}”(hŒW this invocation occurred from a later call_rcu() invocation a full grace period later.”hjöhž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:”…””}”(hjhjhž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.”…””}”(hj3hj1hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h KEhj-ubah}”(h]”h ]”h"]”h$]”h&]”uh1j+hj(hž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.”…””}”(hjKhjIhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h KJhjEubah}”(h]”h ]”h"]”h$]”h&]”uh1j+hj(hžhhŸh¯h Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1j&hjå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.”…””}”(hjjhjhhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h KQhjåhžhubj\)”}”(hhh]”ja)”}”(hŒDQuick Quiz #2: What locking restriction must RCU callbacks respect? ”h]”(jg)”}”(hŒQuick Quiz #2:”h]”hŒQuick Quiz #2:”…””}”(hjhj}hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h KUhjyubjw)”}”(hhh]”hÆ)”}”(hŒ4What locking restriction must RCU callbacks respect?”h]”hŒ4What locking restriction must RCU callbacks respect?”…””}”(hjhjŽhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h KUhj‹ubah}”(h]”h ]”h"]”h$]”h&]”uh1jvhjyubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h KUhjvubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hjåhžhhŸh¯h NubhÆ)”}”(hŒ3:ref:`Answers to Quick Quiz `”h]”h)”}”(hj°h]”j·)”}”(hj°h]”hŒAnswers to Quick Quiz”…””}”(hhhjµ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 ”…””}”(hŒ;It is important to note that userspace RCU implementations ”hj×hžhhŸNh NubhÑ)”}”(hŒ*do*”h]”hŒdo”…””}”(hhhjà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.”…””}”(hX‘ 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”…””}”(hjhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hµhjhž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 ”…””}”(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”…””}”(hhhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhjubhŒ respect grace periods, and ”…””}”(hŒ respect grace periods, and ”hjhžhhŸNh NubhÑ)”}”(hŒ*must*”h]”hŒmust”…””}”(hhhj.hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhjubhŒF invoke callbacks from a known environment in which no locks are held.”…””}”(hŒ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 Kdhjhž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 ”…””}”(hŒ Note that it ”hjGhžhhŸNh NubhÑ)”}”(hŒ*is*”h]”hŒis”…””}”(hhhjPhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhjGubhŒt safe for synchronize_rcu() to return immediately on UP systems, including PREEMPT SMP builds running on UP systems.”…””}”(hŒt safe for synchronize_rcu() to return immediately on UP systems, including PREEMPT SMP builds running on UP systems.”hjGhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h Kihjhžhubj\)”}”(hhh]”ja)”}”(hŒeQuick Quiz #3: Why can't synchronize_rcu() return immediately on UP systems running preemptible RCU? ”h]”(jg)”}”(hŒQuick Quiz #3:”h]”hŒQuick Quiz #3:”…””}”(hjrhjphžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h Knhjlubjw)”}”(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ƒhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h Kmhj~ubah}”(h]”h ]”h"]”h$]”h&]”uh1jvhjlubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h Knhjiubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hjhžhhŸh¯h Nubh¢)”}”(hŒ.. _answer_quick_quiz_up:”h]”h}”(h]”h ]”h"]”h$]”h&]”h­Œanswer-quick-quiz-up”uh1h¡h KphjhžhhŸh¯ubj\)”}”(hhh]”(ja)”}”(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]”(jg)”}”(hŒAnswer to Quick Quiz #1:”h]”hŒAnswer to Quick Quiz #1:”…””}”(hjµhj³hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h Kxhj¯ubjw)”}”(hhh]”(hÆ)”}”(hŒ?Why is it *not* legal to invoke synchronize_rcu() in this case?”h]”(hŒ Why is it ”…””}”(hŒ Why is it ”hjÄhžhhŸNh NubhÑ)”}”(hŒ*not*”h]”hŒnot”…””}”(hhhjÍhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhjÄubhŒ0 legal to invoke synchronize_rcu() in this case?”…””}”(hŒ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èhjæhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h KuhjÁubeh}”(h]”h ]”h"]”h$]”h&]”uh1jvhj¯ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h Kxhj¬ubja)”}”(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]”(jg)”}”(hŒAnswer to Quick Quiz #2:”h]”hŒAnswer to Quick Quiz #2:”…””}”(hjhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h KŽhjubjw)”}”(hhh]”(hÆ)”}”(hŒ4What locking restriction must RCU callbacks respect?”h]”hŒ4What locking restriction must RCU callbacks respect?”…””}”(hjhjhž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%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.”…””}”(hj3hj1hž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 ”…””}”(hŒ“This restriction might seem gratuitous, since very few RCU callbacks acquire locks directly. However, a great many RCU callbacks do acquire locks ”hj?hžhhŸNh NubhÑ)”}”(hŒ *indirectly*”h]”hŒ indirectly”…””}”(hhhjHhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhj?ubhŒ), for example, via the kfree() primitive.”…””}”(hŒ), for example, via the kfree() primitive.”hj?hžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h K‹hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jvhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h KŽhj¬hžhubja)”}”(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]”(jg)”}”(hŒAnswer to Quick Quiz #3:”h]”hŒAnswer to Quick Quiz #3:”…””}”(hjshjqhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jfhŸh¯h K—hjmubjw)”}”(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„hj‚hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h K‘hjubhÆ)”}”(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’hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhŸh¯h K”hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jvhjmubeh}”(h]”h ]”h"]”h$]”h&]”uh1j`hŸh¯h K—hj¬hžhubeh}”(h]”j«ah ]”h"]”Œanswer_quick_quiz_up”ah$]”h&]”uh1j[hjhž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Œ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”‰Œfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œ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”‰Œ embed_images”‰Œ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þjûjºj·j®j«uŒ nametypes”}”(jÈjÂNj+NjâNjþNjºNj®ˆuh}”(h®h²j¿h²j(hëjßj.jûjåj·jj«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.”…””}”(hhhjWubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhjTubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œsource”h¯Œline”Kuh1jRubjS)”}”(hhh]”hÆ)”}”(hhh]”hŒ:Hyperlink target "answer-quick-quiz-up" is not referenced.”…””}”(hhhjrubah}”(h]”h ]”h"]”h$]”h&]”uh1hÅhjoubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”jlŒsource”h¯Œline”Kpuh1jRubeŒ transformer”NŒ include_log”]”Œ decoration”Nhžhub.