summaryrefslogtreecommitdiff
path: root/rts/Stable.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2013-02-14 08:58:03 +0000
committerSimon Marlow <marlowsd@gmail.com>2013-02-14 10:57:10 +0000
commit88b4578bc82795de48876a250c2b6d7cce380628 (patch)
tree77b9dd7bee66ad7c1ae542814ccba70c29393c88 /rts/Stable.c
parent7e7a4e4d7e9e84b2c57d3d55e372e738b5f8dbf5 (diff)
downloadhaskell-88b4578bc82795de48876a250c2b6d7cce380628.tar.gz
small tidyups and refactorings
Diffstat (limited to 'rts/Stable.c')
-rw-r--r--rts/Stable.c238
1 files changed, 106 insertions, 132 deletions
diff --git a/rts/Stable.c b/rts/Stable.c
index ff3843ecd7..e1807faa72 100644
--- a/rts/Stable.c
+++ b/rts/Stable.c
@@ -103,41 +103,36 @@ Mutex stable_mutex;
static void enlargeStableNameTable(void);
static void enlargeStablePtrTable(void);
-/* This hash table maps Haskell objects to stable names, so that every
+/*
+ * 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.
- *
- * OLD COMMENTS about reference counting follow. The reference count
- * in a stable name entry is now just a counter.
- *
- * Reference counting
- * ------------------
- * A plain stable name entry has a zero reference count, which means
- * the entry will dissappear when the object it points to is
- * unreachable. For stable pointers, we need an entry that sticks
- * around and keeps the object it points to alive, so each stable name
- * entry has an associated reference count.
- *
- * A stable pointer has a weighted reference count N attached to it
- * (actually in its upper 5 bits), which represents the weight
- * 2^(N-1). The stable name entry keeps a 32-bit reference count, which
- * represents any weight between 1 and 2^32 (represented as zero).
- * When the weight is 2^32, the stable name table owns "all" of the
- * stable pointers to this object, and the entry can be garbage
- * collected if the object isn't reachable.
- *
- * A new stable pointer is given the weight log2(W/2), where W is the
- * weight stored in the table entry. The new weight in the table is W
- * - 2^log2(W/2).
- *
- * A stable pointer can be "split" into two stable pointers, by
- * dividing the weight by 2 and giving each pointer half.
- * When freeing a stable pointer, the weight of the pointer is added
- * to the weight stored in the table entry.
- * */
+ */
static HashTable *addrToStableHash = NULL;
+/* -----------------------------------------------------------------------------
+ * We must lock the StablePtr table during GC, to prevent simultaneous
+ * calls to freeStablePtr().
+ * -------------------------------------------------------------------------- */
+
+void
+stableLock(void)
+{
+ initStableTables();
+ ACQUIRE_LOCK(&stable_mutex);
+}
+
+void
+stableUnlock(void)
+{
+ RELEASE_LOCK(&stable_mutex);
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialising the tables
+ * -------------------------------------------------------------------------- */
+
STATIC_INLINE void
initSnEntryFreeList(snEntry *table, nat n, snEntry *free)
{
@@ -187,6 +182,44 @@ initStableTables(void)
#endif
}
+/* -----------------------------------------------------------------------------
+ * Enlarging the tables
+ * -------------------------------------------------------------------------- */
+
+static void
+enlargeStableNameTable(void)
+{
+ nat old_SNT_size = SNT_size;
+
+ // 2nd and subsequent times
+ SNT_size *= 2;
+ stable_name_table =
+ stgReallocBytes(stable_name_table,
+ SNT_size * sizeof *stable_name_table,
+ "enlargeStableNameTable");
+
+ initSnEntryFreeList(stable_name_table + old_SNT_size, old_SNT_size, NULL);
+}
+
+static void
+enlargeStablePtrTable(void)
+{
+ nat old_SPT_size = SPT_size;
+
+ // 2nd and subsequent times
+ SPT_size *= 2;
+ stable_ptr_table =
+ stgReallocBytes(stable_ptr_table,
+ SPT_size * sizeof *stable_ptr_table,
+ "enlargeStablePtrTable");
+
+ initSpEntryFreeList(stable_ptr_table + old_SPT_size, old_SPT_size, NULL);
+}
+
+/* -----------------------------------------------------------------------------
+ * Freeing entries and tables
+ * -------------------------------------------------------------------------- */
+
void
exitStableTables(void)
{
@@ -209,6 +242,40 @@ exitStableTables(void)
#endif
}
+STATIC_INLINE void
+freeSnEntry(snEntry *sn)
+{
+ ASSERT(sn->sn_obj == NULL);
+ sn->addr = (P_)stable_name_free;
+ stable_name_free = sn;
+}
+
+STATIC_INLINE void
+freeSpEntry(spEntry *sp)
+{
+ sp->addr = (P_)stable_ptr_free;
+ stable_ptr_free = sp;
+}
+
+void
+freeStablePtrUnsafe(StgStablePtr sp)
+{
+ ASSERT((StgWord)sp < SPT_size);
+ freeSpEntry(&stable_ptr_table[(StgWord)sp]);
+}
+
+void
+freeStablePtr(StgStablePtr sp)
+{
+ stableLock();
+ freeStablePtrUnsafe(sp);
+ stableUnlock();
+}
+
+/* -----------------------------------------------------------------------------
+ * Looking up
+ * -------------------------------------------------------------------------- */
+
/*
* get at the real stuff...remove indirections.
* It untags pointers before dereferencing and
@@ -235,12 +302,14 @@ removeIndirections(StgClosure* p)
return TAG_CLOSURE(tag,q);
}
-static StgWord
-lookupStableName_(StgPtr p)
+StgWord
+lookupStableName (StgPtr p)
{
StgWord sn;
void* sn_tmp;
+ stableLock();
+
if (stable_name_free == NULL) {
enlargeStableNameTable();
}
@@ -259,6 +328,7 @@ lookupStableName_(StgPtr p)
if (sn != 0) {
ASSERT(stable_name_table[sn].addr == p);
debugTrace(DEBUG_stable, "cached stable name %ld at %p",sn,p);
+ stableUnlock();
return sn;
}
@@ -271,40 +341,9 @@ lookupStableName_(StgPtr p)
/* add the new stable name to the hash table */
insertHashTable(addrToStableHash, (W_)p, (void *)sn);
- return sn;
-}
-
-StgWord
-lookupStableName(StgPtr p)
-{
- StgWord res;
-
- initStableTables();
- ACQUIRE_LOCK(&stable_mutex);
- res = lookupStableName_(p);
- RELEASE_LOCK(&stable_mutex);
- return res;
-}
-
-STATIC_INLINE void
-freeSnEntry(snEntry *sn)
-{
- ASSERT(sn->sn_obj == NULL);
- if(sn->addr != NULL) {
- /* StableName object may die before pointee, in which case we
- * need to remove from hash table, or after pointee, in which
- * case addr==NULL and we already removed it. */
- removeHashTable(addrToStableHash, (W_)sn->addr, NULL);
- }
- sn->addr = (P_)stable_name_free;
- stable_name_free = sn;
-}
+ stableUnlock();
-STATIC_INLINE void
-freeSpEntry(spEntry *sp)
-{
- sp->addr = (P_)stable_ptr_free;
- stable_ptr_free = sp;
+ return sn;
}
StgStablePtr
@@ -312,80 +351,15 @@ getStablePtr(StgPtr p)
{
StgWord sp;
- initStableTables();
- ACQUIRE_LOCK(&stable_mutex);
+ stableLock();
if (!stable_ptr_free) enlargeStablePtrTable();
sp = stable_ptr_free - stable_ptr_table;
stable_ptr_free = (spEntry*)(stable_ptr_free->addr);
stable_ptr_table[sp].addr = p;
- RELEASE_LOCK(&stable_mutex);
+ stableUnlock();
return (StgStablePtr)(sp);
}
-void
-freeStablePtrUnsafe(StgStablePtr sp)
-{
- ASSERT((StgWord)sp < SPT_size);
- freeSpEntry(&stable_ptr_table[(StgWord)sp]);
-}
-
-void
-freeStablePtr(StgStablePtr sp)
-{
- initStableTables();
- ACQUIRE_LOCK(&stable_mutex);
- freeStablePtrUnsafe(sp);
- RELEASE_LOCK(&stable_mutex);
-}
-
-static void
-enlargeStableNameTable(void)
-{
- nat old_SNT_size = SNT_size;
-
- // 2nd and subsequent times
- SNT_size *= 2;
- stable_name_table =
- stgReallocBytes(stable_name_table,
- SNT_size * sizeof *stable_name_table,
- "enlargeStableNameTable");
-
- initSnEntryFreeList(stable_name_table + old_SNT_size, old_SNT_size, NULL);
-}
-
-static void
-enlargeStablePtrTable(void)
-{
- nat old_SPT_size = SPT_size;
-
- // 2nd and subsequent times
- SPT_size *= 2;
- stable_ptr_table =
- stgReallocBytes(stable_ptr_table,
- SPT_size * sizeof *stable_ptr_table,
- "enlargeStablePtrTable");
-
- initSpEntryFreeList(stable_ptr_table + old_SPT_size, old_SPT_size, NULL);
-}
-
-/* -----------------------------------------------------------------------------
- * We must lock the StablePtr table during GC, to prevent simultaneous
- * calls to freeStablePtr().
- * -------------------------------------------------------------------------- */
-
-void
-stableLock(void)
-{
- initStableTables();
- ACQUIRE_LOCK(&stable_mutex);
-}
-
-void
-stableUnlock(void)
-{
- RELEASE_LOCK(&stable_mutex);
-}
-
/* -----------------------------------------------------------------------------
* Treat stable pointers as roots for the garbage collector.
* -------------------------------------------------------------------------- */