aboutsummaryrefslogtreecommitdiff
path: root/boehm-gc/dyn_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'boehm-gc/dyn_load.c')
-rw-r--r--boehm-gc/dyn_load.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/boehm-gc/dyn_load.c b/boehm-gc/dyn_load.c
index 8c3ec4186c4..f812843272e 100644
--- a/boehm-gc/dyn_load.c
+++ b/boehm-gc/dyn_load.c
@@ -32,7 +32,9 @@
#include "gc_priv.h"
/* BTL: avoid circular redefinition of dlopen if SOLARIS_THREADS defined */
-# if defined(SOLARIS_THREADS) && defined(dlopen)
+# if (defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \
+ || defined(HPUX_THREADS) || defined(IRIX_THREADS)) && defined(dlopen) \
+ && !defined(USE_LD_WRAP)
/* To support threads in Solaris, 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 */
@@ -167,24 +169,60 @@ static ptr_t GC_first_common()
# endif /* We assume M3 programs don't call dlopen for now */
# endif
-# ifdef SOLARIS_THREADS
+# if defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \
+ || defined(HPUX_THREADS) || defined(IRIX_THREADS)
+ /* 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_inProgress()) {
+ GC_collect_a_little_inner(1000);
+ }
+ GC_dont_gc = TRUE;
+ UNLOCK();
+ return(result);
+ }
+
+
/* Redefine dlopen to guarantee mutual exclusion with */
/* GC_register_dynamic_libraries. */
- /* assumes that dlopen doesn't need to call GC_malloc */
- /* and friends. */
-# include <thread.h>
-# include <synch.h>
+ /* Should probably happen for other operating systems, too. */
+
+#include <dlfcn.h>
-void * GC_dlopen(const char *path, int mode)
+#ifdef 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
- mutex_lock(&GC_allocate_ml);
+ dont_gc_save = disable_gc_for_dlopen();
+# endif
+# ifdef USE_LD_WRAP
+ result = __real_dlopen(path, mode);
+# else
+ result = dlopen(path, mode);
# endif
- result = dlopen(path, mode);
# ifndef USE_PROC_FOR_LIBRARIES
- mutex_unlock(&GC_allocate_ml);
+ GC_dont_gc = dont_gc_save;
# endif
return(result);
}