1 /* ----------------------------------------------------------------------------
3 * (c) The GHC Team, 2006-2009
7 * These are simple spin-only locks as opposed to Mutexes which
8 * probably spin for a while before blocking in the kernel. We use
9 * these when we are sure that all our threads are actively running on
10 * a CPU, eg. in the GC.
12 * TODO: measure whether we really need these, or whether Mutexes
13 * would do (and be a bit safer if a CPU becomes loaded).
15 * Do not #include this file directly: #include "Rts.h" instead.
17 * To understand the structure of the RTS headers, see the wiki:
18 * https://gitlab.haskell.org/ghc/ghc/wikis/commentary/source-tree/includes
20 * -------------------------------------------------------------------------- */
22 #include "rts/PosixSource.h"
25 #if defined(THREADED_RTS)
27 #if defined(PROF_SPIN)
29 ATTR_ALWAYS_INLINE
static inline bool try_acquire_spin_slow_path(SpinLock
* p
)
32 r
= cas((StgVolatilePtr
)&(p
->lock
), 1, 0);
33 if (r
== 0) RELAXED_ADD(&p
->spin
, 1);
37 #else /* !PROF_SPIN */
39 ATTR_ALWAYS_INLINE
static inline bool try_acquire_spin_slow_path(SpinLock
* p
)
44 // Here we first check if we can obtain the lock without trying to cas.
45 // The cas instruction will add extra inter-CPU traffic on most CPU
46 // architectures as it has to invalidate cache lines. Rather than adding
47 // this traffic in the spin loop, we rather restrict it to times when the
48 // lock might be available.
50 // We do not need to do this when PROF_SPIN is enabled, since we write to
51 // the lock in both cases (acquired/not acquired).
52 r
= RELAXED_LOAD(&p
->lock
);
54 r
= cas((StgVolatilePtr
)&(p
->lock
), 1, 0);
61 void acquire_spin_lock_slow_path(SpinLock
* p
)
64 for (uint32_t i
= 0; i
< SPIN_COUNT
; i
++) {
65 if (try_acquire_spin_slow_path(p
)) return;
68 IF_PROF_SPIN(RELAXED_ADD(&p
->yield
, 1));