diff options
Diffstat (limited to 'gc/gc_dlopen.c')
-rw-r--r-- | gc/gc_dlopen.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/gc/gc_dlopen.c b/gc/gc_dlopen.c new file mode 100644 index 0000000..943c4b0 --- /dev/null +++ b/gc/gc_dlopen.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1997 by Silicon Graphics. All rights reserved. + * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved. + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + * Original author: Bill Janssen + * Heavily modified by Hans Boehm and others + */ + +/* + * This used to be in dyn_load.c. It was extracted into a separate file + * to avoid having to link against libdl.{a,so} if the client doesn't call + * dlopen. -HB + */ + +#include "private/gc_priv.h" + +# if defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \ + || defined(HPUX_THREADS) || defined(IRIX_THREADS) + +# if defined(dlopen) && !defined(GC_USE_LD_WRAP) + /* To support various threads pkgs, gc.h interposes on dlopen by */ + /* defining "dlopen" to be "GC_dlopen", which is implemented below. */ + /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */ + /* real system dlopen() in their implementation. We first remove */ + /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */ +# undef dlopen +# endif + + /* Make sure we're not in the middle of a collection, and make */ + /* sure we don't start any. Returns previous value of GC_dont_gc. */ + /* This is invoked prior to a dlopen call to avoid synchronization */ + /* issues. We can't just acquire the allocation lock, since startup */ + /* code in dlopen may try to allocate. */ + /* This solution risks heap growth in the presence of many dlopen */ + /* calls in either a multithreaded environment, or if the library */ + /* initialization code allocates substantial amounts of GC'ed memory. */ + /* But I don't know of a better solution. */ + /* This can still deadlock if the client explicitly starts a GC */ + /* during the dlopen. He shouldn't do that. */ + static GC_bool disable_gc_for_dlopen() + { + GC_bool result; + LOCK(); + result = GC_dont_gc; + while (GC_incremental && GC_collection_in_progress()) { + GC_collect_a_little_inner(1000); + } + GC_dont_gc = TRUE; + UNLOCK(); + return(result); + } + + /* Redefine dlopen to guarantee mutual exclusion with */ + /* GC_register_dynamic_libraries. */ + /* Should probably happen for other operating systems, too. */ + +#include <dlfcn.h> + +#ifdef GC_USE_LD_WRAP + void * __wrap_dlopen(const char *path, int mode) +#else + void * GC_dlopen(path, mode) + GC_CONST char * path; + int mode; +#endif +{ + void * result; + GC_bool dont_gc_save; + +# ifndef USE_PROC_FOR_LIBRARIES + dont_gc_save = disable_gc_for_dlopen(); +# endif +# ifdef GC_USE_LD_WRAP + result = (void *)__real_dlopen(path, mode); +# else + result = dlopen(path, mode); +# endif +# ifndef USE_PROC_FOR_LIBRARIES + GC_dont_gc = dont_gc_save; +# endif + return(result); +} +# endif /* LINUX_THREADS || SOLARIS_THREADS || ... */ + + + |