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