€•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Œ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¦hhÿhž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).”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K hhÿhžhubh¸)”}”(hŒ$[1] https://lwn.net/Articles/164802/”h]”(hŒ[1] ”…””}”(hjhž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Áhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khhÿhž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”…””}”(hjFhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjChž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 ”…””}”(hjThžhhŸNh NubhŒtitle_reference”“”)”}”(hŒ`struct task_struct *`”h]”hŒstruct task_struct *”…””}”(hj^hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j\hjTubhX¬ 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).”…””}”(hjThžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KhjChž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:”…””}”(hjvhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K%hjChž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.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K(hj‹ubah}”(h]”h ]”h"]”h$]”h&]”uh1j‰hj†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&]”uh1j‰hj†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&]”uh1j‰hj†hžhhŸh¶h Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œ lowerroman”Œprefix”Œ(”Œsuffix”Œ)”uh1j„hjChž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.”…””}”(hjíhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KEhjChž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ŒDetects self-recursing locks and prints out all relevant info.”h]”h¸)”}”(hjih]”hŒ>Detects self-recursing locks and prints out all relevant info.”…””}”(hjkhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kdhjgubah}”(h]”h ]”h"]”h$]”h&]”uh1j‰hjubjŠ)”}”(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&]”uh1j‰hjubeh}”(h]”h ]”h"]”h$]”h&]”jjuh1j(hŸh¶h K_hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hŸ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.”…””}”(hjðhž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.”…””}”(hjþhž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”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjhžhhŸh¶h K|ubh¸)”}”(hŒStatically define the mutex::”h]”hŒStatically define the mutex:”…””}”(hj%hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K}hjhžhubhŒ literal_block”“”)”}”(hŒDEFINE_MUTEX(name);”h]”hŒDEFINE_MUTEX(name);”…””}”hj5sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1j3hŸh¶h Khjhžhubh¸)”}”(hŒ"Dynamically initialize the mutex::”h]”hŒ!Dynamically initialize the mutex:”…””}”(hjEhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khjhžhubj4)”}”(hŒmutex_init(mutex);”h]”hŒmutex_init(mutex);”…””}”hjSsbah}”(h]”h ]”h"]”h$]”h&]”jCjDuh1j3hŸh¶h Kƒhjhžhubh¸)”}”(hŒ$Acquire the mutex, uninterruptible::”h]”hŒ#Acquire the mutex, uninterruptible:”…””}”(hjahžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K…hjhžhubj4)”}”(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);”…””}”hjosbah}”(h]”h ]”h"]”h$]”h&]”jCjDuh1j3hŸh¶h K‡hjhž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‹hjhžhubj4)”}”(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&]”jCjDuh1j3hŸh¶h Khjhž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‘hjhžhubj4)”}”(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&]”jCjDuh1j3hŸh¶h K“hjhž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•hjhžhubj4)”}”(hŒ&void mutex_unlock(struct mutex *lock);”h]”hŒ&void mutex_unlock(struct mutex *lock);”…””}”hjÃsbah}”(h]”h ]”h"]”h$]”h&]”jCjDuh1j3hŸh¶h K—hjhž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™hjhžhubj4)”}”(hŒ(int mutex_is_locked(struct mutex *lock);”h]”hŒ(int mutex_is_locked(struct mutex *lock);”…””}”hjßsbah}”(h]”h ]”h"]”h$]”h&]”jCjDuh1j3hŸh¶h K›hjhž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”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjhž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.”…””}”(hj-hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K¨hjhž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”jnŒ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”}”(jHjEj@j=jjýjjjòjïjjj@j=uŒ nametypes”}”(jH‰j@‰j‰j‰jò‰j‰j@‰uh}”(jEh£j=hÿjýjCjjjïjjjõj=juŒ 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.