[project @ 1999-11-02 15:05:38 by simonmar]
[ghc-hetmet.git] / ghc / includes / Updates.h
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.h,v 1.14 1999/11/02 15:05:53 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         info = LOCK_CLOSURE(updclosure);                \
43                                                         \
44         if (info == &BLACKHOLE_BQ_info) {                               \
45            STGCALL1(awakenBlockedQueue,                                 \
46                     ((StgBlockingQueue *)updclosure)->blocking_queue);  \
47         }                                               \
48         updateWithIndirection((StgClosure *)updclosure,         \
49                               (StgClosure *)heapptr);           \
50    }
51 #else
52 #define UPD_REAL_IND(updclosure, heapptr)               \
53         AWAKEN_BQ(updclosure);                          \
54         updateWithIndirection((StgClosure *)updclosure, \
55                               (StgClosure *)heapptr);
56 #endif
57
58 #if defined(PROFILING) || defined(TICKY_TICKY)
59 #define UPD_PERM_IND(updclosure, heapptr)                       \
60         AWAKEN_BQ(updclosure);                                  \
61         updateWithPermIndirection((StgClosure *)updclosure,     \
62                                   (StgClosure *)heapptr);
63 #endif
64
65 /* -----------------------------------------------------------------------------
66    Awaken any threads waiting on this computation
67    -------------------------------------------------------------------------- */
68
69 extern void awakenBlockedQueue(StgTSO *q);
70
71 #define AWAKEN_BQ(closure)                                               \
72         if (closure->header.info == &BLACKHOLE_BQ_info) {                \
73                 STGCALL1(awakenBlockedQueue,                             \
74                          ((StgBlockingQueue *)closure)->blocking_queue); \
75         }
76
77
78 /* -----------------------------------------------------------------------------
79    Push an update frame on the stack.
80    -------------------------------------------------------------------------- */
81
82 #if defined(PROFILING)
83 #define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
84 #else
85 #define PUSH_STD_CCCS(frame)
86 #endif
87
88 extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info; 
89
90 #define PUSH_UPD_FRAME(target, Sp_offset)                       \
91         {                                                       \
92                 StgUpdateFrame *__frame;                        \
93                 TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
94                 __frame = (StgUpdateFrame *)(Sp + (Sp_offset)) - 1; \
95                 SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info);   \
96                 __frame->link = Su;                             \
97                 __frame->updatee = (StgClosure *)(target);      \
98                 PUSH_STD_CCCS(__frame);                         \
99                 Su = __frame;                                   \
100         }
101
102 /* -----------------------------------------------------------------------------
103    Entering CAFs
104
105    When a CAF is first entered, it creates a black hole in the heap,
106    and updates itself with an indirection to this new black hole.
107
108    We update the CAF with an indirection to a newly-allocated black
109    hole in the heap.  We also set the blocking queue on the newly
110    allocated black hole to be empty.
111
112    Why do we make a black hole in the heap when we enter a CAF?
113       
114        - for a  generational garbage collector, which needs a fast
115          test for whether an updatee is in an old generation or not
116
117        - for the parallel system, which can implement updates more
118          easily if the updatee is always in the heap. (allegedly).
119
120    When debugging, we maintain a separate CAF list so we can tell when
121    a CAF has been garbage collected.
122    -------------------------------------------------------------------------- */
123    
124 /* ToDo: only call newCAF when debugging. */
125
126 extern void newCAF(StgClosure*);
127
128 #define UPD_CAF(cafptr, bhptr)                                          \
129   {                                                                     \
130     LOCK_CLOSURE(cafptr);                                               \
131     ((StgInd *)cafptr)->indirectee   = (StgClosure *)(bhptr);           \
132     SET_INFO((StgInd *)cafptr,(const StgInfoTable*)&IND_STATIC_info);   \
133     STGCALL1(newCAF,(StgClosure *)cafptr);                              \
134   }
135
136 /* -----------------------------------------------------------------------------
137    Update-related prototypes
138    -------------------------------------------------------------------------- */
139
140 DLL_IMPORT_RTS extern STGFUN(Upd_frame_entry);
141
142 extern DLL_IMPORT_DATA const StgInfoTable PAP_info;
143 DLL_IMPORT_RTS STGFUN(PAP_entry);
144
145 EXTFUN_RTS(stg_update_PAP);
146
147 extern DLL_IMPORT_DATA const StgInfoTable AP_UPD_info;
148 DLL_IMPORT_RTS STGFUN(AP_UPD_entry);
149
150 extern DLL_IMPORT_DATA const StgInfoTable raise_info;
151
152 #endif /* UPDATES_H */