[project @ 1999-01-18 15:21:37 by simonm]
[ghc-hetmet.git] / ghc / includes / Updates.h
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.h,v 1.5 1999/01/18 15:21:42 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    Awaken any threads waiting on this computation
35    -------------------------------------------------------------------------- */
36
37 extern void awaken_blocked_queue(StgTSO *q);
38
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);             \
44                 }                                                       \
45         }
46
47
48 /* -----------------------------------------------------------------------------
49    Push an update frame on the stack.
50    -------------------------------------------------------------------------- */
51
52 #if defined(PROFILING)
53 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
54 #else
55 #define PUSH_STD_CCCS(frame)
56 #endif
57
58 extern const StgPolyInfoTable Upd_frame_info; 
59
60 #define PUSH_UPD_FRAME(target, Sp_offset)                       \
61         {                                                       \
62                 StgUpdateFrame *__frame;                        \
63                 TICK_UPDF_PUSHED();                             \
64                 __frame = stgCast(StgUpdateFrame*,Sp + (Sp_offset)) - 1; \
65                 SET_INFO(__frame,stgCast(StgInfoTable*,&Upd_frame_info));   \
66                 __frame->link = Su;                             \
67                 __frame->updatee = (StgClosure *)(target);      \
68                 PUSH_STD_CCCS(__frame);                         \
69                 Su = __frame;                                   \
70         }
71
72 /* -----------------------------------------------------------------------------
73    Entering CAFs
74
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.
77
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.
81
82    Why do we make a black hole in the heap when we enter a CAF?
83       
84        - for a  generational garbage collector, which needs a fast
85          test for whether an updatee is in an old generation or not
86
87        - for the parallel system, which can implement updates more
88          easily if the updatee is always in the heap. (allegedly).
89
90    When debugging, we maintain a separate CAF list so we can tell when
91    a CAF has been garbage collected.
92    -------------------------------------------------------------------------- */
93    
94 /* ToDo: only call newCAF when debugging. */
95
96 extern void newCAF(StgClosure*);
97
98 #define UPD_CAF(cafptr, bhptr)                                  \
99   {                                                             \
100     SET_INFO((StgInd *)cafptr,&IND_STATIC_info);                \
101     ((StgInd *)cafptr)->indirectee   = (StgClosure *)(bhptr);   \
102     STGCALL1(newCAF,(StgClosure *)cafptr);                      \
103   }
104
105 /* -----------------------------------------------------------------------------
106    Update-related prototypes
107    -------------------------------------------------------------------------- */
108
109 extern STGFUN(Upd_frame_entry);
110
111 extern const StgInfoTable PAP_info;
112 STGFUN(PAP_entry);
113
114 EXTFUN(stg_update_PAP);
115
116 extern const StgInfoTable AP_UPD_info;
117 STGFUN(AP_UPD_entry);
118
119 extern const StgInfoTable raise_info;
120
121 #endif /* UPDATES_H */