summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2014-09-29 12:49:21 +0100
committerSimon Marlow <marlowsd@gmail.com>2014-11-28 14:10:32 +0000
commit9e6e4796437a7fc23e83605a45db9b2663570123 (patch)
treeb78db2642aed0c47bcbca124f99031fcb52d6d9d /rts
parentb5e8b3b162b3ff15ae6caf1afc659565365f54a8 (diff)
downloadhaskell-9e6e4796437a7fc23e83605a45db9b2663570123.tar.gz
Add purgeObj() to remove the symbol table entries for an object
This allows us to replace an object without actually unloading the old object, which is necessary when we know we have references to the old object so it can't be completely unloaded. Using unloadObj() would cause the GC (CheckUnload) to repeatedly and fruitlessly try to unload the old object.
Diffstat (limited to 'rts')
-rw-r--r--rts/Linker.c74
1 files changed, 51 insertions, 23 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 6d9abfe695..0c390ae46c 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -2255,20 +2255,45 @@ mmap_again:
}
#endif // USE_MMAP
+/*
+ * Remove symbols from the symbol table, and free oc->symbols.
+ * This operation is idempotent.
+ */
static void removeOcSymbols (ObjectCode *oc)
{
if (oc->symbols == NULL) return;
- /* Remove all the mappings for the symbols within this object..
- */
+ // Remove all the mappings for the symbols within this object..
int i;
for (i = 0; i < oc->n_symbols; i++) {
if (oc->symbols[i] != NULL) {
ghciRemoveSymbolTable(symhash, oc->symbols[i], oc);
}
}
+
+ stgFree(oc->symbols);
+ oc->symbols = NULL;
+}
+
+/*
+ * Release StablePtrs and free oc->stable_ptrs.
+ * This operation is idempotent.
+ */
+static void freeOcStablePtrs (ObjectCode *oc)
+{
+ // Release any StablePtrs that were created when this
+ // object module was initialized.
+ ForeignExportStablePtr *fe_ptr, *next;
+
+ for (fe_ptr = oc->stable_ptrs; fe_ptr != NULL; fe_ptr = next) {
+ next = fe_ptr->next;
+ freeStablePtr(fe_ptr->stable_ptr);
+ stgFree(fe_ptr);
+ }
+ oc->stable_ptrs = NULL;
}
+
/*
* freeObjectCode() releases all the pieces of an ObjectCode. It is called by
* the GC when a previously unloaded ObjectCode has been determined to be
@@ -3015,6 +3040,7 @@ static HsInt loadObj_ (pathchar *path)
if (! loadOc(oc)) {
// failed; free everything we've allocated
removeOcSymbols(oc);
+ // no need to freeOcStablePtrs, they aren't created until resolveObjs()
freeObjectCode(oc);
return 0;
}
@@ -3150,7 +3176,7 @@ HsInt resolveObjs (void)
/* -----------------------------------------------------------------------------
* delete an object from the pool
*/
-static HsInt unloadObj_ (pathchar *path)
+static HsInt unloadObj_ (pathchar *path, rtsBool just_purge)
{
ObjectCode *oc, *prev, *next;
HsBool unloadedAnyObj = HS_BOOL_FALSE;
@@ -3166,30 +3192,24 @@ static HsInt unloadObj_ (pathchar *path)
if (!pathcmp(oc->fileName,path)) {
+ // these are both idempotent, so in just_purge mode we can
+ // later call unloadObj() to really unload the object.
removeOcSymbols(oc);
+ freeOcStablePtrs(oc);
- if (prev == NULL) {
- objects = oc->next;
- } else {
- prev->next = oc->next;
- }
- oc->next = unloaded_objects;
- unloaded_objects = oc;
-
- // Release any StablePtrs that were created when this
- // object module was initialized.
- {
- ForeignExportStablePtr *fe_ptr, *next;
-
- for (fe_ptr = oc->stable_ptrs; fe_ptr != NULL; fe_ptr = next) {
- next = fe_ptr->next;
- freeStablePtr(fe_ptr->stable_ptr);
- stgFree(fe_ptr);
+ if (!just_purge) {
+ if (prev == NULL) {
+ objects = oc->next;
+ } else {
+ prev->next = oc->next;
}
+ oc->next = unloaded_objects;
+ unloaded_objects = oc;
+ oc->status = OBJECT_UNLOADED;
+ } else {
+ prev = oc;
}
- oc->status = OBJECT_UNLOADED;
-
/* This could be a member of an archive so continue
* unloading other members. */
unloadedAnyObj = HS_BOOL_TRUE;
@@ -3210,7 +3230,15 @@ static HsInt unloadObj_ (pathchar *path)
HsInt unloadObj (pathchar *path)
{
ACQUIRE_LOCK(&linker_mutex);
- HsInt r = unloadObj_(path);
+ HsInt r = unloadObj_(path, rtsFalse);
+ RELEASE_LOCK(&linker_mutex);
+ return r;
+}
+
+HsInt purgeObj (pathchar *path)
+{
+ ACQUIRE_LOCK(&linker_mutex);
+ HsInt r = unloadObj_(path, rtsTrue);
RELEASE_LOCK(&linker_mutex);
return r;
}