X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FStable.c;h=c46f8b2b9e40055871fdabfa648ec84b97d071ff;hb=661c97c65e5fa47177502e592bb763f752b487ac;hp=2391cb127fb37cec344065a20f15a4f7f15c793b;hpb=5a2769f0273dd389977e8283375e7920d183bdd4;p=ghc-hetmet.git diff --git a/rts/Stable.c b/rts/Stable.c index 2391cb1..c46f8b2 100644 --- a/rts/Stable.c +++ b/rts/Stable.c @@ -6,19 +6,14 @@ * * ---------------------------------------------------------------------------*/ -// Make static versions of inline functions in Stable.h: -#define RTS_STABLE_C - #include "PosixSource.h" #include "Rts.h" +#include "RtsAPI.h" + #include "Hash.h" #include "RtsUtils.h" -#include "OSThreads.h" -#include "Storage.h" -#include "RtsAPI.h" -#include "RtsFlags.h" -#include "OSThreads.h" #include "Trace.h" +#include "Stable.h" /* Comment from ADR's implementation in old RTS: @@ -85,6 +80,8 @@ static unsigned int SPT_size = 0; static Mutex stable_mutex; #endif +static void enlargeStablePtrTable(void); + /* This hash table maps Haskell objects to stable names, so that every * call to lookupStableName on a given object will return the same * stable name. @@ -159,8 +156,26 @@ initStablePtrTable(void) #endif } +void +exitStablePtrTable(void) +{ + if (addrToStableHash) + freeHashTable(addrToStableHash, NULL); + addrToStableHash = NULL; + if (stable_ptr_table) + stgFree(stable_ptr_table); + stable_ptr_table = NULL; + SPT_size = 0; +#ifdef THREADED_RTS + closeMutex(&stable_mutex); +#endif +} + /* * get at the real stuff...remove indirections. + * It untags pointers before dereferencing and + * retags the real stuff with its tag (if there + * is any) when returning. * * ToDo: move to a better home. */ @@ -168,16 +183,18 @@ static StgClosure* removeIndirections(StgClosure* p) { - StgClosure* q = p; + StgWord tag = GET_CLOSURE_TAG(p); + StgClosure* q = UNTAG_CLOSURE(p); while (get_itbl(q)->type == IND || get_itbl(q)->type == IND_STATIC || - get_itbl(q)->type == IND_OLDGEN || - get_itbl(q)->type == IND_PERM || - get_itbl(q)->type == IND_OLDGEN_PERM ) { + get_itbl(q)->type == IND_PERM) { q = ((StgInd *)q)->indirectee; + tag = GET_CLOSURE_TAG(q); + q = UNTAG_CLOSURE(q); } - return q; + + return TAG_CLOSURE(tag,q); } static StgWord @@ -195,6 +212,9 @@ lookupStableName_(StgPtr p) */ p = (StgPtr)removeIndirections((StgClosure*)p); + // register the untagged pointer. This just makes things simpler. + p = (StgPtr)UNTAG_CLOSURE((StgClosure*)p); + sn_tmp = lookupHashTable(addrToStableHash,(W_)p); sn = (StgWord)sn_tmp; @@ -277,7 +297,7 @@ freeStablePtr(StgStablePtr sp) RELEASE_LOCK(&stable_mutex); } -void +static void enlargeStablePtrTable(void) { nat old_SPT_size = SPT_size; @@ -293,6 +313,23 @@ enlargeStablePtrTable(void) } /* ----------------------------------------------------------------------------- + * We must lock the StablePtr table during GC, to prevent simultaneous + * calls to freeStablePtr(). + * -------------------------------------------------------------------------- */ + +void +stablePtrPreGC(void) +{ + ACQUIRE_LOCK(&stable_mutex); +} + +void +stablePtrPostGC(void) +{ + RELEASE_LOCK(&stable_mutex); +} + +/* ----------------------------------------------------------------------------- * Treat stable pointers as roots for the garbage collector. * * A stable pointer is any stable name entry with a ref > 0. We'll @@ -300,7 +337,7 @@ enlargeStablePtrTable(void) * -------------------------------------------------------------------------- */ void -markStablePtrTable(evac_fn evac) +markStablePtrTable(evac_fn evac, void *user) { snEntry *p, *end_stable_ptr_table; StgPtr q; @@ -324,7 +361,7 @@ markStablePtrTable(evac_fn evac) // if the ref is non-zero, treat addr as a root if (p->ref != 0) { - evac((StgClosure **)&p->addr); + evac(user, (StgClosure **)&p->addr); } } } @@ -339,7 +376,7 @@ markStablePtrTable(evac_fn evac) * -------------------------------------------------------------------------- */ void -threadStablePtrTable( evac_fn evac ) +threadStablePtrTable( evac_fn evac, void *user ) { snEntry *p, *end_stable_ptr_table; StgPtr q; @@ -349,12 +386,12 @@ threadStablePtrTable( evac_fn evac ) for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) { if (p->sn_obj != NULL) { - evac((StgClosure **)&p->sn_obj); + evac(user, (StgClosure **)&p->sn_obj); } q = p->addr; if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) { - evac((StgClosure **)&p->addr); + evac(user, (StgClosure **)&p->addr); } } } @@ -400,15 +437,15 @@ gcStablePtrTable( void ) if (p->sn_obj == NULL) { // StableName object is dead freeStableName(p); - debugTrace(DEBUG_stable, "GC'd Stable name %ld", - p - stable_ptr_table); + debugTrace(DEBUG_stable, "GC'd Stable name %ld", + (long)(p - stable_ptr_table)); continue; } else { p->addr = (StgPtr)isAlive((StgClosure *)p->addr); debugTrace(DEBUG_stable, "stable name %ld still alive at %p, ref %ld\n", - p - stable_ptr_table, p->addr, p->ref); + (long)(p - stable_ptr_table), p->addr, p->ref); } } }