perf: Key the interpreter symbol cache by Name rather than FastString
[ghc.git] / rts / SpinLock.c
blob1e86860f112a241053e654ad1b4241a217f8135e
1 /* ----------------------------------------------------------------------------
3 * (c) The GHC Team, 2006-2009
5 * Spin locks
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"
23 #include "Rts.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)
31 StgWord r;
32 r = cas((StgVolatilePtr)&(p->lock), 1, 0);
33 if (r == 0) RELAXED_ADD(&p->spin, 1);
34 return r != 0;
37 #else /* !PROF_SPIN */
39 ATTR_ALWAYS_INLINE static inline bool try_acquire_spin_slow_path(SpinLock * p)
41 StgWord r;
42 // Note
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);
53 if (r != 0) {
54 r = cas((StgVolatilePtr)&(p->lock), 1, 0);
56 return r != 0;
59 #endif
61 void acquire_spin_lock_slow_path(SpinLock * p)
63 do {
64 for (uint32_t i = 0; i < SPIN_COUNT; i++) {
65 if (try_acquire_spin_slow_path(p)) return;
66 busy_wait_nop();
68 IF_PROF_SPIN(RELAXED_ADD(&p->yield, 1));
69 yieldThread();
70 } while (1);
73 #endif