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