Weak.c 2.73 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2 3
 *
 * (c) The GHC Team, 1998-1999
4
 *
5
 * Weak pointers / finalizers
6 7 8
 *
 * ---------------------------------------------------------------------------*/

9
#include "PosixSource.h"
sof's avatar
sof committed
10
#define COMPILING_RTS_MAIN
11
#include "Rts.h"
12
#include "RtsUtils.h"
sof's avatar
sof committed
13
#include "SchedAPI.h"
14 15 16
#include "RtsFlags.h"
#include "Weak.h"
#include "Storage.h"
sof's avatar
sof committed
17
#include "Schedule.h"
18
#include "Prelude.h"
sof's avatar
sof committed
19
#include "RtsAPI.h"
20 21 22 23

StgWeak *weak_ptr_list;

/*
24
 * scheduleFinalizers() is called on the list of weak pointers found
25
 * to be dead after a garbage collection.  It overwrites each object
26
 * with DEAD_WEAK, and creates a new thread to run the pending finalizers.
27 28 29 30 31 32 33
 *
 * This function is called just after GC.  The weak pointers on the
 * argument list are those whose keys were found to be not reachable,
 * however the value and finalizer fields have by now been marked live.
 * The weak pointer object itself may not be alive - i.e. we may be
 * looking at either an object in from-space or one in to-space.  It
 * doesn't really matter either way.
sof's avatar
sof committed
34 35
 *
 * Pre-condition: sched_mutex _not_ held.
36 37 38
 */

void
39
scheduleFinalizers(Capability *cap, StgWeak *list)
40
{
41 42 43 44 45
    StgWeak *w;
    StgTSO *t;
    StgMutArrPtrs *arr;
    nat n;

46
    // count number of finalizers, and kill all the weak pointers first...
47 48 49 50 51 52 53 54
    n = 0;
    for (w = list; w; w = w->link) { 

	// Better not be a DEAD_WEAK at this stage; the garbage
	// collector removes DEAD_WEAKs from the weak pointer list.
	ASSERT(w->header.info != &stg_DEAD_WEAK_info);

	if (w->finalizer != &stg_NO_FINALIZER_closure) {
55
	    n++;
56 57 58 59 60 61 62 63 64 65 66 67
	}

#ifdef PROFILING
        // A weak pointer is inherently used, so we do not need to call
        // LDV_recordDead().
	//
        // Furthermore, when PROFILING is turned on, dead weak
        // pointers are exactly as large as weak pointers, so there is
        // no need to fill the slop, either.  See stg_DEAD_WEAK_info
        // in StgMiscClosures.hc.
#endif
	SET_HDR(w, &stg_DEAD_WEAK_info, w->header.prof.ccs);
68
    }
69
	
70
    // No finalizers to run?
71 72
    if (n == 0) return;

73
    IF_DEBUG(weak,debugBelch("weak: batching %d finalizers\n", n));
74

75
    arr = (StgMutArrPtrs *)allocateLocal(cap, sizeofW(StgMutArrPtrs) + n);
76
    TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs), n, 0);
77
    SET_HDR(arr, &stg_MUT_ARR_PTRS_FROZEN_info, CCS_SYSTEM);
78 79
    arr->ptrs = n;

80 81 82
    n = 0;
    for (w = list; w; w = w->link) {
	if (w->finalizer != &stg_NO_FINALIZER_closure) {
83 84 85 86 87
	    arr->payload[n] = w->finalizer;
	    n++;
	}
    }

88 89 90 91
    t = createIOThread(cap, 
		       RtsFlags.GcFlags.initialStkSize, 
		       rts_apply(cap,
			   rts_apply(cap,
92
			       (StgClosure *)runFinalizerBatch_closure,
93
			       rts_mkInt(cap,n)), 
94 95
			   (StgClosure *)arr)
	);
96
    scheduleThread(cap,t);
97
}