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