1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.h,v 1.5 1999/01/18 15:21:42 simonm Exp $
4 * Definitions related to updates.
6 * ---------------------------------------------------------------------------*/
11 /* -----------------------------------------------------------------------------
12 Update a closure with an indirection. This may also involve waking
13 up a queue of blocked threads waiting on the result of this
15 -------------------------------------------------------------------------- */
17 /* ToDo: overwrite slop words with something safe in case sanity checking
19 * (I think the fancy version of the GC is supposed to do this too.)
22 /* This expands to a fair chunk of code, what with waking up threads
23 * and checking whether we're updating something in a old generation.
24 * preferably don't use this macro inline in compiled code.
27 #define UPD_IND(updclosure, heapptr) \
28 TICK_UPDATED_SET_UPDATED(updclosure); \
29 AWAKEN_BQ(updclosure); \
30 updateWithIndirection((StgClosure *)updclosure, \
31 (StgClosure *)heapptr);
33 /* -----------------------------------------------------------------------------
34 Awaken any threads waiting on this computation
35 -------------------------------------------------------------------------- */
37 extern void awaken_blocked_queue(StgTSO *q);
39 #define AWAKEN_BQ(closure) \
40 if (closure->header.info == &BLACKHOLE_BQ_info) { \
41 StgTSO *bq = ((StgBlockingQueue *)closure)->blocking_queue;\
42 if (bq != (StgTSO *)&END_TSO_QUEUE_closure) { \
43 STGCALL1(awaken_blocked_queue, bq); \
48 /* -----------------------------------------------------------------------------
49 Push an update frame on the stack.
50 -------------------------------------------------------------------------- */
52 #if defined(PROFILING)
53 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
55 #define PUSH_STD_CCCS(frame)
58 extern const StgPolyInfoTable Upd_frame_info;
60 #define PUSH_UPD_FRAME(target, Sp_offset) \
62 StgUpdateFrame *__frame; \
64 __frame = stgCast(StgUpdateFrame*,Sp + (Sp_offset)) - 1; \
65 SET_INFO(__frame,stgCast(StgInfoTable*,&Upd_frame_info)); \
67 __frame->updatee = (StgClosure *)(target); \
68 PUSH_STD_CCCS(__frame); \
72 /* -----------------------------------------------------------------------------
75 When a CAF is first entered, it creates a black hole in the heap,
76 and updates itself with an indirection to this new black hole.
78 We update the CAF with an indirection to a newly-allocated black
79 hole in the heap. We also set the blocking queue on the newly
80 allocated black hole to be empty.
82 Why do we make a black hole in the heap when we enter a CAF?
84 - for a generational garbage collector, which needs a fast
85 test for whether an updatee is in an old generation or not
87 - for the parallel system, which can implement updates more
88 easily if the updatee is always in the heap. (allegedly).
90 When debugging, we maintain a separate CAF list so we can tell when
91 a CAF has been garbage collected.
92 -------------------------------------------------------------------------- */
94 /* ToDo: only call newCAF when debugging. */
96 extern void newCAF(StgClosure*);
98 #define UPD_CAF(cafptr, bhptr) \
100 SET_INFO((StgInd *)cafptr,&IND_STATIC_info); \
101 ((StgInd *)cafptr)->indirectee = (StgClosure *)(bhptr); \
102 STGCALL1(newCAF,(StgClosure *)cafptr); \
105 /* -----------------------------------------------------------------------------
106 Update-related prototypes
107 -------------------------------------------------------------------------- */
109 extern STGFUN(Upd_frame_entry);
111 extern const StgInfoTable PAP_info;
114 EXTFUN(stg_update_PAP);
116 extern const StgInfoTable AP_UPD_info;
117 STGFUN(AP_UPD_entry);
119 extern const StgInfoTable raise_info;
121 #endif /* UPDATES_H */