Small refactor to mkRuntimErrorId
[ghc.git] / includes / rts / storage / SMPClosureOps.h
1 /* ----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2005-2013
4 *
5 * Macros for THREADED_RTS support
6 *
7 * -------------------------------------------------------------------------- */
8
9 #ifndef RTS_STORAGE_SMPCLOSUREOPS_H
10 #define RTS_STORAGE_SMPCLOSUREOPS_H
11
12 #ifdef CMINUSMINUS
13
14 /* Lock closure, equivalent to ccall lockClosure but the condition is inlined.
15 * Arguments are swapped for uniformity with unlockClosure. */
16 #if defined(THREADED_RTS)
17 #define LOCK_CLOSURE(closure, info) \
18 if (CInt[n_capabilities] == 1 :: CInt) { \
19 info = GET_INFO(closure); \
20 } else { \
21 ("ptr" info) = ccall reallyLockClosure(closure "ptr"); \
22 }
23 #else
24 #define LOCK_CLOSURE(closure, info) info = GET_INFO(closure)
25 #endif
26
27 #define unlockClosure(ptr,info) \
28 prim_write_barrier; \
29 StgHeader_info(ptr) = info;
30
31 #else
32
33 INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p);
34 EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p);
35 EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p);
36 EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info);
37
38 #if defined(THREADED_RTS)
39
40 /* -----------------------------------------------------------------------------
41 * Locking/unlocking closures
42 *
43 * This is used primarily in the implementation of MVars.
44 * -------------------------------------------------------------------------- */
45
46 // We want a callable copy of reallyLockClosure() so that we can refer to it
47 // from .cmm files compiled using the native codegen, so these are given
48 // EXTERN_INLINE. C-- should use LOCK_CLOSURE not lockClosure, so we've
49 // kept it INLINE_HEADER.
50 EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p)
51 {
52 StgWord info;
53 do {
54 uint32_t i = 0;
55 do {
56 info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
57 if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info;
58 } while (++i < SPIN_COUNT);
59 yieldThread();
60 } while (1);
61 }
62
63 INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p)
64 {
65 if (n_capabilities == 1) {
66 return (StgInfoTable *)p->header.info;
67 }
68 else {
69 return reallyLockClosure(p);
70 }
71 }
72
73 // ToDo: consider splitting tryLockClosure into reallyTryLockClosure,
74 // same as lockClosure
75 EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p)
76 {
77 StgWord info;
78 if (n_capabilities == 1) {
79 return (StgInfoTable *)p->header.info;
80 }
81 else {
82 info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
83 if (info != (W_)&stg_WHITEHOLE_info) {
84 return (StgInfoTable *)info;
85 } else {
86 return NULL;
87 }
88 }
89 }
90
91 #else /* !THREADED_RTS */
92
93 EXTERN_INLINE StgInfoTable *
94 reallyLockClosure(StgClosure *p)
95 { return (StgInfoTable *)p->header.info; }
96
97 INLINE_HEADER StgInfoTable *
98 lockClosure(StgClosure *p)
99 { return (StgInfoTable *)p->header.info; }
100
101 EXTERN_INLINE StgInfoTable *
102 tryLockClosure(StgClosure *p)
103 { return (StgInfoTable *)p->header.info; }
104
105 #endif /* THREADED_RTS */
106
107 EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info)
108 {
109 // This is a strictly ordered write, so we need a write_barrier():
110 write_barrier();
111 p->header.info = info;
112 }
113
114 // Handy specialised versions of lockClosure()/unlockClosure()
115 INLINE_HEADER void lockTSO(StgTSO *tso);
116 INLINE_HEADER void lockTSO(StgTSO *tso)
117 { lockClosure((StgClosure *)tso); }
118
119 INLINE_HEADER void unlockTSO(StgTSO *tso);
120 INLINE_HEADER void unlockTSO(StgTSO *tso)
121 { unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); }
122
123 #endif /* CMINUSMINUS */
124
125 #endif /* RTS_STORAGE_SMPCLOSUREOPS_H */