diff options
author | Simon Marlow <marlowsd@gmail.com> | 2014-12-04 10:12:01 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2014-12-05 10:06:13 +0000 |
commit | 55a2a0b4893486e5dde151620d7f46e8035d2af5 (patch) | |
tree | ea727a15ccceaf00d761252340331d2154d76b67 /rts | |
parent | 78edd76047d255bb543f7ce5517477f371bb2f0b (diff) | |
download | haskell-55a2a0b4893486e5dde151620d7f46e8035d2af5.tar.gz |
Revert "Revert "Make the linker API thread-safe""
Also includes a fix for the segfaults on Windows caused by the original
version of this patch.
This reverts commit 4b51194df4090d984f02c12128e868077660fb8b.
Diffstat (limited to 'rts')
-rw-r--r-- | rts/CheckUnload.c | 4 | ||||
-rw-r--r-- | rts/Linker.c | 109 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 4 |
3 files changed, 80 insertions, 37 deletions
diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c index c63a35a24e..73573fbb34 100644 --- a/rts/CheckUnload.c +++ b/rts/CheckUnload.c @@ -260,6 +260,8 @@ void checkUnload (StgClosure *static_objects) if (unloaded_objects == NULL) return; + ACQUIRE_LOCK(&linker_mutex); + // Mark every unloadable object as unreferenced initially for (oc = unloaded_objects; oc; oc = oc->next) { IF_DEBUG(linker, debugBelch("Checking whether to unload %" PATH_FMT "\n", @@ -317,4 +319,6 @@ void checkUnload (StgClosure *static_objects) } freeHashTable(addrs, NULL); + + RELEASE_LOCK(&linker_mutex); } diff --git a/rts/Linker.c b/rts/Linker.c index a4f6c6b142..cb2fac6b6b 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -155,6 +155,10 @@ ObjectCode *objects = NULL; /* initially empty */ to be actually freed via checkUnload() */ ObjectCode *unloaded_objects = NULL; /* initially empty */ +#ifdef THREADED_RTS +Mutex linker_mutex; +#endif + /* Type of the initializer */ typedef void (*init_t) (int argc, char **argv, char **env); @@ -1637,9 +1641,12 @@ initLinker_ (int retain_cafs) objects = NULL; unloaded_objects = NULL; -#if defined(THREADED_RTS) && (defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)) +#if defined(THREADED_RTS) + initMutex(&linker_mutex); +#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) initMutex(&dl_mutex); #endif +#endif symhash = allocStrHashTable(); /* populate the symbol table with stuff from the RTS */ @@ -1728,6 +1735,9 @@ exitLinker( void ) { if (linker_init_done == 1) { freeHashTable(symhash, free); } +#ifdef THREADED_RTS + closeMutex(&linker_mutex); +#endif } /* ----------------------------------------------------------------------------- @@ -1914,8 +1924,6 @@ addDLL( pathchar *dll_name ) char line[MAXLINE]; int result; - initLinker(); - IF_DEBUG(linker, debugBelch("addDLL: dll_name = '%s'\n", dll_name)); errmsg = internal_dlopen(dll_name); @@ -1977,8 +1985,6 @@ addDLL( pathchar *dll_name ) OpenedDLL* o_dll; HINSTANCE instance; - initLinker(); - /* debugBelch("\naddDLL; dll_name = `%s'\n", dll_name); */ /* See if we've already got it, and ignore if so. */ @@ -2047,12 +2053,11 @@ HsInt insertSymbol(pathchar* obj_name, char* key, void* data) /* ----------------------------------------------------------------------------- * lookup a symbol in the hash table */ -void * -lookupSymbol( char *lbl ) +static void* lookupSymbol_ (char *lbl) { void *val; IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s\n", lbl)); - initLinker() ; + ASSERT(symhash != NULL); if (!ghciLookupSymbolTable(symhash, lbl, &val)) { @@ -2085,14 +2090,15 @@ lookupSymbol( char *lbl ) void* sym; sym = lookupSymbolInDLLs((unsigned char*)lbl); - if (sym != NULL) { return sym; }; + if (sym != NULL) { + return sym; + }; // Also try looking up the symbol without the @N suffix. Some // DLLs have the suffixes on their symbols, some don't. zapTrailingAtSign ( (unsigned char*)lbl ); sym = lookupSymbolInDLLs((unsigned char*)lbl); - if (sym != NULL) { return sym; }; - return NULL; + return sym; // might be NULL if not found # else ASSERT(2+2 == 5); @@ -2104,6 +2110,14 @@ lookupSymbol( char *lbl ) } } +void* lookupSymbol( char *lbl ) +{ + ACQUIRE_LOCK(&linker_mutex); + char *r = lookupSymbol_(lbl); + RELEASE_LOCK(&linker_mutex); + return r; +} + /* ----------------------------------------------------------------------------- Create a StablePtr for a foreign export. This is normally called by a C function with __attribute__((constructor)), which is generated @@ -2150,8 +2164,6 @@ void ghci_enquire ( char* addr ) const int DELTA = 64; ObjectCode* oc; - initLinker(); - for (oc = objects; oc; oc = oc->next) { for (i = 0; i < oc->n_symbols; i++) { sym = oc->symbols[i]; @@ -2434,8 +2446,7 @@ isAlreadyLoaded( pathchar *path ) return 0; /* not loaded yet */ } -HsInt -loadArchive( pathchar *path ) +static HsInt loadArchive_ (pathchar *path) { ObjectCode* oc; char *image; @@ -2476,8 +2487,6 @@ loadArchive( pathchar *path ) * all resources correctly. This function is pretty complex, so it needs * to be refactored to make this practical. */ - initLinker(); - IF_DEBUG(linker, debugBelch("loadArchive: start\n")); IF_DEBUG(linker, debugBelch("loadArchive: Loading archive `%" PATH_FMT" '\n", path)); @@ -2902,13 +2911,20 @@ loadArchive( pathchar *path ) return 1; } +HsInt loadArchive (pathchar *path) +{ + ACQUIRE_LOCK(&linker_mutex); + HsInt r = loadArchive_(path); + RELEASE_LOCK(&linker_mutex); + return r; +} + /* ----------------------------------------------------------------------------- * Load an obj (populate the global symbol table, but don't resolve yet) * * Returns: 1 if ok, 0 on error. */ -HsInt -loadObj( pathchar *path ) +static HsInt loadObj_ (pathchar *path) { ObjectCode* oc; char *image; @@ -2925,8 +2941,6 @@ loadObj( pathchar *path ) #endif IF_DEBUG(linker, debugBelch("loadObj %" PATH_FMT "\n", path)); - initLinker(); - /* debugBelch("loadObj %s\n", path ); */ /* Check that we haven't already loaded this object. @@ -2963,7 +2977,9 @@ loadObj( pathchar *path ) image = mmapForLinker(fileSize, 0, fd); close(fd); - if (image == NULL) return 0; + if (image == NULL) { + return 0; + } #else /* !USE_MMAP */ /* load the image into memory */ @@ -3035,6 +3051,14 @@ loadObj( pathchar *path ) return 1; } +HsInt loadObj (pathchar *path) +{ + ACQUIRE_LOCK(&linker_mutex); + HsInt r = loadObj_(path); + RELEASE_LOCK(&linker_mutex); + return r; +} + static HsInt loadOc( ObjectCode* oc ) { int r; @@ -3099,14 +3123,12 @@ loadOc( ObjectCode* oc ) { * * Returns: 1 if ok, 0 on error. */ -HsInt -resolveObjs( void ) +static HsInt resolveObjs_ (void) { ObjectCode *oc; int r; IF_DEBUG(linker, debugBelch("resolveObjs: start\n")); - initLinker(); for (oc = objects; oc; oc = oc->next) { if (oc->status != OBJECT_RESOLVED) { @@ -3144,11 +3166,18 @@ resolveObjs( void ) return 1; } +HsInt resolveObjs (void) +{ + ACQUIRE_LOCK(&linker_mutex); + HsInt r = resolveObjs_(); + RELEASE_LOCK(&linker_mutex); + return r; +} + /* ----------------------------------------------------------------------------- * delete an object from the pool */ -HsInt -unloadObj( pathchar *path ) +static HsInt unloadObj_ (pathchar *path) { ObjectCode *oc, *prev, *next; HsBool unloadedAnyObj = HS_BOOL_FALSE; @@ -3156,8 +3185,6 @@ unloadObj( pathchar *path ) ASSERT(symhash != NULL); ASSERT(objects != NULL); - initLinker(); - IF_DEBUG(linker, debugBelch("unloadObj: %" PATH_FMT "\n", path)); prev = NULL; @@ -3207,6 +3234,14 @@ unloadObj( pathchar *path ) } } +HsInt unloadObj (pathchar *path) +{ + ACQUIRE_LOCK(&linker_mutex); + HsInt r = unloadObj_(path); + RELEASE_LOCK(&linker_mutex); + return r; +} + /* ----------------------------------------------------------------------------- * Sanity checking. For each ObjectCode, maintain a list of address ranges * which may be prodded during relocation, and abort if we try and write @@ -4598,7 +4633,7 @@ ocResolve_PEi386 ( ObjectCode* oc ) + ((size_t)(sym->Value)); } else { copyName ( sym->Name, strtab, symbol, 1000-1 ); - S = (size_t) lookupSymbol( (char*)symbol ); + S = (size_t) lookupSymbol_( (char*)symbol ); if ((void*)S != NULL) goto foundit; errorBelch("%" PATH_FMT ": unknown symbol `%s'", oc->fileName, symbol); return 0; @@ -5460,7 +5495,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, } else { symbol = strtab + sym.st_name; - S_tmp = lookupSymbol( symbol ); + S_tmp = lookupSymbol_( symbol ); if (S_tmp == NULL) return 0; S = (Elf_Addr)S_tmp; } @@ -5771,7 +5806,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } else { /* No, so look up the name in our global table. */ symbol = strtab + sym.st_name; - S_tmp = lookupSymbol( symbol ); + S_tmp = lookupSymbol_( symbol ); S = (Elf_Addr)S_tmp; #ifdef ELF_FUNCTION_DESC @@ -6320,7 +6355,7 @@ resolveImports( addr = (void*) (symbol->n_value); IF_DEBUG(linker, debugBelch("resolveImports: undefined external %s has value %p\n", nm, addr)); } else { - addr = lookupSymbol(nm); + addr = lookupSymbol_(nm); IF_DEBUG(linker, debugBelch("resolveImports: looking up %s, %p\n", nm, addr)); } @@ -6476,7 +6511,7 @@ relocateSection( // symtab, or it is undefined, meaning dlsym must be used // to resolve it. - addr = lookupSymbol(nm); + addr = lookupSymbol_(nm); IF_DEBUG(linker, debugBelch("relocateSection: looked up %s, " "external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n", nm)); IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr)); @@ -6528,7 +6563,7 @@ relocateSection( IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value)); } else { - addr = lookupSymbol(nm); + addr = lookupSymbol_(nm); if (addr == NULL) { errorBelch("\nlookupSymbol failed in relocateSection (relocate external)\n" @@ -6831,7 +6866,7 @@ relocateSection( else { struct nlist *symbol = &nlist[reloc->r_symbolnum]; char *nm = image + symLC->stroff + symbol->n_un.n_strx; - void *symbolAddress = lookupSymbol(nm); + void *symbolAddress = lookupSymbol_(nm); if (!symbolAddress) { errorBelch("\nunknown symbol `%s'", nm); @@ -7058,7 +7093,7 @@ ocGetNames_MachO(ObjectCode* oc) if(nlist[i].n_type & N_EXT) { char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; - if ((nlist[i].n_desc & N_WEAK_DEF) && lookupSymbol(nm)) { + if ((nlist[i].n_desc & N_WEAK_DEF) && lookupSymbol_(nm)) { // weak definition, and we already have a definition IF_DEBUG(linker, debugBelch(" weak: %s\n", nm)); } diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h index e1942bc8ae..4fe533b903 100644 --- a/rts/LinkerInternals.h +++ b/rts/LinkerInternals.h @@ -144,6 +144,10 @@ typedef struct _ObjectCode { extern ObjectCode *objects; extern ObjectCode *unloaded_objects; +#ifdef THREADED_RTS +extern Mutex linker_mutex; +#endif + void exitLinker( void ); void freeObjectCode (ObjectCode *oc); |