1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-1999
5 * Weak pointers / finalizers
7 * ---------------------------------------------------------------------------*/
9 #include "PosixSource.h"
20 runCFinalizers(StgCFinalizerList
*list
)
22 StgCFinalizerList
*head
;
24 (StgClosure
*)head
!= &stg_NO_FINALIZER_closure
;
25 head
= (StgCFinalizerList
*)head
->link
)
28 ((void (*)(void *, void *))head
->fptr
)(head
->eptr
, head
->ptr
);
30 ((void (*)(void *))head
->fptr
)(head
->ptr
);
35 runAllCFinalizers(StgWeak
*list
)
42 task
->running_finalizers
= rtsTrue
;
45 for (w
= list
; w
; w
= w
->link
) {
46 runCFinalizers((StgCFinalizerList
*)w
->cfinalizers
);
50 task
->running_finalizers
= rtsFalse
;
55 * scheduleFinalizers() is called on the list of weak pointers found
56 * to be dead after a garbage collection. It overwrites each object
57 * with DEAD_WEAK, and creates a new thread to run the pending finalizers.
59 * This function is called just after GC. The weak pointers on the
60 * argument list are those whose keys were found to be not reachable,
61 * however the value and finalizer fields have by now been marked live.
62 * The weak pointer object itself may not be alive - i.e. we may be
63 * looking at either an object in from-space or one in to-space. It
64 * doesn't really matter either way.
66 * Pre-condition: sched_mutex _not_ held.
70 scheduleFinalizers(Capability
*cap
, StgWeak
*list
)
81 task
->running_finalizers
= rtsTrue
;
84 // count number of finalizers, and kill all the weak pointers first...
86 for (w
= list
; w
; w
= w
->link
) {
87 // Better not be a DEAD_WEAK at this stage; the garbage
88 // collector removes DEAD_WEAKs from the weak pointer list.
89 ASSERT(w
->header
.info
!= &stg_DEAD_WEAK_info
);
91 if (w
->finalizer
!= &stg_NO_FINALIZER_closure
) {
95 runCFinalizers((StgCFinalizerList
*)w
->cfinalizers
);
98 // A weak pointer is inherently used, so we do not need to call
101 // Furthermore, when PROFILING is turned on, dead weak
102 // pointers are exactly as large as weak pointers, so there is
103 // no need to fill the slop, either. See stg_DEAD_WEAK_info
104 // in StgMiscClosures.hc.
106 SET_HDR(w
, &stg_DEAD_WEAK_info
, w
->header
.prof
.ccs
);
110 task
->running_finalizers
= rtsFalse
;
113 // No finalizers to run?
116 debugTrace(DEBUG_weak
, "weak: batching %d finalizers", n
);
118 size
= n
+ mutArrPtrsCardTableSize(n
);
119 arr
= (StgMutArrPtrs
*)allocate(cap
, sizeofW(StgMutArrPtrs
) + size
);
120 TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs
), n
, 0);
121 SET_HDR(arr
, &stg_MUT_ARR_PTRS_FROZEN_info
, CCS_SYSTEM
);
126 for (w
= list
; w
; w
= w
->link
) {
127 if (w
->finalizer
!= &stg_NO_FINALIZER_closure
) {
128 arr
->payload
[n
] = w
->finalizer
;
132 // set all the cards to 1
133 for (i
= n
; i
< size
; i
++) {
134 arr
->payload
[i
] = (StgClosure
*)(W_
)(-1);
137 t
= createIOThread(cap
,
138 RtsFlags
.GcFlags
.initialStkSize
,
141 (StgClosure
*)runFinalizerBatch_closure
,
145 scheduleThread(cap
,t
);