[project @ 2002-02-04 20:10:47 by sof]
[ghc-hetmet.git] / ghc / includes / SMP.h
1 /* ----------------------------------------------------------------------------
2  * $Id: SMP.h,v 1.4 2002/02/04 20:10:47 sof Exp $
3  *
4  * (c) The GHC Team, 1999
5  *
6  * Macros for SMP support
7  *
8  * -------------------------------------------------------------------------- */
9
10 #ifndef SMP_H
11 #define SMP_H
12
13 /* SMP is currently not compatible with the following options:
14  *
15  *      INTERPRETER
16  *      PROFILING
17  *      TICKY_TICKY
18  *      and unregisterised builds.
19  */
20
21 #if defined(SMP)
22
23 #if  defined(PROFILING)  || defined(TICKY_TICKY)
24 #error Build options incompatible with SMP.
25 #endif
26
27 /*
28  * CMPXCHG - this instruction is the standard "test & set".  We use it
29  * for locking closures in the thunk and blackhole entry code.  If the
30  * closure is already locked, or has an unexpected info pointer
31  * (because another thread is altering it in parallel), we just jump
32  * to the new entry point.
33  */
34 #if defined(i386_TARGET_ARCH) && defined(TABLES_NEXT_TO_CODE)
35 #define CMPXCHG(p, cmp, new)                    \
36   __asm__ __volatile__ (                        \
37           "lock ; cmpxchg %1, %0\n"             \
38           "\tje 1f\n"                           \
39           "\tjmp *%%eax\n"                      \
40           "\t1:\n"                              \
41           : /* no outputs */                    \
42           : "m" (p), "r" (new), "r" (cmp)       \
43           )
44
45 /* 
46  * XCHG - the atomic exchange instruction.  Used for locking closures
47  * during updates (see LOCK_CLOSURE below) and the MVar primops.
48  */
49 #define XCHG(reg, obj)                          \
50   __asm__ __volatile__ (                        \
51           "xchgl %1,%0"                         \
52           :"+r" (reg), "+m" (obj)               \
53           : /* no input-only operands */        \
54           )
55
56 #else
57 #error SMP macros not defined for this architecture
58 #endif
59
60 /*
61  * LOCK_CLOSURE locks the specified closure, busy waiting for any
62  * existing locks to be cleared.
63  */
64 #define LOCK_CLOSURE(c)                                 \
65   ({                                                    \
66     const StgInfoTable *__info;                         \
67     __info = &stg_WHITEHOLE_info;                       \
68     do {                                                \
69       XCHG(__info,((StgClosure *)(c))->header.info);    \
70     } while (__info == &stg_WHITEHOLE_info);            \
71     __info;                                             \
72   })
73
74 #define LOCK_THUNK(__info)                              \
75   CMPXCHG(R1.cl->header.info, __info, &stg_WHITEHOLE_info);
76
77 #else /* !SMP */
78
79 #define LOCK_CLOSURE(c)     /* nothing */
80 #define LOCK_THUNK(__info)  /* nothing */
81
82 #endif /* SMP */
83
84 #endif /* SMP_H */