d814c10c824547f2bb965f6d68b56761d9ec8069
[ghc-hetmet.git] / ghc / includes / Updates.h
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.h,v 1.15 1999/11/09 15:47:09 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Definitions related to updates.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #ifndef UPDATES_H
11 #define UPDATES_H
12
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
16    computation.
17    -------------------------------------------------------------------------- */
18
19 /* ToDo: overwrite slop words with something safe in case sanity checking 
20  *       is turned on.  
21  *       (I think the fancy version of the GC is supposed to do this too.)
22  */
23
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.
27  */
28
29 #ifdef TICKY_TICKY
30 # define UPD_IND(updclosure, heapptr) UPD_PERM_IND(updclosure,heapptr)
31 #else
32 # define UPD_IND(updclosure, heapptr) UPD_REAL_IND(updclosure,heapptr)
33 #endif
34
35 /* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
36    if you *really* need an IND use UPD_REAL_IND
37  */
38 #ifdef SMP
39 #define UPD_REAL_IND(updclosure, heapptr)                               \
40    {                                                                    \
41         const StgInfoTable *info;                                       \
42         if (Bdescr((P_)updclosure)->back != (bdescr *)BaseReg) {        \
43                 info = LOCK_CLOSURE(updclosure);                        \
44         } else {                                                        \
45                 info = updclosure->header.info;                         \
46         }                                                               \
47         AWAKEN_BQ(info,updclosure);                                     \
48         updateWithIndirection(info,                                     \
49                               (StgClosure *)updclosure,                 \
50                               (StgClosure *)heapptr);                   \
51    }
52 #else
53 #define UPD_REAL_IND(updclosure, heapptr)               \
54    {                                                    \
55         const StgInfoTable *info;                       \
56         info = ((StgClosure *)updclosure)->header.info; \
57         AWAKEN_BQ(info,updclosure);                     \
58         updateWithIndirection(info,                     \
59                               (StgClosure *)updclosure, \
60                               (StgClosure *)heapptr);   \
61    }
62 #endif
63
64 #if defined(PROFILING) || defined(TICKY_TICKY)
65 #define UPD_PERM_IND(updclosure, heapptr)                       \
66    {                                                            \
67         const StgInfoTable *info;                               \
68         info = ((StgClosure *)updclosure)->header.info;         \
69         AWAKEN_BQ(info,updclosure);                             \
70         updateWithPermIndirection(info,                         \
71                                   (StgClosure *)updclosure,     \
72                                   (StgClosure *)heapptr);       \
73    }
74 #endif
75
76 #ifdef SMP
77 #define UPD_IND_NOLOCK(updclosure, heapptr)                             \
78    {                                                                    \
79         const StgInfoTable *info;                                       \
80         info = updclosure->header.info;                                 \
81         AWAKEN_BQ(info,updclosure);                                     \
82         updateWithIndirection(info,                                     \
83                               (StgClosure *)updclosure,                 \
84                               (StgClosure *)heapptr);                   \
85    }
86 #else
87 #define UPD_IND_NOLOCK(updclosure,heapptr) UPD_IND(updclosure,heapptr)
88 #endif
89
90 /* -----------------------------------------------------------------------------
91    Awaken any threads waiting on this computation
92    -------------------------------------------------------------------------- */
93
94 extern void awakenBlockedQueue(StgTSO *q);
95
96 #define AWAKEN_BQ(info,closure)                                         \
97         if (info == &BLACKHOLE_BQ_info) {                               \
98              STGCALL1(awakenBlockedQueue,                               \
99                       ((StgBlockingQueue *)closure)->blocking_queue);   \
100         }
101
102
103 /* -----------------------------------------------------------------------------
104    Push an update frame on the stack.
105    -------------------------------------------------------------------------- */
106
107 #if defined(PROFILING)
108 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
109 #else
110 #define PUSH_STD_CCCS(frame)
111 #endif
112
113 extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info; 
114
115 #define PUSH_UPD_FRAME(target, Sp_offset)                       \
116         {                                                       \
117                 StgUpdateFrame *__frame;                        \
118                 TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
119                 __frame = (StgUpdateFrame *)(Sp + (Sp_offset)) - 1; \
120                 SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info);   \
121                 __frame->link = Su;                             \
122                 __frame->updatee = (StgClosure *)(target);      \
123                 PUSH_STD_CCCS(__frame);                         \
124                 Su = __frame;                                   \
125         }
126
127 /* -----------------------------------------------------------------------------
128    Entering CAFs
129
130    When a CAF is first entered, it creates a black hole in the heap,
131    and updates itself with an indirection to this new black hole.
132
133    We update the CAF with an indirection to a newly-allocated black
134    hole in the heap.  We also set the blocking queue on the newly
135    allocated black hole to be empty.
136
137    Why do we make a black hole in the heap when we enter a CAF?
138       
139        - for a  generational garbage collector, which needs a fast
140          test for whether an updatee is in an old generation or not
141
142        - for the parallel system, which can implement updates more
143          easily if the updatee is always in the heap. (allegedly).
144
145    When debugging, we maintain a separate CAF list so we can tell when
146    a CAF has been garbage collected.
147    -------------------------------------------------------------------------- */
148    
149 /* ToDo: only call newCAF when debugging. */
150
151 extern void newCAF(StgClosure*);
152
153 #define UPD_CAF(cafptr, bhptr)                                          \
154   {                                                                     \
155     LOCK_CLOSURE(cafptr);                                               \
156     ((StgInd *)cafptr)->indirectee   = (StgClosure *)(bhptr);           \
157     SET_INFO((StgInd *)cafptr,(const StgInfoTable*)&IND_STATIC_info);   \
158     STGCALL1(newCAF,(StgClosure *)cafptr);                              \
159   }
160
161 /* -----------------------------------------------------------------------------
162    Update-related prototypes
163    -------------------------------------------------------------------------- */
164
165 DLL_IMPORT_RTS extern STGFUN(Upd_frame_entry);
166
167 extern DLL_IMPORT_DATA const StgInfoTable PAP_info;
168 DLL_IMPORT_RTS STGFUN(PAP_entry);
169
170 EXTFUN_RTS(stg_update_PAP);
171
172 extern DLL_IMPORT_DATA const StgInfoTable AP_UPD_info;
173 DLL_IMPORT_RTS STGFUN(AP_UPD_entry);
174
175 extern DLL_IMPORT_DATA const StgInfoTable raise_info;
176
177 #endif /* UPDATES_H */