RTS tidyup sweep, first phase
[ghc-hetmet.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