Commit 723095b0 authored by Edward Z. Yang's avatar Edward Z. Yang

Per-capability nursery weak pointer lists, fixes #9075

Signed-off-by: default avatarEdward Z. Yang <ezyang@cs.stanford.edu>
parent 0c1974c8
......@@ -273,6 +273,8 @@ initCapability( Capability *cap, nat i )
cap->mut_lists[g] = NULL;
}
cap->weak_ptr_list_hd = NULL;
cap->weak_ptr_list_tl = NULL;
cap->free_tvar_watch_queues = END_STM_WATCH_QUEUE;
cap->free_invariant_check_queues = END_INVARIANT_CHECK_QUEUE;
cap->free_trec_chunks = END_STM_CHUNK_LIST;
......
......@@ -79,6 +79,11 @@ struct Capability_ {
// full pinned object blocks allocated since the last GC
bdescr *pinned_object_blocks;
// per-capability weak pointer list associated with nursery (older
// lists stored in generation object)
StgWeak *weak_ptr_list_hd;
StgWeak *weak_ptr_list_tl;
// Context switch flag. When non-zero, this means: stop running
// Haskell code, and switch threads.
int context_switch;
......
......@@ -577,10 +577,11 @@ stg_mkWeakzh ( gcptr key,
StgWeak_finalizer(w) = finalizer;
StgWeak_cfinalizers(w) = stg_NO_FINALIZER_closure;
ACQUIRE_LOCK(sm_mutex);
StgWeak_link(w) = generation_weak_ptr_list(W_[g0]);
generation_weak_ptr_list(W_[g0]) = w;
RELEASE_LOCK(sm_mutex);
StgWeak_link(w) = Capability_weak_ptr_list_hd(MyCapability());
Capability_weak_ptr_list_hd(MyCapability()) = w;
if (Capability_weak_ptr_list_tl(MyCapability()) == NULL) {
Capability_weak_ptr_list_tl(MyCapability()) = w;
}
IF_DEBUG(weak, ccall debugBelch(stg_weak_msg,w));
......
......@@ -1781,6 +1781,12 @@ computeRetainerSet( void )
//
// The following code assumes that WEAK objects are considered to be roots
// for retainer profilng.
for (n = 0; n < n_capabilities; n++) {
// NB: after a GC, all nursery weak_ptr_lists have been migrated
// to the global lists living in the generations
ASSERT(capabilities[n]->weak_ptr_list_hd == NULL);
ASSERT(capabilities[n]->weak_ptr_list_tl == NULL);
}
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
for (weak = generations[g].weak_ptr_list; weak != NULL; weak = weak->link) {
// retainRoot((StgClosure *)weak);
......
......@@ -304,7 +304,7 @@ hs_add_root(void (*init_root)(void) STG_UNUSED)
static void
hs_exit_(rtsBool wait_foreign)
{
nat g;
nat g, i;
if (hs_init_count <= 0) {
errorBelch("warning: too many hs_exit()s");
......@@ -336,6 +336,9 @@ hs_exit_(rtsBool wait_foreign)
exitScheduler(wait_foreign);
/* run C finalizers for all active weak pointers */
for (i = 0; i < n_capabilities; i++) {
runAllCFinalizers(capabilities[i]->weak_ptr_list_hd);
}
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
runAllCFinalizers(generations[g].weak_ptr_list);
}
......
......@@ -286,6 +286,9 @@ GarbageCollect (nat collect_gen,
memInventory(DEBUG_gc);
#endif
// do this *before* we start scavenging
collectFreshWeakPtrs();
// check sanity *before* GC
IF_DEBUG(sanity, checkSanity(rtsFalse /* before GC */, major_gc));
......
......@@ -25,6 +25,8 @@
#include "Storage.h"
#include "Threads.h"
#include "sm/Sanity.h"
/* -----------------------------------------------------------------------------
Weak Pointers
......@@ -341,6 +343,39 @@ static void tidyThreadList (generation *gen)
}
}
#ifdef DEBUG
static void checkWeakPtrSanity(StgWeak *hd, StgWeak *tl)
{
StgWeak *w, *prev;
for (w = hd; w != NULL; prev = w, w = w->link) {
ASSERT(INFO_PTR_TO_STRUCT(UNTAG_CLOSURE((StgClosure*)w)->header.info)->type == WEAK);
checkClosure((StgClosure*)w);
}
if (tl != NULL) {
ASSERT(prev == tl);
}
}
#endif
void collectFreshWeakPtrs()
{
nat i;
generation *gen = &generations[0];
// move recently allocated weak_ptr_list to the old list as well
for (i = 0; i < n_capabilities; i++) {
Capability *cap = capabilities[i];
if (cap->weak_ptr_list_tl != NULL) {
IF_DEBUG(sanity, checkWeakPtrSanity(cap->weak_ptr_list_hd, cap->weak_ptr_list_tl));
cap->weak_ptr_list_tl->link = gen->weak_ptr_list;
gen->weak_ptr_list = cap->weak_ptr_list_hd;
cap->weak_ptr_list_tl = NULL;
cap->weak_ptr_list_hd = NULL;
} else {
ASSERT(cap->weak_ptr_list_hd == NULL);
}
}
}
/* -----------------------------------------------------------------------------
Evacuate every weak pointer object on the weak_ptr_list, and update
the link fields.
......
......@@ -20,6 +20,7 @@ extern StgWeak *old_weak_ptr_list;
extern StgTSO *resurrected_threads;
extern StgTSO *exception_threads;
void collectFreshWeakPtrs ( void );
void initWeakForGC ( void );
rtsBool traverseWeakPtrList ( void );
void markWeakPtrList ( void );
......
......@@ -349,6 +349,8 @@ wanteds = concat
,structField C "Capability" "context_switch"
,structField C "Capability" "interrupt"
,structField C "Capability" "sparks"
,structField C "Capability" "weak_ptr_list_hd"
,structField C "Capability" "weak_ptr_list_tl"
,structField Both "bdescr" "start"
,structField Both "bdescr" "free"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment