€•6wŒ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/arch/arm/vlocks”Œ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/arch/arm/vlocks”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ#/translations/it_IT/arch/arm/vlocks”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ#/translations/ja_JP/arch/arm/vlocks”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ#/translations/ko_KR/arch/arm/vlocks”Œ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/arch/arm/vlocks”Œ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Œ&vlocks for Bare-Metal Mutual Exclusion”h]”hŒ&vlocks for Bare-Metal Mutual Exclusion”…””}”(hh¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh£hžhhŸŒ=/var/lib/git/docbuild/linux/Documentation/arch/arm/vlocks.rst”h KubhŒ paragraph”“”)”}”(hŒVoting Locks, or "vlocks" provide a simple low-level mutual exclusion mechanism, with reasonable but minimal requirements on the memory system.”h]”hŒ“Voting Locks, or “vlocks†provide a simple low-level mutual exclusion mechanism, with reasonable but minimal requirements on the memory system.”…””}”(hh¹hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khh£hžhubh¸)”}”(hŒÞThese are intended to be used to coordinate critical activity among CPUs which are otherwise non-coherent, in situations where the hardware provides no other mechanism to support this and ordinary spinlocks cannot be used.”h]”hŒÞThese are intended to be used to coordinate critical activity among CPUs which are otherwise non-coherent, in situations where the hardware provides no other mechanism to support this and ordinary spinlocks cannot be used.”…””}”(hhÇhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K hh£hžhubh¸)”}”(hX2vlocks make use of the atomicity provided by the memory system for writes to a single memory location. To arbitrate, every CPU "votes for itself", by storing a unique number to a common memory location. The final value seen in that memory location when all the votes have been cast identifies the winner.”h]”hX6vlocks make use of the atomicity provided by the memory system for writes to a single memory location. To arbitrate, every CPU “votes for itselfâ€, by storing a unique number to a common memory location. The final value seen in that memory location when all the votes have been cast identifies the winner.”…””}”(hhÕhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khh£hžhubh¸)”}”(hŒßIn order to make sure that the election produces an unambiguous result in finite time, a CPU will only enter the election in the first place if no winner has been chosen and the election does not appear to have started yet.”h]”hŒßIn order to make sure that the election produces an unambiguous result in finite time, a CPU will only enter the election in the first place if no winner has been chosen and the election does not appear to have started yet.”…””}”(hhãhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khh£hžhubh¢)”}”(hhh]”(h§)”}”(hŒ Algorithm”h]”hŒ Algorithm”…””}”(hhôhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hhñhžhhŸh¶h Kubh¸)”}”(hŒJThe easiest way to explain the vlocks algorithm is with some pseudo-code::”h]”hŒIThe easiest way to explain the vlocks algorithm is with some pseudo-code:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KhhñhžhubhŒ literal_block”“”)”}”(hXUint currently_voting[NR_CPUS] = { 0, }; int last_vote = -1; /* no votes yet */ bool vlock_trylock(int this_cpu) { /* signal our desire to vote */ currently_voting[this_cpu] = 1; if (last_vote != -1) { /* someone already volunteered himself */ currently_voting[this_cpu] = 0; return false; /* not ourself */ } /* let's suggest ourself */ last_vote = this_cpu; currently_voting[this_cpu] = 0; /* then wait until everyone else is done voting */ for_each_cpu(i) { while (currently_voting[i] != 0) /* wait */; } /* result */ if (last_vote == this_cpu) return true; /* we won */ return false; } bool vlock_unlock(void) { last_vote = -1; }”h]”hXUint currently_voting[NR_CPUS] = { 0, }; int last_vote = -1; /* no votes yet */ bool vlock_trylock(int this_cpu) { /* signal our desire to vote */ currently_voting[this_cpu] = 1; if (last_vote != -1) { /* someone already volunteered himself */ currently_voting[this_cpu] = 0; return false; /* not ourself */ } /* let's suggest ourself */ last_vote = this_cpu; currently_voting[this_cpu] = 0; /* then wait until everyone else is done voting */ for_each_cpu(i) { while (currently_voting[i] != 0) /* wait */; } /* result */ if (last_vote == this_cpu) return true; /* we won */ return false; } bool vlock_unlock(void) { last_vote = -1; }”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jhŸh¶h K!hhñhžhubh¸)”}”(hŒ¿The currently_voting[] array provides a way for the CPUs to determine whether an election is in progress, and plays a role analogous to the "entering" array in Lamport's bakery algorithm [1].”h]”hŒÅThe currently_voting[] array provides a way for the CPUs to determine whether an election is in progress, and plays a role analogous to the “entering†array in Lamport’s bakery algorithm [1].”…””}”(hj"hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KDhhñhžhubh¸)”}”(hŒÚHowever, once the election has started, the underlying memory system atomicity is used to pick the winner. This avoids the need for a static priority rule to act as a tie-breaker, or any counters which could overflow.”h]”hŒÚHowever, once the election has started, the underlying memory system atomicity is used to pick the winner. This avoids the need for a static priority rule to act as a tie-breaker, or any counters which could overflow.”…””}”(hj0hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KHhhñhžhubh¸)”}”(hŒ©As long as the last_vote variable is globally visible to all CPUs, it will contain only one value that won't change once every CPU has cleared its currently_voting flag.”h]”hŒ«As long as the last_vote variable is globally visible to all CPUs, it will contain only one value that won’t change once every CPU has cleared its currently_voting flag.”…””}”(hj>hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KMhhñhžhubeh}”(h]”Œ algorithm”ah ]”h"]”Œ algorithm”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kubh¢)”}”(hhh]”(h§)”}”(hŒFeatures and limitations”h]”hŒFeatures and limitations”…””}”(hjWhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjThžhhŸh¶h KSubhŒ block_quote”“”)”}”(hX * vlocks are not intended to be fair. In the contended case, it is the _last_ CPU which attempts to get the lock which will be most likely to win. vlocks are therefore best suited to situations where it is necessary to pick a unique winner, but it does not matter which CPU actually wins. * Like other similar mechanisms, vlocks will not scale well to a large number of CPUs. vlocks can be cascaded in a voting hierarchy to permit better scaling if necessary, as in the following hypothetical example for 4096 CPUs:: /* first level: local election */ my_town = towns[(this_cpu >> 4) & 0xf]; I_won = vlock_trylock(my_town, this_cpu & 0xf); if (I_won) { /* we won the town election, let's go for the state */ my_state = states[(this_cpu >> 8) & 0xf]; I_won = vlock_lock(my_state, this_cpu & 0xf)); if (I_won) { /* and so on */ I_won = vlock_lock(the_whole_country, this_cpu & 0xf]; if (I_won) { /* ... */ } vlock_unlock(the_whole_country); } vlock_unlock(my_state); } vlock_unlock(my_town); ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hX!vlocks are not intended to be fair. In the contended case, it is the _last_ CPU which attempts to get the lock which will be most likely to win. vlocks are therefore best suited to situations where it is necessary to pick a unique winner, but it does not matter which CPU actually wins. ”h]”(h¸)”}”(hŒ‘vlocks are not intended to be fair. In the contended case, it is the _last_ CPU which attempts to get the lock which will be most likely to win.”h]”hŒ‘vlocks are not intended to be fair. In the contended case, it is the _last_ CPU which attempts to get the lock which will be most likely to win.”…””}”(hjvhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KUhjrubh¸)”}”(hŒvlocks are therefore best suited to situations where it is necessary to pick a unique winner, but it does not matter which CPU actually wins.”h]”hŒvlocks are therefore best suited to situations where it is necessary to pick a unique winner, but it does not matter which CPU actually wins.”…””}”(hj„hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KYhjrubeh}”(h]”h ]”h"]”h$]”h&]”uh1jphjmubjq)”}”(hX¯Like other similar mechanisms, vlocks will not scale well to a large number of CPUs. vlocks can be cascaded in a voting hierarchy to permit better scaling if necessary, as in the following hypothetical example for 4096 CPUs:: /* first level: local election */ my_town = towns[(this_cpu >> 4) & 0xf]; I_won = vlock_trylock(my_town, this_cpu & 0xf); if (I_won) { /* we won the town election, let's go for the state */ my_state = states[(this_cpu >> 8) & 0xf]; I_won = vlock_lock(my_state, this_cpu & 0xf)); if (I_won) { /* and so on */ I_won = vlock_lock(the_whole_country, this_cpu & 0xf]; if (I_won) { /* ... */ } vlock_unlock(the_whole_country); } vlock_unlock(my_state); } vlock_unlock(my_town); ”h]”(h¸)”}”(hŒTLike other similar mechanisms, vlocks will not scale well to a large number of CPUs.”h]”hŒTLike other similar mechanisms, vlocks will not scale well to a large number of CPUs.”…””}”(hjœhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K]hj˜ubh¸)”}”(hŒŒvlocks can be cascaded in a voting hierarchy to permit better scaling if necessary, as in the following hypothetical example for 4096 CPUs::”h]”hŒ‹vlocks can be cascaded in a voting hierarchy to permit better scaling if necessary, as in the following hypothetical example for 4096 CPUs:”…””}”(hjªhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K`hj˜ubj)”}”(hXo/* first level: local election */ my_town = towns[(this_cpu >> 4) & 0xf]; I_won = vlock_trylock(my_town, this_cpu & 0xf); if (I_won) { /* we won the town election, let's go for the state */ my_state = states[(this_cpu >> 8) & 0xf]; I_won = vlock_lock(my_state, this_cpu & 0xf)); if (I_won) { /* and so on */ I_won = vlock_lock(the_whole_country, this_cpu & 0xf]; if (I_won) { /* ... */ } vlock_unlock(the_whole_country); } vlock_unlock(my_state); } vlock_unlock(my_town);”h]”hXo/* first level: local election */ my_town = towns[(this_cpu >> 4) & 0xf]; I_won = vlock_trylock(my_town, this_cpu & 0xf); if (I_won) { /* we won the town election, let's go for the state */ my_state = states[(this_cpu >> 8) & 0xf]; I_won = vlock_lock(my_state, this_cpu & 0xf)); if (I_won) { /* and so on */ I_won = vlock_lock(the_whole_country, this_cpu & 0xf]; if (I_won) { /* ... */ } vlock_unlock(the_whole_country); } vlock_unlock(my_state); } vlock_unlock(my_town);”…””}”hj¸sbah}”(h]”h ]”h"]”h$]”h&]”j j!uh1jhŸh¶h Kchj˜ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jphjmubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1jkhŸh¶h KUhjgubah}”(h]”h ]”h"]”h$]”h&]”uh1jehŸh¶h KUhjThžhubeh}”(h]”Œfeatures-and-limitations”ah ]”h"]”Œfeatures and limitations”ah$]”h&]”uh1h¡hh£hžhhŸh¶h KSubh¢)”}”(hhh]”(h§)”}”(hŒARM implementation”h]”hŒARM implementation”…””}”(hjåhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjâhžhhŸh¶h Kxubh¸)”}”(hŒZThe current ARM implementation [2] contains some optimisations beyond the basic algorithm:”h]”hŒZThe current ARM implementation [2] contains some optimisations beyond the basic algorithm:”…””}”(hjóhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kzhjâhžhubjf)”}”(hXÉ * By packing the members of the currently_voting array close together, we can read the whole array in one transaction (providing the number of CPUs potentially contending the lock is small enough). This reduces the number of round-trips required to external memory. In the ARM implementation, this means that we can use a single load and comparison:: LDR Rt, [Rn] CMP Rt, #0 ...in place of code equivalent to:: LDRB Rt, [Rn] CMP Rt, #0 LDRBEQ Rt, [Rn, #1] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #2] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #3] CMPEQ Rt, #0 This cuts down on the fast-path latency, as well as potentially reducing bus contention in contended cases. The optimisation relies on the fact that the ARM memory system guarantees coherency between overlapping memory accesses of different sizes, similarly to many other architectures. Note that we do not care which element of currently_voting appears in which bits of Rt, so there is no need to worry about endianness in this optimisation. If there are too many CPUs to read the currently_voting array in one transaction then multiple transactions are still required. The implementation uses a simple loop of word-sized loads for this case. The number of transactions is still fewer than would be required if bytes were loaded individually. In principle, we could aggregate further by using LDRD or LDM, but to keep the code simple this was not attempted in the initial implementation. * vlocks are currently only used to coordinate between CPUs which are unable to enable their caches yet. This means that the implementation removes many of the barriers which would be required when executing the algorithm in cached memory. packing of the currently_voting array does not work with cached memory unless all CPUs contending the lock are cache-coherent, due to cache writebacks from one CPU clobbering values written by other CPUs. (Though if all the CPUs are cache-coherent, you should be probably be using proper spinlocks instead anyway). * The "no votes yet" value used for the last_vote variable is 0 (not -1 as in the pseudocode). This allows statically-allocated vlocks to be implicitly initialised to an unlocked state simply by putting them in .bss. An offset is added to each CPU's ID for the purpose of setting this variable, so that no CPU uses the value 0 for its ID. ”h]”jl)”}”(hhh]”(jq)”}”(hXæBy packing the members of the currently_voting array close together, we can read the whole array in one transaction (providing the number of CPUs potentially contending the lock is small enough). This reduces the number of round-trips required to external memory. In the ARM implementation, this means that we can use a single load and comparison:: LDR Rt, [Rn] CMP Rt, #0 ...in place of code equivalent to:: LDRB Rt, [Rn] CMP Rt, #0 LDRBEQ Rt, [Rn, #1] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #2] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #3] CMPEQ Rt, #0 This cuts down on the fast-path latency, as well as potentially reducing bus contention in contended cases. The optimisation relies on the fact that the ARM memory system guarantees coherency between overlapping memory accesses of different sizes, similarly to many other architectures. Note that we do not care which element of currently_voting appears in which bits of Rt, so there is no need to worry about endianness in this optimisation. If there are too many CPUs to read the currently_voting array in one transaction then multiple transactions are still required. The implementation uses a simple loop of word-sized loads for this case. The number of transactions is still fewer than would be required if bytes were loaded individually. In principle, we could aggregate further by using LDRD or LDM, but to keep the code simple this was not attempted in the initial implementation. ”h]”(h¸)”}”(hXBy packing the members of the currently_voting array close together, we can read the whole array in one transaction (providing the number of CPUs potentially contending the lock is small enough). This reduces the number of round-trips required to external memory.”h]”hXBy packing the members of the currently_voting array close together, we can read the whole array in one transaction (providing the number of CPUs potentially contending the lock is small enough). This reduces the number of round-trips required to external memory.”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K}hjubh¸)”}”(hŒTIn the ARM implementation, this means that we can use a single load and comparison::”h]”hŒSIn the ARM implementation, this means that we can use a single load and comparison:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K‚hjubj)”}”(hŒLDR Rt, [Rn] CMP Rt, #0”h]”hŒLDR Rt, [Rn] CMP Rt, #0”…””}”hj(sbah}”(h]”h ]”h"]”h$]”h&]”j j!uh1jhŸh¶h K…hjubh¸)”}”(hŒ#...in place of code equivalent to::”h]”hŒ"...in place of code equivalent to:”…””}”(hj6hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kˆhjubj)”}”(hŒ‹LDRB Rt, [Rn] CMP Rt, #0 LDRBEQ Rt, [Rn, #1] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #2] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #3] CMPEQ Rt, #0”h]”hŒ‹LDRB Rt, [Rn] CMP Rt, #0 LDRBEQ Rt, [Rn, #1] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #2] CMPEQ Rt, #0 LDRBEQ Rt, [Rn, #3] CMPEQ Rt, #0”…””}”hjDsbah}”(h]”h ]”h"]”h$]”h&]”j j!uh1jhŸh¶h KŠhjubh¸)”}”(hŒkThis cuts down on the fast-path latency, as well as potentially reducing bus contention in contended cases.”h]”hŒkThis cuts down on the fast-path latency, as well as potentially reducing bus contention in contended cases.”…””}”(hjRhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K“hjubh¸)”}”(hXOThe optimisation relies on the fact that the ARM memory system guarantees coherency between overlapping memory accesses of different sizes, similarly to many other architectures. Note that we do not care which element of currently_voting appears in which bits of Rt, so there is no need to worry about endianness in this optimisation.”h]”hXOThe optimisation relies on the fact that the ARM memory system guarantees coherency between overlapping memory accesses of different sizes, similarly to many other architectures. Note that we do not care which element of currently_voting appears in which bits of Rt, so there is no need to worry about endianness in this optimisation.”…””}”(hj`hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K–hjubh¸)”}”(hX.If there are too many CPUs to read the currently_voting array in one transaction then multiple transactions are still required. The implementation uses a simple loop of word-sized loads for this case. The number of transactions is still fewer than would be required if bytes were loaded individually.”h]”hX.If there are too many CPUs to read the currently_voting array in one transaction then multiple transactions are still required. The implementation uses a simple loop of word-sized loads for this case. The number of transactions is still fewer than would be required if bytes were loaded individually.”…””}”(hjnhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Khjubh¸)”}”(hŒIn principle, we could aggregate further by using LDRD or LDM, but to keep the code simple this was not attempted in the initial implementation.”h]”hŒIn principle, we could aggregate further by using LDRD or LDM, but to keep the code simple this was not attempted in the initial implementation.”…””}”(hj|hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K¤hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jphjubjq)”}”(hX-vlocks are currently only used to coordinate between CPUs which are unable to enable their caches yet. This means that the implementation removes many of the barriers which would be required when executing the algorithm in cached memory. packing of the currently_voting array does not work with cached memory unless all CPUs contending the lock are cache-coherent, due to cache writebacks from one CPU clobbering values written by other CPUs. (Though if all the CPUs are cache-coherent, you should be probably be using proper spinlocks instead anyway). ”h]”(h¸)”}”(hŒîvlocks are currently only used to coordinate between CPUs which are unable to enable their caches yet. This means that the implementation removes many of the barriers which would be required when executing the algorithm in cached memory.”h]”hŒîvlocks are currently only used to coordinate between CPUs which are unable to enable their caches yet. This means that the implementation removes many of the barriers which would be required when executing the algorithm in cached memory.”…””}”(hj”hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K©hjubh¸)”}”(hX;packing of the currently_voting array does not work with cached memory unless all CPUs contending the lock are cache-coherent, due to cache writebacks from one CPU clobbering values written by other CPUs. (Though if all the CPUs are cache-coherent, you should be probably be using proper spinlocks instead anyway).”h]”hX;packing of the currently_voting array does not work with cached memory unless all CPUs contending the lock are cache-coherent, due to cache writebacks from one CPU clobbering values written by other CPUs. (Though if all the CPUs are cache-coherent, you should be probably be using proper spinlocks instead anyway).”…””}”(hj¢hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h K®hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jphjubjq)”}”(hXTThe "no votes yet" value used for the last_vote variable is 0 (not -1 as in the pseudocode). This allows statically-allocated vlocks to be implicitly initialised to an unlocked state simply by putting them in .bss. An offset is added to each CPU's ID for the purpose of setting this variable, so that no CPU uses the value 0 for its ID. ”h]”(h¸)”}”(hŒ×The "no votes yet" value used for the last_vote variable is 0 (not -1 as in the pseudocode). This allows statically-allocated vlocks to be implicitly initialised to an unlocked state simply by putting them in .bss.”h]”hŒÛThe “no votes yet†value used for the last_vote variable is 0 (not -1 as in the pseudocode). This allows statically-allocated vlocks to be implicitly initialised to an unlocked state simply by putting them in .bss.”…””}”(hjºhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kµhj¶ubh¸)”}”(hŒyAn offset is added to each CPU's ID for the purpose of setting this variable, so that no CPU uses the value 0 for its ID.”h]”hŒ{An offset is added to each CPU’s ID for the purpose of setting this variable, so that no CPU uses the value 0 for its ID.”…””}”(hjÈhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h Kºhj¶ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jphjubeh}”(h]”h ]”h"]”h$]”h&]”jÒjÓuh1jkhŸh¶h K}hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jehŸh¶h K}hjâhžhubeh}”(h]”Œarm-implementation”ah ]”h"]”Œarm implementation”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kxubh¢)”}”(hhh]”(h§)”}”(hŒColophon”h]”hŒColophon”…””}”(hjóhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjðhžhhŸh¶h K¿ubh¸)”}”(hX.Originally created and documented by Dave Martin for Linaro Limited, for use in ARM-based big.LITTLE platforms, with review and input gratefully received from Nicolas Pitre and Achin Gupta. Thanks to Nicolas for grabbing most of this text out of the relevant mail thread and writing up the pseudocode.”h]”hX.Originally created and documented by Dave Martin for Linaro Limited, for use in ARM-based big.LITTLE platforms, with review and input gratefully received from Nicolas Pitre and Achin Gupta. Thanks to Nicolas for grabbing most of this text out of the relevant mail thread and writing up the pseudocode.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KÁhjðhžhubh¸)”}”(hŒCopyright (C) 2012-2013 Linaro Limited Distributed under the terms of Version 2 of the GNU General Public License, as defined in linux/COPYING.”h]”hŒCopyright (C) 2012-2013 Linaro Limited Distributed under the terms of Version 2 of the GNU General Public License, as defined in linux/COPYING.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KÇhjðhžhubeh}”(h]”Œcolophon”ah ]”h"]”Œcolophon”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K¿ubh¢)”}”(hhh]”(h§)”}”(hŒ References”h]”hŒ References”…””}”(hj(hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj%hžhhŸh¶h KÍubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hŒÃ[1] Lamport, L. "A New Solution of Dijkstra's Concurrent Programming Problem", Communications of the ACM 17, 8 (August 1974), 453-455. https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm ”h]”(hŒterm”“”)”}”(hŒD[1] Lamport, L. "A New Solution of Dijkstra's Concurrent Programming”h]”hŒH[1] Lamport, L. “A New Solution of Dijkstra’s Concurrent Programming”…””}”(hjChžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jAhŸh¶h KÒhj=ubhŒ definition”“”)”}”(hhh]”(h¸)”}”(hŒAProblem", Communications of the ACM 17, 8 (August 1974), 453-455.”h]”hŒCProblemâ€, Communications of the ACM 17, 8 (August 1974), 453-455.”…””}”(hjVhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KÐhjSubh¸)”}”(hŒ:https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm”h]”hŒ reference”“”)”}”(hjfh]”hŒ:https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm”…””}”(hjjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”jfuh1jhhjdubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KÒhjSubeh}”(h]”h ]”h"]”h$]”h&]”uh1jQhj=ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j;hŸh¶h KÒhj8ubah}”(h]”h ]”h"]”h$]”h&]”uh1j6hj%hžhhŸh¶h Nubh¸)”}”(hŒ2[2] linux/arch/arm/common/vlock.S, www.kernel.org.”h]”hŒ2[2] linux/arch/arm/common/vlock.S, www.kernel.org.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hŸh¶h KÔhj%hžhubeh}”(h]”Œ references”ah ]”h"]”Œ references”ah$]”h&]”uh1h¡hh£hžhhŸh¶h KÍubeh}”(h]”Œ&vlocks-for-bare-metal-mutual-exclusion”ah ]”h"]”Œ&vlocks for bare-metal mutual exclusion”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¨jQjNjßjÜjíjêj"jj£j uŒ nametypes”}”(j«‰jQ‰j߉jí‰j"‰j£‰uh}”(j¨h£jNhñjÜjTjêjâjjðj j%uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.