€•üpŒ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/locking/mutex-design”Œ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/locking/mutex-design”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/it_IT/locking/mutex-design”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/ja_JP/locking/mutex-design”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ(/translations/ko_KR/locking/mutex-design”Œ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/locking/mutex-design”Œ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/locking/mutex-design”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒGeneric Mutex Subsystem”h]”hŒGeneric Mutex Subsystem”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒB/var/lib/git/docbuild/linux/Documentation/locking/mutex-design.rst”h´KubhŒ paragraph”“”)”}”(hŒ)started by Ingo Molnar ”h]”(hŒstarted by Ingo Molnar <”…””}”(hhÍh²hh³Nh´NubhŒ reference”“”)”}”(hŒmingo@redhat.com”h]”hŒmingo@redhat.com”…””}”(hh×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:mingo@redhat.com”uh1hÕhhÍubhŒ>”…””}”(hhÍh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)”}”(hŒ-updated by Davidlohr Bueso ”h]”(hŒupdated by Davidlohr Bueso <”…””}”(hhñh²hh³Nh´NubhÖ)”}”(hŒdavidlohr@hp.com”h]”hŒdavidlohr@hp.com”…””}”(hhùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:davidlohr@hp.com”uh1hÕhhñubhŒ>”…””}”(hhñh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubh¶)”}”(hhh]”(h»)”}”(hŒWhat are mutexes?”h]”hŒWhat are mutexes?”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjh²hh³hÊh´K ubhÌ)”}”(hXýIn the Linux kernel, mutexes refer to a particular locking primitive that enforces serialization on shared memory systems, and not only to the generic term referring to 'mutual exclusion' found in academia or similar theoretical text books. Mutexes are sleeping locks which behave similarly to binary semaphores, and were introduced in 2006[1] as an alternative to these. This new data structure provided a number of advantages, including simpler interfaces, and at that time smaller code (see Disadvantages).”h]”hXIn the Linux kernel, mutexes refer to a particular locking primitive that enforces serialization on shared memory systems, and not only to the generic term referring to ‘mutual exclusion’ found in academia or similar theoretical text books. Mutexes are sleeping locks which behave similarly to binary semaphores, and were introduced in 2006[1] as an alternative to these. This new data structure provided a number of advantages, including simpler interfaces, and at that time smaller code (see Disadvantages).”…””}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hjh²hubhÌ)”}”(hŒ$[1] https://lwn.net/Articles/164802/”h]”(hŒ[1] ”…””}”(hj2h²hh³Nh´NubhÖ)”}”(hŒ https://lwn.net/Articles/164802/”h]”hŒ https://lwn.net/Articles/164802/”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”j<uh1hÕhj2ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khjh²hubeh}”(h]”Œwhat-are-mutexes”ah ]”h"]”Œwhat are mutexes?”ah$]”h&]”uh1hµhh·h²hh³hÊh´K ubh¶)”}”(hhh]”(h»)”}”(hŒImplementation”h]”hŒImplementation”…””}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjWh²hh³hÊh´KubhÌ)”}”(hXºMutexes are represented by 'struct mutex', defined in include/linux/mutex.h and implemented in kernel/locking/mutex.c. These locks use an atomic variable (->owner) to keep track of the lock state during its lifetime. Field owner actually contains `struct task_struct *` to the current lock owner and it is therefore NULL if not currently owned. Since task_struct pointers are aligned to at least L1_CACHE_BYTES, low bits (3) are used to store extra state (e.g., if waiter list is non-empty). In its most basic form it also includes a wait-queue and a spinlock that serializes access to it. Furthermore, CONFIG_MUTEX_SPIN_ON_OWNER=y systems use a spinner MCS lock (->osq), described below in (ii).”h]”(hŒüMutexes are represented by ‘struct mutex’, defined in include/linux/mutex.h and implemented in kernel/locking/mutex.c. These locks use an atomic variable (->owner) to keep track of the lock state during its lifetime. Field owner actually contains ”…””}”(hjhh²hh³Nh´NubhŒtitle_reference”“”)”}”(hŒ`struct task_struct *`”h]”hŒstruct task_struct *”…””}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jphjhubhX¬ to the current lock owner and it is therefore NULL if not currently owned. Since task_struct pointers are aligned to at least L1_CACHE_BYTES, low bits (3) are used to store extra state (e.g., if waiter list is non-empty). In its most basic form it also includes a wait-queue and a spinlock that serializes access to it. Furthermore, CONFIG_MUTEX_SPIN_ON_OWNER=y systems use a spinner MCS lock (->osq), described below in (ii).”…””}”(hjhh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhjWh²hubhÌ)”}”(hŒmWhen acquiring a mutex, there are three possible paths that can be taken, depending on the state of the lock:”h]”hŒmWhen acquiring a mutex, there are three possible paths that can be taken, depending on the state of the lock:”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K%hjWh²hubhŒenumerated_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hX fastpath: tries to atomically acquire the lock by cmpxchg()ing the owner with the current task. This only works in the uncontended case (cmpxchg() checks against 0UL, so all 3 state bits above have to be 0). If the lock is contended it goes to the next possible path. ”h]”hÌ)”}”(hX fastpath: tries to atomically acquire the lock by cmpxchg()ing the owner with the current task. This only works in the uncontended case (cmpxchg() checks against 0UL, so all 3 state bits above have to be 0). If the lock is contended it goes to the next possible path.”h]”hX fastpath: tries to atomically acquire the lock by cmpxchg()ing the owner with the current task. This only works in the uncontended case (cmpxchg() checks against 0UL, so all 3 state bits above have to be 0). If the lock is contended it goes to the next possible path.”…””}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K(hjŸubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³hÊh´Nubjž)”}”(hXWmidpath: aka optimistic spinning, tries to spin for acquisition while the lock owner is running and there are no other tasks ready to run that have higher priority (need_resched). The rationale is that if the lock owner is running, it is likely to release the lock soon. The mutex spinners are queued up using MCS lock so that only one spinner can compete for the mutex. The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spinlock with the desirable properties of being fair and with each cpu trying to acquire the lock spinning on a local variable. It avoids expensive cacheline bouncing that common test-and-set spinlock implementations incur. An MCS-like lock is specially tailored for optimistic spinning for sleeping lock implementation. An important feature of the customized MCS lock is that it has the extra property that spinners are able to exit the MCS spinlock queue when they need to reschedule. This further helps avoid situations where MCS spinners that need to reschedule would continue waiting to spin on mutex owner, only to go directly to slowpath upon obtaining the MCS lock. ”h]”(hÌ)”}”(hXrmidpath: aka optimistic spinning, tries to spin for acquisition while the lock owner is running and there are no other tasks ready to run that have higher priority (need_resched). The rationale is that if the lock owner is running, it is likely to release the lock soon. The mutex spinners are queued up using MCS lock so that only one spinner can compete for the mutex.”h]”hXrmidpath: aka optimistic spinning, tries to spin for acquisition while the lock owner is running and there are no other tasks ready to run that have higher priority (need_resched). The rationale is that if the lock owner is running, it is likely to release the lock soon. The mutex spinners are queued up using MCS lock so that only one spinner can compete for the mutex.”…””}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K-hj·ubhÌ)”}”(hXáThe MCS lock (proposed by Mellor-Crummey and Scott) is a simple spinlock with the desirable properties of being fair and with each cpu trying to acquire the lock spinning on a local variable. It avoids expensive cacheline bouncing that common test-and-set spinlock implementations incur. An MCS-like lock is specially tailored for optimistic spinning for sleeping lock implementation. An important feature of the customized MCS lock is that it has the extra property that spinners are able to exit the MCS spinlock queue when they need to reschedule. This further helps avoid situations where MCS spinners that need to reschedule would continue waiting to spin on mutex owner, only to go directly to slowpath upon obtaining the MCS lock.”h]”hXáThe MCS lock (proposed by Mellor-Crummey and Scott) is a simple spinlock with the desirable properties of being fair and with each cpu trying to acquire the lock spinning on a local variable. It avoids expensive cacheline bouncing that common test-and-set spinlock implementations incur. An MCS-like lock is specially tailored for optimistic spinning for sleeping lock implementation. An important feature of the customized MCS lock is that it has the extra property that spinners are able to exit the MCS spinlock queue when they need to reschedule. This further helps avoid situations where MCS spinners that need to reschedule would continue waiting to spin on mutex owner, only to go directly to slowpath upon obtaining the MCS lock.”…””}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K4hj·ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³hÊh´Nubjž)”}”(hŒÓslowpath: last resort, if the lock is still unable to be acquired, the task is added to the wait-queue and sleeps until woken up by the unlock path. Under normal circumstances it blocks as TASK_UNINTERRUPTIBLE. ”h]”hÌ)”}”(hŒÒslowpath: last resort, if the lock is still unable to be acquired, the task is added to the wait-queue and sleeps until woken up by the unlock path. Under normal circumstances it blocks as TASK_UNINTERRUPTIBLE.”h]”hŒÒslowpath: last resort, if the lock is still unable to be acquired, the task is added to the wait-queue and sleeps until woken up by the unlock path. Under normal circumstances it blocks as TASK_UNINTERRUPTIBLE.”…””}”(hjáh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KAhjÝubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œ lowerroman”Œprefix”Œ(”Œsuffix”Œ)”uh1j˜hjWh²hh³hÊh´K(ubhÌ)”}”(hXkWhile formally kernel mutexes are sleepable locks, it is path (ii) that makes them more practically a hybrid type. By simply not interrupting a task and busy-waiting for a few cycles instead of immediately sleeping, the performance of this lock has been seen to significantly improve a number of workloads. Note that this technique is also used for rw-semaphores.”h]”hXkWhile formally kernel mutexes are sleepable locks, it is path (ii) that makes them more practically a hybrid type. By simply not interrupting a task and busy-waiting for a few cycles instead of immediately sleeping, the performance of this lock has been seen to significantly improve a number of workloads. Note that this technique is also used for rw-semaphores.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KEhjWh²hubeh}”(h]”Œimplementation”ah ]”h"]”Œimplementation”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ Semantics”h]”hŒ Semantics”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjh²hh³hÊh´KLubhÌ)”}”(hŒubjž)”}”(hŒ$Only the owner can unlock the mutex.”h]”hÌ)”}”(hjZh]”hŒ$Only the owner can unlock the mutex.”…””}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KQhjXubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ#Multiple unlocks are not permitted.”h]”hÌ)”}”(hjqh]”hŒ#Multiple unlocks are not permitted.”…””}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KRhjoubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ-Recursive locking/unlocking is not permitted.”h]”hÌ)”}”(hjˆh]”hŒ-Recursive locking/unlocking is not permitted.”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KShj†ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ9A mutex must only be initialized via the API (see below).”h]”hÌ)”}”(hjŸh]”hŒ9A mutex must only be initialized via the API (see below).”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KThjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ&A task may not exit with a mutex held.”h]”hÌ)”}”(hj¶h]”hŒ&A task may not exit with a mutex held.”…””}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KUhj´ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ7Memory areas where held locks reside must not be freed.”h]”hÌ)”}”(hjÍh]”hŒ7Memory areas where held locks reside must not be freed.”…””}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KVhjËubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ'Held mutexes must not be reinitialized.”h]”hÌ)”}”(hjäh]”hŒ'Held mutexes must not be reinitialized.”…””}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KWhjâubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubjž)”}”(hŒ`Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. ”h]”hÌ)”}”(hŒ_Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers.”h]”hŒ_Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers.”…””}”(hjýh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KXhjùubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj>ubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j<h³hÊh´KPhj8ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6h³hÊh´KPhjh²hubhÌ)”}”(hŒÅThese semantics are fully enforced when CONFIG DEBUG_MUTEXES is enabled. In addition, the mutex debugging code also implements a number of other features that make lock debugging easier and faster:”h]”hŒÅThese semantics are fully enforced when CONFIG DEBUG_MUTEXES is enabled. In addition, the mutex debugging code also implements a number of other features that make lock debugging easier and faster:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K[hjh²hubj7)”}”(hXŠ- Uses symbolic names of mutexes, whenever they are printed in debug output. - Point-of-acquire tracking, symbolic lookup of function names, list of all locks held in the system, printout of them. - Owner tracking. - Detects self-recursing locks and prints out all relevant info. - Detects multi-task circular deadlocks and prints out all affected locks and tasks (and only those tasks). ”h]”j=)”}”(hhh]”(jž)”}”(hŒJUses symbolic names of mutexes, whenever they are printed in debug output.”h]”hÌ)”}”(hŒJUses symbolic names of mutexes, whenever they are printed in debug output.”h]”hŒJUses symbolic names of mutexes, whenever they are printed in debug output.”…””}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K_hj4ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj1ubjž)”}”(hŒuPoint-of-acquire tracking, symbolic lookup of function names, list of all locks held in the system, printout of them.”h]”hÌ)”}”(hŒuPoint-of-acquire tracking, symbolic lookup of function names, list of all locks held in the system, printout of them.”h]”hŒuPoint-of-acquire tracking, symbolic lookup of function names, list of all locks held in the system, printout of them.”…””}”(hjPh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KahjLubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj1ubjž)”}”(hŒOwner tracking.”h]”hÌ)”}”(hjfh]”hŒOwner tracking.”…””}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kchjdubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj1ubjž)”}”(hŒ>Detects self-recursing locks and prints out all relevant info.”h]”hÌ)”}”(hj}h]”hŒ>Detects self-recursing locks and prints out all relevant info.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kdhj{ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj1ubjž)”}”(hŒjDetects multi-task circular deadlocks and prints out all affected locks and tasks (and only those tasks). ”h]”hÌ)”}”(hŒiDetects multi-task circular deadlocks and prints out all affected locks and tasks (and only those tasks).”h]”hŒiDetects multi-task circular deadlocks and prints out all affected locks and tasks (and only those tasks).”…””}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kehj’ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj1ubeh}”(h]”h ]”h"]”h$]”h&]”jjuh1j<h³hÊh´K_hj-ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6h³hÊh´K_hjh²hubhÌ)”}”(hŒ§Mutexes - and most other sleeping locks like rwsems - do not provide an implicit reference for the memory they occupy, which reference is released with mutex_unlock().”h]”hŒ§Mutexes - and most other sleeping locks like rwsems - do not provide an implicit reference for the memory they occupy, which reference is released with mutex_unlock().”…””}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhjh²hubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hŒÚ[ This is in contrast with spin_unlock() [or completion_done()], which APIs can be used to guarantee that the memory is not touched by the lock implementation after spin_unlock()/completion_done() releases the lock. ] ”h]”(hŒterm”“”)”}”(hŒF[ This is in contrast with spin_unlock() [or completion_done()], which”h]”hŒF[ This is in contrast with spin_unlock() [or completion_done()], which”…””}”(hjÑh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÏh³hÊh´KohjËubhŒ definition”“”)”}”(hhh]”hÌ)”}”(hŒ’APIs can be used to guarantee that the memory is not touched by the lock implementation after spin_unlock()/completion_done() releases the lock. ]”h]”hŒ’APIs can be used to guarantee that the memory is not touched by the lock implementation after spin_unlock()/completion_done() releases the lock. ]”…””}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kmhjáubah}”(h]”h ]”h"]”h$]”h&]”uh1jßhjËubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÉh³hÊh´KohjÆubah}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjh²hh³hÊh´NubhÌ)”}”(hŒïmutex_unlock() may access the mutex structure even after it has internally released the lock already - so it's not safe for another context to acquire the mutex and assume that the mutex_unlock() context is not using the structure anymore.”h]”hŒñmutex_unlock() may access the mutex structure even after it has internally released the lock already - so it’s not safe for another context to acquire the mutex and assume that the mutex_unlock() context is not using the structure anymore.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kqhjh²hubhÌ)”}”(hŒßThe mutex user must ensure that the mutex is not destroyed while a release operation is still in progress - in other words, callers of mutex_unlock() must ensure that the mutex stays alive until mutex_unlock() has returned.”h]”hŒßThe mutex user must ensure that the mutex is not destroyed while a release operation is still in progress - in other words, callers of mutex_unlock() must ensure that the mutex stays alive until mutex_unlock() has returned.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kvhjh²hubeh}”(h]”Œ semantics”ah ]”h"]”Œ semantics”ah$]”h&]”uh1hµhh·h²hh³hÊh´KLubh¶)”}”(hhh]”(h»)”}”(hŒ Interfaces”h]”hŒ Interfaces”…””}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj(h²hh³hÊh´K|ubhÌ)”}”(hŒStatically define the mutex::”h]”hŒStatically define the mutex:”…””}”(hj9h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K}hj(h²hubhŒ literal_block”“”)”}”(hŒDEFINE_MUTEX(name);”h]”hŒDEFINE_MUTEX(name);”…””}”hjIsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jGh³hÊh´Khj(h²hubhÌ)”}”(hŒ"Dynamically initialize the mutex::”h]”hŒ!Dynamically initialize the mutex:”…””}”(hjYh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khj(h²hubjH)”}”(hŒmutex_init(mutex);”h]”hŒmutex_init(mutex);”…””}”hjgsbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´Kƒhj(h²hubhÌ)”}”(hŒ$Acquire the mutex, uninterruptible::”h]”hŒ#Acquire the mutex, uninterruptible:”…””}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K…hj(h²hubjH)”}”(hŒvoid mutex_lock(struct mutex *lock); void mutex_lock_nested(struct mutex *lock, unsigned int subclass); int mutex_trylock(struct mutex *lock);”h]”hŒvoid mutex_lock(struct mutex *lock); void mutex_lock_nested(struct mutex *lock, unsigned int subclass); int mutex_trylock(struct mutex *lock);”…””}”hjƒsbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´K‡hj(h²hubhÌ)”}”(hŒ"Acquire the mutex, interruptible::”h]”hŒ!Acquire the mutex, interruptible:”…””}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K‹hj(h²hubjH)”}”(hŒ¥int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); int mutex_lock_interruptible(struct mutex *lock);”h]”hŒ¥int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); int mutex_lock_interruptible(struct mutex *lock);”…””}”hjŸsbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´Khj(h²hubhÌ)”}”(hŒ/Acquire the mutex, interruptible, if dec to 0::”h]”hŒ.Acquire the mutex, interruptible, if dec to 0:”…””}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K‘hj(h²hubjH)”}”(hŒAint atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);”h]”hŒAint atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);”…””}”hj»sbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´K“hj(h²hubhÌ)”}”(hŒUnlock the mutex::”h]”hŒUnlock the mutex:”…””}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K•hj(h²hubjH)”}”(hŒ&void mutex_unlock(struct mutex *lock);”h]”hŒ&void mutex_unlock(struct mutex *lock);”…””}”hj×sbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´K—hj(h²hubhÌ)”}”(hŒTest if the mutex is taken::”h]”hŒTest if the mutex is taken:”…””}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K™hj(h²hubjH)”}”(hŒ(int mutex_is_locked(struct mutex *lock);”h]”hŒ(int mutex_is_locked(struct mutex *lock);”…””}”hjósbah}”(h]”h ]”h"]”h$]”h&]”jWjXuh1jGh³hÊh´K›hj(h²hubeh}”(h]”Œ interfaces”ah ]”h"]”Œ interfaces”ah$]”h&]”uh1hµhh·h²hh³hÊh´K|ubh¶)”}”(hhh]”(h»)”}”(hŒ Disadvantages”h]”hŒ Disadvantages”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj h²hh³hÊh´KžubhÌ)”}”(hXUnlike its original design and purpose, 'struct mutex' is among the largest locks in the kernel. E.g: on x86-64 it is 32 bytes, where 'struct semaphore' is 24 bytes and rw_semaphore is 40 bytes. Larger structure sizes mean more CPU cache and memory footprint.”h]”hX Unlike its original design and purpose, ‘struct mutex’ is among the largest locks in the kernel. E.g: on x86-64 it is 32 bytes, where ‘struct semaphore’ is 24 bytes and rw_semaphore is 40 bytes. Larger structure sizes mean more CPU cache and memory footprint.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hj h²hubeh}”(h]”Œ disadvantages”ah ]”h"]”Œ disadvantages”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kžubh¶)”}”(hhh]”(h»)”}”(hŒWhen to use mutexes”h]”hŒWhen to use mutexes”…””}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj0h²hh³hÊh´K¦ubhÌ)”}”(hŒ¨Unless the strict semantics of mutexes are unsuitable and/or the critical region prevents the lock from being shared, always prefer them to any other locking primitive.”h]”hŒ¨Unless the strict semantics of mutexes are unsuitable and/or the critical region prevents the lock from being shared, always prefer them to any other locking primitive.”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¨hj0h²hubeh}”(h]”Œwhen-to-use-mutexes”ah ]”h"]”Œwhen to use mutexes”ah$]”h&]”uh1hµhh·h²hh³hÊh´K¦ubeh}”(h]”Œgeneric-mutex-subsystem”ah ]”h"]”Œgeneric mutex subsystem”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\jYjTjQjjj%j"jjj-j*jTjQuŒ nametypes”}”(j\‰jT‰j‰j%‰j‰j-‰jT‰uh}”(jYh·jQjjjWj"jjj(j*j jQj0uŒ 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.