[project @ 2005-05-27 14:47:08 by tharris]
[ghc-hetmet.git] / ghc / includes / SMP.h
1 /* ----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 2005
4  *
5  * Macros for SMP support
6  *
7  * -------------------------------------------------------------------------- */
8
9 #ifndef SMP_H
10 #define SMP_H
11
12 /* SMP is currently not compatible with the following options:
13  *
14  *      INTERPRETER
15  *      PROFILING
16  *      TICKY_TICKY
17  *      and unregisterised builds.
18  */
19
20 #if defined(SMP)
21
22 #if  defined(PROFILING)  || defined(TICKY_TICKY)
23 #error Build options incompatible with SMP.
24 #endif
25
26 /* 
27  * XCHG - the atomic exchange instruction.  Used for locking closures
28  * during updates (see LOCK_CLOSURE below) and the MVar primops.
29  *
30  * NB: the xchg instruction is implicitly locked, so we do not need
31  * a lock prefix here. 
32  */
33 INLINE_HEADER StgWord
34 xchg(StgPtr p, StgWord w)
35 {
36     StgWord result;
37     result = w;
38     __asm__ __volatile__ (
39           "xchg %1,%0"
40           :"+r" (result), "+m" (*p)
41           : /* no input-only operands */
42         );
43     return result;
44 }
45
46 /* 
47  * CMPXCHG - the single-word atomic compare-and-exchange instruction.  Used 
48  * in the STM implementation.
49  */
50 INLINE_HEADER StgWord
51 cas(StgVolatilePtr p, StgWord o, StgWord n)
52 {
53     __asm__ __volatile__ (
54           "lock cmpxchg %3,%1"
55           :"=a"(o), "=m" (*(volatile unsigned int *)p) 
56           :"0" (o), "r" (n));
57     return o;
58 }
59
60 INLINE_HEADER StgInfoTable *
61 lockClosure(StgClosure *p)
62 {
63 #if i386_HOST_ARCH || x86_64_HOST_ARCH
64     StgWord info;
65     do {
66         info = xchg((P_)&p->header.info, (W_)&stg_WHITEHOLE_info);
67         if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info;
68         yieldThread();
69     } while (1);
70 #else
71    ACQUIRE_SM_LOCK
72 #endif
73 }
74
75 INLINE_HEADER void
76 unlockClosure(StgClosure *p, StgInfoTable *info)
77 {
78 #if i386_HOST_ARCH || x86_64_HOST_ARCH
79     // This is safe enough, because lockClosure() does the memory barrier:
80     p->header.info = info;
81 #else
82     RELEASE_SM_LOCK;
83 #endif
84 }
85
86 #endif /* SMP */
87
88 #endif /* SMP_H */