proxygen
MicroLock.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/MicroLock.h>
18 #include <thread>
19 
20 #include <folly/portability/Asm.h>
21 
22 namespace folly {
23 
25  uint32_t oldWord,
26  detail::Futex<>* wordPtr,
27  uint32_t slotHeldBit,
28  unsigned maxSpins,
29  unsigned maxYields) {
30  uint32_t newWord;
31  unsigned spins = 0;
32  uint32_t slotWaitBit = slotHeldBit << 1;
33  uint32_t needWaitBit = 0;
34 
35 retry:
36  if ((oldWord & slotHeldBit) != 0) {
37  ++spins;
38  if (spins > maxSpins + maxYields) {
39  // Somebody appears to have the lock. Block waiting for the
40  // holder to unlock the lock. We set heldbit(slot) so that the
41  // lock holder knows to FUTEX_WAKE us.
42  newWord = oldWord | slotWaitBit;
43  if (newWord != oldWord) {
44  if (!wordPtr->compare_exchange_weak(
45  oldWord,
46  newWord,
47  std::memory_order_relaxed,
48  std::memory_order_relaxed)) {
49  goto retry;
50  }
51  }
52  detail::futexWait(wordPtr, newWord, slotHeldBit);
53  needWaitBit = slotWaitBit;
54  } else if (spins > maxSpins) {
55  // sched_yield(), but more portable
57  } else {
59  }
60  oldWord = wordPtr->load(std::memory_order_relaxed);
61  goto retry;
62  }
63 
64  newWord = oldWord | slotHeldBit | needWaitBit;
65  if (!wordPtr->compare_exchange_weak(
66  oldWord,
67  newWord,
68  std::memory_order_acquire,
69  std::memory_order_relaxed)) {
70  goto retry;
71  }
72 }
73 } // namespace folly
static constexpr StringPiece retry
Atom< std::uint32_t > Futex
Definition: Futex.h:51
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
FutexResult futexWait(const Futex *futex, uint32_t expected, uint32_t waitMask)
Definition: Futex-inl.h:100
static void lockSlowPath(uint32_t oldWord, detail::Futex<> *wordPtr, uint32_t slotHeldBit, unsigned maxSpins, unsigned maxYields)
Definition: MicroLock.cpp:24
void asm_volatile_pause()
Definition: Asm.h:37