1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.h,v 1.14 1999/11/02 15:05:53 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Definitions related to updates.
8 * ---------------------------------------------------------------------------*/
13 /* -----------------------------------------------------------------------------
14 Update a closure with an indirection. This may also involve waking
15 up a queue of blocked threads waiting on the result of this
17 -------------------------------------------------------------------------- */
19 /* ToDo: overwrite slop words with something safe in case sanity checking
21 * (I think the fancy version of the GC is supposed to do this too.)
24 /* This expands to a fair chunk of code, what with waking up threads
25 * and checking whether we're updating something in a old generation.
26 * preferably don't use this macro inline in compiled code.
30 # define UPD_IND(updclosure, heapptr) UPD_PERM_IND(updclosure,heapptr)
32 # define UPD_IND(updclosure, heapptr) UPD_REAL_IND(updclosure,heapptr)
35 /* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
36 if you *really* need an IND use UPD_REAL_IND
39 #define UPD_REAL_IND(updclosure, heapptr) \
41 const StgInfoTable *info; \
42 info = LOCK_CLOSURE(updclosure); \
44 if (info == &BLACKHOLE_BQ_info) { \
45 STGCALL1(awakenBlockedQueue, \
46 ((StgBlockingQueue *)updclosure)->blocking_queue); \
48 updateWithIndirection((StgClosure *)updclosure, \
49 (StgClosure *)heapptr); \
52 #define UPD_REAL_IND(updclosure, heapptr) \
53 AWAKEN_BQ(updclosure); \
54 updateWithIndirection((StgClosure *)updclosure, \
55 (StgClosure *)heapptr);
58 #if defined(PROFILING) || defined(TICKY_TICKY)
59 #define UPD_PERM_IND(updclosure, heapptr) \
60 AWAKEN_BQ(updclosure); \
61 updateWithPermIndirection((StgClosure *)updclosure, \
62 (StgClosure *)heapptr);
65 /* -----------------------------------------------------------------------------
66 Awaken any threads waiting on this computation
67 -------------------------------------------------------------------------- */
69 extern void awakenBlockedQueue(StgTSO *q);
71 #define AWAKEN_BQ(closure) \
72 if (closure->header.info == &BLACKHOLE_BQ_info) { \
73 STGCALL1(awakenBlockedQueue, \
74 ((StgBlockingQueue *)closure)->blocking_queue); \
78 /* -----------------------------------------------------------------------------
79 Push an update frame on the stack.
80 -------------------------------------------------------------------------- */
82 #if defined(PROFILING)
83 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
85 #define PUSH_STD_CCCS(frame)
88 extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info;
90 #define PUSH_UPD_FRAME(target, Sp_offset) \
92 StgUpdateFrame *__frame; \
93 TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
94 __frame = (StgUpdateFrame *)(Sp + (Sp_offset)) - 1; \
95 SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info); \
97 __frame->updatee = (StgClosure *)(target); \
98 PUSH_STD_CCCS(__frame); \
102 /* -----------------------------------------------------------------------------
105 When a CAF is first entered, it creates a black hole in the heap,
106 and updates itself with an indirection to this new black hole.
108 We update the CAF with an indirection to a newly-allocated black
109 hole in the heap. We also set the blocking queue on the newly
110 allocated black hole to be empty.
112 Why do we make a black hole in the heap when we enter a CAF?
114 - for a generational garbage collector, which needs a fast
115 test for whether an updatee is in an old generation or not
117 - for the parallel system, which can implement updates more
118 easily if the updatee is always in the heap. (allegedly).
120 When debugging, we maintain a separate CAF list so we can tell when
121 a CAF has been garbage collected.
122 -------------------------------------------------------------------------- */
124 /* ToDo: only call newCAF when debugging. */
126 extern void newCAF(StgClosure*);
128 #define UPD_CAF(cafptr, bhptr) \
130 LOCK_CLOSURE(cafptr); \
131 ((StgInd *)cafptr)->indirectee = (StgClosure *)(bhptr); \
132 SET_INFO((StgInd *)cafptr,(const StgInfoTable*)&IND_STATIC_info); \
133 STGCALL1(newCAF,(StgClosure *)cafptr); \
136 /* -----------------------------------------------------------------------------
137 Update-related prototypes
138 -------------------------------------------------------------------------- */
140 DLL_IMPORT_RTS extern STGFUN(Upd_frame_entry);
142 extern DLL_IMPORT_DATA const StgInfoTable PAP_info;
143 DLL_IMPORT_RTS STGFUN(PAP_entry);
145 EXTFUN_RTS(stg_update_PAP);
147 extern DLL_IMPORT_DATA const StgInfoTable AP_UPD_info;
148 DLL_IMPORT_RTS STGFUN(AP_UPD_entry);
150 extern DLL_IMPORT_DATA const StgInfoTable raise_info;
152 #endif /* UPDATES_H */