RTS tidyup sweep, first phase
[ghc.git] / includes / rts / SpinLock.h
1 /* ----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2006-2008
4 *
5 * Spin locks
6 *
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.
11 *
12 * TODO: measure whether we really need these, or whether Mutexes
13 * would do (and be a bit safer if a CPU becomes loaded).
14 *
15 * -------------------------------------------------------------------------- */
16
17 #ifndef RTS_SPINLOCK_H
18 #define RTS_SPINLOCK_H
19
20 #if defined(THREADED_RTS)
21
22 #if defined(PROF_SPIN)
23 typedef struct SpinLock_
24 {
25 StgWord lock;
26 StgWord64 spin; // DEBUG version counts how much it spins
27 } SpinLock;
28 #else
29 typedef StgWord SpinLock;
30 #endif
31
32 typedef lnat SpinLockCount;
33
34
35 #if defined(PROF_SPIN)
36
37 // PROF_SPIN enables counting the number of times we spin on a lock
38
39 // acquire spin lock
40 INLINE_HEADER void ACQUIRE_SPIN_LOCK(SpinLock * p)
41 {
42 StgWord32 r = 0;
43 spin:
44 r = cas((StgVolatilePtr)&(p->lock), 1, 0);
45 if (r == 0) {
46 p->spin++;
47 goto spin;
48 }
49 }
50
51 // release spin lock
52 INLINE_HEADER void RELEASE_SPIN_LOCK(SpinLock * p)
53 {
54 write_barrier();
55 p->lock = 1;
56 }
57
58 // initialise spin lock
59 INLINE_HEADER void initSpinLock(SpinLock * p)
60 {
61 write_barrier();
62 p->lock = 1;
63 p->spin = 0;
64 }
65
66 #else
67
68 // acquire spin lock
69 INLINE_HEADER void ACQUIRE_SPIN_LOCK(SpinLock * p)
70 {
71 StgWord32 r = 0;
72 do {
73 r = cas((StgVolatilePtr)p, 1, 0);
74 } while(r == 0);
75 }
76
77 // release spin lock
78 INLINE_HEADER void RELEASE_SPIN_LOCK(SpinLock * p)
79 {
80 write_barrier();
81 (*p) = 1;
82 }
83
84 // init spin lock
85 INLINE_HEADER void initSpinLock(SpinLock * p)
86 {
87 write_barrier();
88 (*p) = 1;
89 }
90
91 #endif /* PROF_SPIN */
92
93 #else /* !THREADED_RTS */
94
95 // Using macros here means we don't have to ensure the argument is in scope
96 #define ACQUIRE_SPIN_LOCK(p) /* nothing */
97 #define RELEASE_SPIN_LOCK(p) /* nothing */
98
99 INLINE_HEADER void initSpinLock(void * p STG_UNUSED)
100 { /* nothing */ }
101
102 #endif /* THREADED_RTS */
103
104 #endif /* RTS_SPINLOCK_H */
105