findPtr: don't search the nursery
[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 #if defined(PROF_SPIN)
42 extern volatile StgWord64 whitehole_lockClosure_spin;
43 extern volatile StgWord64 whitehole_lockClosure_yield;
44 #endif
45
46 /* -----------------------------------------------------------------------------
47 * Locking/unlocking closures
48 *
49 * This is used primarily in the implementation of MVars.
50 * -------------------------------------------------------------------------- */
51
52 // We want a callable copy of reallyLockClosure() so that we can refer to it
53 // from .cmm files compiled using the native codegen, so these are given
54 // EXTERN_INLINE. C-- should use LOCK_CLOSURE not lockClosure, so we've
55 // kept it INLINE_HEADER.
56 EXTERN_INLINE StgInfoTable *reallyLockClosure(StgClosure *p)
57 {
58 StgWord info;
59 do {
60 uint32_t i = 0;
61 do {
62 info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
63 if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info;
64 #if defined(PROF_SPIN)
65 ++whitehole_lockClosure_spin;
66 #endif
67 busy_wait_nop();
68 } while (++i < SPIN_COUNT);
69 #if defined(PROF_SPIN)
70 ++whitehole_lockClosure_yield;
71 #endif
72 yieldThread();
73 } while (1);
74 }
75
76 INLINE_HEADER StgInfoTable *lockClosure(StgClosure *p)
77 {
78 if (n_capabilities == 1) {
79 return (StgInfoTable *)p->header.info;
80 }
81 else {
82 return reallyLockClosure(p);
83 }
84 }
85
86 // ToDo: consider splitting tryLockClosure into reallyTryLockClosure,
87 // same as lockClosure
88 EXTERN_INLINE StgInfoTable *tryLockClosure(StgClosure *p)
89 {
90 StgWord info;
91 if (n_capabilities == 1) {
92 return (StgInfoTable *)p->header.info;
93 }
94 else {
95 info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info);
96 if (info != (W_)&stg_WHITEHOLE_info) {
97 return (StgInfoTable *)info;
98 } else {
99 return NULL;
100 }
101 }
102 }
103
104 #else /* !THREADED_RTS */
105
106 EXTERN_INLINE StgInfoTable *
107 reallyLockClosure(StgClosure *p)
108 { return (StgInfoTable *)p->header.info; }
109
110 INLINE_HEADER StgInfoTable *
111 lockClosure(StgClosure *p)
112 { return (StgInfoTable *)p->header.info; }
113
114 EXTERN_INLINE StgInfoTable *
115 tryLockClosure(StgClosure *p)
116 { return (StgInfoTable *)p->header.info; }
117
118 #endif /* THREADED_RTS */
119
120 EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info)
121 {
122 // This is a strictly ordered write, so we need a write_barrier():
123 write_barrier();
124 p->header.info = info;
125 }
126
127 // Handy specialised versions of lockClosure()/unlockClosure()
128 INLINE_HEADER void lockTSO(StgTSO *tso);
129 INLINE_HEADER void lockTSO(StgTSO *tso)
130 { lockClosure((StgClosure *)tso); }
131
132 INLINE_HEADER void unlockTSO(StgTSO *tso);
133 INLINE_HEADER void unlockTSO(StgTSO *tso)
134 { unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); }
135
136 #endif /* CMINUSMINUS */
137
138 #include "EndPrivate.h"