don't steal %ebx for the GC on x86: it's also used by PIC
[ghc-hetmet.git] / rts / Weak.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-1999
4  *
5  * Weak pointers / finalizers
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #include "PosixSource.h"
10 #include "Rts.h"
11 #include "RtsUtils.h"
12 #include "SchedAPI.h"
13 #include "RtsFlags.h"
14 #include "Weak.h"
15 #include "Schedule.h"
16 #include "Prelude.h"
17 #include "RtsAPI.h"
18 #include "Trace.h"
19
20 StgWeak *weak_ptr_list;
21
22 /*
23  * scheduleFinalizers() is called on the list of weak pointers found
24  * to be dead after a garbage collection.  It overwrites each object
25  * with DEAD_WEAK, and creates a new thread to run the pending finalizers.
26  *
27  * This function is called just after GC.  The weak pointers on the
28  * argument list are those whose keys were found to be not reachable,
29  * however the value and finalizer fields have by now been marked live.
30  * The weak pointer object itself may not be alive - i.e. we may be
31  * looking at either an object in from-space or one in to-space.  It
32  * doesn't really matter either way.
33  *
34  * Pre-condition: sched_mutex _not_ held.
35  */
36
37 void
38 scheduleFinalizers(Capability *cap, StgWeak *list)
39 {
40     StgWeak *w;
41     StgTSO *t;
42     StgMutArrPtrs *arr;
43     nat n;
44
45     // count number of finalizers, and kill all the weak pointers first...
46     n = 0;
47     for (w = list; w; w = w->link) { 
48
49         // Better not be a DEAD_WEAK at this stage; the garbage
50         // collector removes DEAD_WEAKs from the weak pointer list.
51         ASSERT(w->header.info != &stg_DEAD_WEAK_info);
52
53         if (w->finalizer != &stg_NO_FINALIZER_closure) {
54             n++;
55         }
56
57 #ifdef PROFILING
58         // A weak pointer is inherently used, so we do not need to call
59         // LDV_recordDead().
60         //
61         // Furthermore, when PROFILING is turned on, dead weak
62         // pointers are exactly as large as weak pointers, so there is
63         // no need to fill the slop, either.  See stg_DEAD_WEAK_info
64         // in StgMiscClosures.hc.
65 #endif
66         SET_HDR(w, &stg_DEAD_WEAK_info, w->header.prof.ccs);
67     }
68         
69     // No finalizers to run?
70     if (n == 0) return;
71
72     debugTrace(DEBUG_weak, "weak: batching %d finalizers", n);
73
74     arr = (StgMutArrPtrs *)allocateLocal(cap, sizeofW(StgMutArrPtrs) + n);
75     TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs), n, 0);
76     SET_HDR(arr, &stg_MUT_ARR_PTRS_FROZEN_info, CCS_SYSTEM);
77     arr->ptrs = n;
78
79     n = 0;
80     for (w = list; w; w = w->link) {
81         if (w->finalizer != &stg_NO_FINALIZER_closure) {
82             arr->payload[n] = w->finalizer;
83             n++;
84         }
85     }
86
87     t = createIOThread(cap, 
88                        RtsFlags.GcFlags.initialStkSize, 
89                        rts_apply(cap,
90                            rts_apply(cap,
91                                (StgClosure *)runFinalizerBatch_closure,
92                                rts_mkInt(cap,n)), 
93                            (StgClosure *)arr)
94         );
95     scheduleThread(cap,t);
96 }