diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-10-29 16:14:29 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-10-30 14:02:19 -0400 |
commit | 105d43db7bb7f399be3e5474d207e330d1b2da5a (patch) | |
tree | 7503c1b1f78e841d6439e2aec745f3b39c54bf11 /rts/SpinLock.c | |
parent | a80cc8577774a744d684cd1f513e373405cd2f2b (diff) | |
download | haskell-105d43db7bb7f399be3e5474d207e330d1b2da5a.tar.gz |
rts/SpinLock: Separate out slow path
Not only is this in general a good idea, but it turns out that GCC
unrolls the retry loop, resulting is massive code bloat in critical
parts of the RTS (e.g. `evacuate`).
Diffstat (limited to 'rts/SpinLock.c')
-rw-r--r-- | rts/SpinLock.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/rts/SpinLock.c b/rts/SpinLock.c new file mode 100644 index 0000000000..314918257f --- /dev/null +++ b/rts/SpinLock.c @@ -0,0 +1,41 @@ +/* ---------------------------------------------------------------------------- + * + * (c) The GHC Team, 2006-2009 + * + * Spin locks + * + * These are simple spin-only locks as opposed to Mutexes which + * probably spin for a while before blocking in the kernel. We use + * these when we are sure that all our threads are actively running on + * a CPU, eg. in the GC. + * + * TODO: measure whether we really need these, or whether Mutexes + * would do (and be a bit safer if a CPU becomes loaded). + * + * Do not #include this file directly: #include "Rts.h" instead. + * + * To understand the structure of the RTS headers, see the wiki: + * https://gitlab.haskell.org/ghc/ghc/wikis/commentary/source-tree/includes + * + * -------------------------------------------------------------------------- */ + +#include "PosixSource.h" +#include "Rts.h" + +#if defined(THREADED_RTS) + +void acquire_spin_lock_slow_path(SpinLock * p) +{ + do { + for (uint32_t i = 0; i < SPIN_COUNT; i++) { + StgWord32 r = cas((StgVolatilePtr)&(p->lock), 1, 0); + if (r != 0) return; + IF_PROF_SPIN(__atomic_fetch_add(&p->spin, 1, __ATOMIC_RELAXED)); + busy_wait_nop(); + } + IF_PROF_SPIN(__atomic_fetch_add(&p->yield, 1, __ATOMIC_RELAXED)); + yieldThread(); + } while (1); +} + +#endif |