3a599c220b8c563c2a107897204c67803f031297
[ghc-hetmet.git] / ghc / includes / Updates.h
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.h,v 1.3 1999/01/13 17:25:55 simonm Exp $
3  *
4  * Definitions related to updates.
5  *
6  * ---------------------------------------------------------------------------*/
7
8 #ifndef UPDATES_H
9 #define UPDATES_H
10
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
14    computation.
15    -------------------------------------------------------------------------- */
16
17 /* ToDo: overwrite slop words with something safe in case sanity checking 
18  *       is turned on.  
19  *       (I think the fancy version of the GC is supposed to do this too.)
20  */
21
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.
25  */
26
27 #define UPD_IND(updclosure, heapptr)                            \
28         TICK_UPDATED_SET_UPDATED(updclosure);                   \
29         AWAKEN_BQ(updclosure);                                  \
30         updateWithIndirection((StgClosure *)updclosure,         \
31                               (StgClosure *)heapptr);
32
33 /* -----------------------------------------------------------------------------
34    Update a closure inplace with an infotable that expects 1 (closure)
35    argument.
36    Also may wake up BQs.
37    -------------------------------------------------------------------------- */
38
39 #define UPD_INPLACE1(updclosure,info,c0)                        \
40         TICK_UPDATED_SET_UPDATED(updclosure);                   \
41         AWAKEN_BQ(updclosure);                                  \
42         SET_INFO(updclosure,info);                              \
43         payloadCPtr(updclosure,0) = (c0)
44
45 /* -----------------------------------------------------------------------------
46    Awaken any threads waiting on this computation
47    -------------------------------------------------------------------------- */
48
49 extern void awaken_blocked_queue(StgTSO *q);
50
51 #define AWAKEN_BQ(closure)                                              \
52         if (closure->header.info == &BLACKHOLE_info) {                  \
53                 StgTSO *bq = ((StgBlackHole *)closure)->blocking_queue; \
54                 if (bq != (StgTSO *)&END_TSO_QUEUE_closure) {           \
55                         STGCALL1(awaken_blocked_queue, bq);             \
56                 }                                                       \
57         }
58
59
60 /* -----------------------------------------------------------------------------
61    Push an update frame on the stack.
62    -------------------------------------------------------------------------- */
63
64 #if defined(PROFILING)
65 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
66 #else
67 #define PUSH_STD_CCCS(frame)
68 #endif
69
70 extern const StgPolyInfoTable Upd_frame_info; 
71
72 #define PUSH_UPD_FRAME(target, Sp_offset)                       \
73         {                                                       \
74                 StgUpdateFrame *__frame;                        \
75                 TICK_UPDF_PUSHED();                             \
76                 __frame = stgCast(StgUpdateFrame*,Sp + (Sp_offset)) - 1; \
77                 SET_INFO(__frame,stgCast(StgInfoTable*,&Upd_frame_info));   \
78                 __frame->link = Su;                             \
79                 __frame->updatee = (StgClosure *)(target);      \
80                 PUSH_STD_CCCS(__frame);                         \
81                 Su = __frame;                                   \
82         }
83
84 /* -----------------------------------------------------------------------------
85    Entering CAFs
86
87    When a CAF is first entered, it creates a black hole in the heap,
88    and updates itself with an indirection to this new black hole.
89
90    We update the CAF with an indirection to a newly-allocated black
91    hole in the heap.  We also set the blocking queue on the newly
92    allocated black hole to be empty.
93
94    Why do we make a black hole in the heap when we enter a CAF?
95       
96        - for a  generational garbage collector, which needs a fast
97          test for whether an updatee is in an old generation or not
98
99        - for the parallel system, which can implement updates more
100          easily if the updatee is always in the heap. (allegedly).
101
102    When debugging, we maintain a separate CAF list so we can tell when
103    a CAF has been garbage collected.
104    -------------------------------------------------------------------------- */
105    
106 /* ToDo: only call newCAF when debugging. */
107
108 extern void newCAF(StgClosure*);
109
110 #define UPD_CAF(cafptr, bhptr)                                  \
111   {                                                             \
112     SET_INFO((StgInd *)cafptr,&IND_STATIC_info);                \
113     ((StgInd *)cafptr)->indirectee   = (StgClosure *)(bhptr);   \
114     ((StgBlackHole *)(bhptr))->blocking_queue =                 \
115           (StgTSO *)&END_TSO_QUEUE_closure;                     \
116     STGCALL1(newCAF,(StgClosure *)cafptr);                      \
117   }
118
119 /* -----------------------------------------------------------------------------
120    Update-related prototypes
121    -------------------------------------------------------------------------- */
122
123 extern STGFUN(Upd_frame_entry);
124
125 extern const StgInfoTable PAP_info;
126 STGFUN(PAP_entry);
127
128 EXTFUN(stg_update_PAP);
129
130 extern const StgInfoTable AP_UPD_info;
131 STGFUN(AP_UPD_entry);
132
133 extern const StgInfoTable raise_info;
134
135 #endif /* UPDATES_H */