[project @ 2005-03-27 13:41:13 by panne]
[ghc-hetmet.git] / ghc / includes / SMP.h
1 /* ----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1999
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  * CMPXCHG - this instruction is the standard "test & set".  We use it
28  * for locking closures in the thunk and blackhole entry code.  If the
29  * closure is already locked, or has an unexpected info pointer
30  * (because another thread is altering it in parallel), we just jump
31  * to the new entry point.
32  */
33 #if defined(i386_HOST_ARCH) && defined(TABLES_NEXT_TO_CODE)
34 #define CMPXCHG(p, cmp, new)                    \
35   __asm__ __volatile__ (                        \
36           "lock ; cmpxchg %1, %0\n"             \
37           "\tje 1f\n"                           \
38           "\tjmp *%%eax\n"                      \
39           "\t1:\n"                              \
40           : /* no outputs */                    \
41           : "m" (p), "r" (new), "r" (cmp)       \
42           )
43
44 /* 
45  * XCHG - the atomic exchange instruction.  Used for locking closures
46  * during updates (see LOCK_CLOSURE below) and the MVar primops.
47  */
48 #define XCHG(reg, obj)                          \
49   __asm__ __volatile__ (                        \
50           "xchgl %1,%0"                         \
51           :"+r" (reg), "+m" (obj)               \
52           : /* no input-only operands */        \
53           )
54
55 #else
56 #error SMP macros not defined for this architecture
57 #endif
58
59 /*
60  * LOCK_CLOSURE locks the specified closure, busy waiting for any
61  * existing locks to be cleared.
62  */
63 #define LOCK_CLOSURE(c)                                 \
64   ({                                                    \
65     const StgInfoTable *__info;                         \
66     __info = &stg_WHITEHOLE_info;                       \
67     do {                                                \
68       XCHG(__info,((StgClosure *)(c))->header.info);    \
69     } while (__info == &stg_WHITEHOLE_info);            \
70     __info;                                             \
71   })
72
73 #define LOCK_THUNK(__info)                              \
74   CMPXCHG(R1.cl->header.info, __info, &stg_WHITEHOLE_info);
75
76 #else /* !SMP */
77
78 #define LOCK_CLOSURE(c)     /* nothing */
79 #define LOCK_THUNK(__info)  /* nothing */
80
81 #endif /* SMP */
82
83 #endif /* SMP_H */