#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 */
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR)
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
!defined(MSWIN32) && !(defined(ALPHA) && defined(OSF1)) && \
- !defined(HP_PA) && (!defined(LINUX) && !defined(__ELF__)) && \
+ !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
!defined(RS6000) && !defined(SCO_ELF)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
#endif /* SUNOS4 ... */
-# if defined(SUNOS4) || defined(SUNOS5DL)
-/* Add dynamic library data sections to the root set. */
-# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS)
-# ifndef SRC_M3
- --> fix mutual exclusion with dlopen
-# endif /* We assume M3 programs don't call dlopen for now */
-# endif
+# 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_in_progress()) {
+ GC_collect_a_little_inner(1000);
+ }
+ GC_dont_gc = TRUE;
+ UNLOCK();
+ return(result);
+ }
-# ifdef SOLARIS_THREADS
/* 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);
}
# define dlopen GC_dlopen
# endif
+# if defined(SUNOS4) || defined(SUNOS5DL)
+/* Add dynamic library data sections to the root set. */
+# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS)
+# ifndef SRC_M3
+ --> fix mutual exclusion with dlopen
+# endif /* We assume M3 programs don't call dlopen for now */
+# endif
+
# ifndef USE_PROC_FOR_LIBRARIES
void GC_register_dynamic_libraries()
{
static struct link_map *
GC_FirstDLOpenedLinkMap()
{
+# ifdef __GNUC__
+# pragma weak _DYNAMIC
+# endif
extern ElfW(Dyn) _DYNAMIC[];
ElfW(Dyn) *dp;
struct r_debug *r;
#include <errno.h>
extern void * GC_roots_present();
+ /* The type is a lie, since the real type doesn't make sense here, */
+ /* and we only test for NULL. */
+#ifndef GC_scratch_last_end_ptr
extern ptr_t GC_scratch_last_end_ptr; /* End of GC_scratch_alloc arena */
+#endif
/* We use /proc to track down all parts of the address space that are */
/* mapped by the process, and throw out regions we know we shouldn't */
if (fd < 0) {
sprintf(buf, "/proc/%d", getpid());
+ /* The above generates a lint complaint, since pid_t varies. */
+ /* It's unclear how to improve this. */
fd = open(buf, O_RDONLY);
if (fd < 0) {
ABORT("/proc open failed");
if (needed_sz >= current_sz) {
current_sz = needed_sz * 2 + 1;
/* Expansion, plus room for 0 record */
- addr_map = (prmap_t *)GC_scratch_alloc(current_sz * sizeof(prmap_t));
+ addr_map = (prmap_t *)GC_scratch_alloc((word)
+ (current_sz * sizeof(prmap_t)));
}
if (ioctl(fd, PIOCMAP, addr_map) < 0) {
GC_err_printf4("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
}
#endif
-#if defined(HP_PA)
+#if defined(HPUX)
#include <errno.h>
#include <dl.h>
/* Check if this is the end of the list or if some error occured */
if (status != 0) {
+# ifdef HPUX_THREADS
+ /* I've seen errno values of 0. The man page is not clear */
+ /* as to whether errno should get set on a -1 return. */
+ break;
+# else
if (errno == EINVAL) {
break; /* Moved past end of shared library list --> finished */
} else {
}
ABORT("shl_get failed");
}
+# endif
}
# ifdef VERBOSE
index++;
}
}
-#endif /* HP_PA */
+#endif /* HPUX */
#ifdef RS6000
#pragma alloca