€•RJŒ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/core-api/real-time/theory”Œ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/core-api/real-time/theory”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ-/translations/it_IT/core-api/real-time/theory”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ-/translations/ja_JP/core-api/real-time/theory”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ-/translations/ko_KR/core-api/real-time/theory”Œ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/core-api/real-time/theory”Œ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/core-api/real-time/theory”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒG/var/lib/git/docbuild/linux/Documentation/core-api/real-time/theory.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒTheory of operation”h]”hŒTheory of operation”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ field_list”“”)”}”(hhh]”hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hhéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hçhhäh³hÇh´KubhŒ field_body”“”)”}”(hŒ2Sebastian Andrzej Siewior ”h]”hŒ paragraph”“”)”}”(hŒ1Sebastian Andrzej Siewior ”h]”(hŒSebastian Andrzej Siewior <”…””}”(hhÿh²hh³Nh´NubhŒ reference”“”)”}”(hŒbigeasy@linutronix.de”h]”hŒbigeasy@linutronix.de”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:bigeasy@linutronix.de”uh1jhhÿubhŒ>”…””}”(hhÿh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khhùubah}”(h]”h ]”h"]”h$]”h&]”uh1h÷hhäubeh}”(h]”h ]”h"]”h$]”h&]”uh1hâh³hÇh´Khhßh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒPreface”h]”hŒPreface”…””}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj5h²hh³hÇh´K ubhþ)”}”(hX½PREEMPT_RT transforms the Linux kernel into a real-time kernel. It achieves this by replacing locking primitives, such as spinlock_t, with a preemptible and priority-inheritance aware implementation known as rtmutex, and by enforcing the use of threaded interrupts. As a result, the kernel becomes fully preemptible, with the exception of a few critical code paths, including entry code, the scheduler, and low-level interrupt handling routines.”h]”hX½PREEMPT_RT transforms the Linux kernel into a real-time kernel. It achieves this by replacing locking primitives, such as spinlock_t, with a preemptible and priority-inheritance aware implementation known as rtmutex, and by enforcing the use of threaded interrupts. As a result, the kernel becomes fully preemptible, with the exception of a few critical code paths, including entry code, the scheduler, and low-level interrupt handling routines.”…””}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K hj5h²hubhþ)”}”(hXThis transformation places the majority of kernel execution contexts under the control of the scheduler and significantly increasing the number of preemption points. Consequently, it reduces the latency between a high-priority task becoming runnable and its actual execution on the CPU.”h]”hXThis transformation places the majority of kernel execution contexts under the control of the scheduler and significantly increasing the number of preemption points. Consequently, it reduces the latency between a high-priority task becoming runnable and its actual execution on the CPU.”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khj5h²hubeh}”(h]”Œpreface”ah ]”h"]”Œpreface”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K ubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Scheduling”h]”hŒ Scheduling”…””}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjjh²hh³hÇh´Kubhþ)”}”(hX*The core principles of Linux scheduling and the associated user-space API are documented in the man page sched(7) `sched(7) `_. By default, the Linux kernel uses the SCHED_OTHER scheduling policy. Under this policy, a task is preempted when the scheduler determines that it has consumed a fair share of CPU time relative to other runnable tasks. However, the policy does not guarantee immediate preemption when a new SCHED_OTHER task becomes runnable. The currently running task may continue executing.”h]”(hŒrThe core principles of Linux scheduling and the associated user-space API are documented in the man page sched(7) ”…””}”(hj{h²hh³Nh´Nubj)”}”(hŒ@`sched(7) `_”h]”hŒsched(7)”…””}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œsched(7)”Œrefuri”Œ2https://man7.org/linux/man-pages/man7/sched.7.html”uh1jhj{ubhŒtarget”“”)”}”(hŒ5 ”h]”h}”(h]”Œsched-7”ah ]”h"]”Œsched(7)”ah$]”h&]”Œrefuri”j”uh1j•Œ referenced”Khj{ubhXx. By default, the Linux kernel uses the SCHED_OTHER scheduling policy. Under this policy, a task is preempted when the scheduler determines that it has consumed a fair share of CPU time relative to other runnable tasks. However, the policy does not guarantee immediate preemption when a new SCHED_OTHER task becomes runnable. The currently running task may continue executing.”…””}”(hj{h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khjjh²hubhþ)”}”(hX\This behavior differs from that of real-time scheduling policies such as SCHED_FIFO. When a task with a real-time policy becomes runnable, the scheduler immediately selects it for execution if it has a higher priority than the currently running task. The task continues to run until it voluntarily yields the CPU, typically by blocking on an event.”h]”hX\This behavior differs from that of real-time scheduling policies such as SCHED_FIFO. When a task with a real-time policy becomes runnable, the scheduler immediately selects it for execution if it has a higher priority than the currently running task. The task continues to run until it voluntarily yields the CPU, typically by blocking on an event.”…””}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K$hjjh²hubeh}”(h]”Œ scheduling”ah ]”h"]”Œ scheduling”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒSleeping spin locks”h]”hŒSleeping spin locks”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÅh²hh³hÇh´K+ubhþ)”}”(hX The various lock types and their behavior under real-time configurations are described in detail in Documentation/locking/locktypes.rst. In a non-PREEMPT_RT configuration, a spinlock_t is acquired by first disabling preemption and then actively spinning until the lock becomes available. Once the lock is released, preemption is enabled. From a real-time perspective, this approach is undesirable because disabling preemption prevents the scheduler from switching to a higher-priority task, potentially increasing latency.”h]”hX The various lock types and their behavior under real-time configurations are described in detail in Documentation/locking/locktypes.rst. In a non-PREEMPT_RT configuration, a spinlock_t is acquired by first disabling preemption and then actively spinning until the lock becomes available. Once the lock is released, preemption is enabled. From a real-time perspective, this approach is undesirable because disabling preemption prevents the scheduler from switching to a higher-priority task, potentially increasing latency.”…””}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K-hjÅh²hubhþ)”}”(hXŒTo address this, PREEMPT_RT replaces spinning locks with sleeping spin locks that do not disable preemption. On PREEMPT_RT, spinlock_t is implemented using rtmutex. Instead of spinning, a task attempting to acquire a contended lock disables CPU migration, donates its priority to the lock owner (priority inheritance), and voluntarily schedules out while waiting for the lock to become available.”h]”hXŒTo address this, PREEMPT_RT replaces spinning locks with sleeping spin locks that do not disable preemption. On PREEMPT_RT, spinlock_t is implemented using rtmutex. Instead of spinning, a task attempting to acquire a contended lock disables CPU migration, donates its priority to the lock owner (priority inheritance), and voluntarily schedules out while waiting for the lock to become available.”…””}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K6hjÅh²hubhþ)”}”(hŒÄDisabling CPU migration provides the same effect as disabling preemption, while still allowing preemption and ensuring that the task continues to run on the same CPU while holding a sleeping lock.”h]”hŒÄDisabling CPU migration provides the same effect as disabling preemption, while still allowing preemption and ensuring that the task continues to run on the same CPU while holding a sleeping lock.”…””}”(hjòh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K=hjÅh²hubeh}”(h]”Œsleeping-spin-locks”ah ]”h"]”Œsleeping spin locks”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K+ubhÉ)”}”(hhh]”(hÎ)”}”(hŒPriority inheritance”h]”hŒPriority inheritance”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KBubhþ)”}”(hX*Lock types such as spinlock_t and mutex_t in a PREEMPT_RT enabled kernel are implemented on top of rtmutex, which provides support for priority inheritance (PI). When a task blocks on such a lock, the PI mechanism temporarily propagates the blocked task’s scheduling parameters to the lock owner.”h]”hX*Lock types such as spinlock_t and mutex_t in a PREEMPT_RT enabled kernel are implemented on top of rtmutex, which provides support for priority inheritance (PI). When a task blocks on such a lock, the PI mechanism temporarily propagates the blocked task’s scheduling parameters to the lock owner.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KDhjh²hubhþ)”}”(hX“For example, if a SCHED_FIFO task A blocks on a lock currently held by a SCHED_OTHER task B, task A’s scheduling policy and priority are temporarily inherited by task B. After this inheritance, task A is put to sleep while waiting for the lock, and task B effectively becomes the highest-priority task in the system. This allows B to continue executing, make progress, and eventually release the lock.”h]”hX“For example, if a SCHED_FIFO task A blocks on a lock currently held by a SCHED_OTHER task B, task A’s scheduling policy and priority are temporarily inherited by task B. After this inheritance, task A is put to sleep while waiting for the lock, and task B effectively becomes the highest-priority task in the system. This allows B to continue executing, make progress, and eventually release the lock.”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KIhjh²hubhþ)”}”(hŒlOnce B releases the lock, it reverts to its original scheduling parameters, and task A can resume execution.”h]”hŒlOnce B releases the lock, it reverts to its original scheduling parameters, and task A can resume execution.”…””}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KPhjh²hubeh}”(h]”Œpriority-inheritance”ah ]”h"]”Œpriority inheritance”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KBubhÉ)”}”(hhh]”(hÎ)”}”(hŒThreaded interrupts”h]”hŒThreaded interrupts”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjKh²hh³hÇh´KTubhþ)”}”(hŒäInterrupt handlers are another source of code that executes with preemption disabled and outside the control of the scheduler. To bring interrupt handling under scheduler control, PREEMPT_RT enforces threaded interrupt handlers.”h]”hŒäInterrupt handlers are another source of code that executes with preemption disabled and outside the control of the scheduler. To bring interrupt handling under scheduler control, PREEMPT_RT enforces threaded interrupt handlers.”…””}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KVhjKh²hubhþ)”}”(hXWith forced threading, interrupt handling is split into two stages. The first stage, the primary handler, is executed in IRQ context with interrupts disabled. Its sole responsibility is to wake the associated threaded handler. The second stage, the threaded handler, is the function passed to request_irq() as the interrupt handler. It runs in process context, scheduled by the kernel.”h]”hXWith forced threading, interrupt handling is split into two stages. The first stage, the primary handler, is executed in IRQ context with interrupts disabled. Its sole responsibility is to wake the associated threaded handler. The second stage, the threaded handler, is the function passed to request_irq() as the interrupt handler. It runs in process context, scheduled by the kernel.”…””}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KZhjKh²hubhþ)”}”(hX1From waking the interrupt thread until threaded handling is completed, the interrupt source is masked in the interrupt controller. This ensures that the device interrupt remains pending but does not retrigger the CPU, allowing the system to exit IRQ context and handle the interrupt in a scheduled thread.”h]”hX1From waking the interrupt thread until threaded handling is completed, the interrupt source is masked in the interrupt controller. This ensures that the device interrupt remains pending but does not retrigger the CPU, allowing the system to exit IRQ context and handle the interrupt in a scheduled thread.”…””}”(hjxh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K`hjKh²hubhþ)”}”(hŒ½By default, the threaded handler executes with the SCHED_FIFO scheduling policy and a priority of 50 (MAX_RT_PRIO / 2), which is midway between the minimum and maximum real-time priorities.”h]”hŒ½By default, the threaded handler executes with the SCHED_FIFO scheduling policy and a priority of 50 (MAX_RT_PRIO / 2), which is midway between the minimum and maximum real-time priorities.”…””}”(hj†h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KehjKh²hubhþ)”}”(hX If the threaded interrupt handler raises any soft interrupts during its execution, those soft interrupt routines are invoked after the threaded handler completes, within the same thread. Preemption remains enabled during the execution of the soft interrupt handler.”h]”hX If the threaded interrupt handler raises any soft interrupts during its execution, those soft interrupt routines are invoked after the threaded handler completes, within the same thread. Preemption remains enabled during the execution of the soft interrupt handler.”…””}”(hj”h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´KihjKh²hubeh}”(h]”Œthreaded-interrupts”ah ]”h"]”Œthreaded interrupts”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KTubhÉ)”}”(hhh]”(hÎ)”}”(hŒSummary”h]”hŒSummary”…””}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjªh²hh³hÇh´Koubhþ)”}”(hŒûBy using sleeping locks and forced-threaded interrupts, PREEMPT_RT significantly reduces sections of code where interrupts or preemption is disabled, allowing the scheduler to preempt the current execution context and switch to a higher-priority task.”h]”hŒûBy using sleeping locks and forced-threaded interrupts, PREEMPT_RT significantly reduces sections of code where interrupts or preemption is disabled, allowing the scheduler to preempt the current execution context and switch to a higher-priority task.”…””}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Kqhjªh²hubeh}”(h]”Œsummary”ah ]”h"]”Œsummary”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Koubeh}”(h]”Œtheory-of-operation”ah ]”h"]”Œtheory of operation”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(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”}”Œnameids”}”(jÖjÓjgjdjÂj¿j jjjjHjEj§j¤jÎjËuŒ nametypes”}”(jÖ‰jg‰j‰j ˆj‰jH‰j§‰jΉuh}”(jÓhÊjdj5j¿jjjj—jjÅjEjj¤jKjË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”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.