version 1.1.1.1, 1999/11/27 10:58:32 |
version 1.1.1.3, 2000/12/01 14:48:24 |
|
|
#include "gc_priv.h" |
#include "gc_priv.h" |
|
|
/* BTL: avoid circular redefinition of dlopen if SOLARIS_THREADS defined */ |
/* 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 */ |
/* To support threads in Solaris, gc.h interposes on dlopen by */ |
/* defining "dlopen" to be "GC_dlopen", which is implemented below. */ |
/* defining "dlopen" to be "GC_dlopen", which is implemented below. */ |
/* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */ |
/* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */ |
|
|
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR) |
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR) |
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \ |
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \ |
!defined(MSWIN32) && !(defined(ALPHA) && defined(OSF1)) && \ |
!defined(MSWIN32) && !(defined(ALPHA) && defined(OSF1)) && \ |
!defined(HP_PA) && !(defined(LINUX) && defined(__ELF__)) && \ |
!defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ |
!defined(RS6000) && !defined(SCO_ELF) |
!defined(RS6000) && !defined(SCO_ELF) |
--> We only know how to find data segments of dynamic libraries for the |
--> We only know how to find data segments of dynamic libraries for the |
--> above. Additional SVR4 variants might not be too |
--> above. Additional SVR4 variants might not be too |
Line 159 static ptr_t GC_first_common() |
|
Line 161 static ptr_t GC_first_common() |
|
|
|
#endif /* SUNOS4 ... */ |
#endif /* SUNOS4 ... */ |
|
|
# if defined(SUNOS4) || defined(SUNOS5DL) |
# if defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \ |
/* Add dynamic library data sections to the root set. */ |
|| defined(HPUX_THREADS) || defined(IRIX_THREADS) |
# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS) |
/* Make sure we're not in the middle of a collection, and make */ |
# ifndef SRC_M3 |
/* sure we don't start any. Returns previous value of GC_dont_gc. */ |
--> fix mutual exclusion with dlopen |
/* This is invoked prior to a dlopen call to avoid synchronization */ |
# endif /* We assume M3 programs don't call dlopen for now */ |
/* issues. We can't just acquire the allocation lock, since startup */ |
# endif |
/* 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 */ |
/* Redefine dlopen to guarantee mutual exclusion with */ |
/* GC_register_dynamic_libraries. */ |
/* GC_register_dynamic_libraries. */ |
/* assumes that dlopen doesn't need to call GC_malloc */ |
/* Should probably happen for other operating systems, too. */ |
/* and friends. */ |
|
# include <thread.h> |
|
# include <synch.h> |
|
|
|
void * GC_dlopen(const char *path, int mode) |
#include <dlfcn.h> |
|
|
|
#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; |
void * result; |
|
GC_bool dont_gc_save; |
|
|
# ifndef USE_PROC_FOR_LIBRARIES |
# ifndef USE_PROC_FOR_LIBRARIES |
mutex_lock(&GC_allocate_ml); |
dont_gc_save = disable_gc_for_dlopen(); |
# endif |
# endif |
result = dlopen(path, mode); |
# ifdef USE_LD_WRAP |
|
result = __real_dlopen(path, mode); |
|
# else |
|
result = dlopen(path, mode); |
|
# endif |
# ifndef USE_PROC_FOR_LIBRARIES |
# ifndef USE_PROC_FOR_LIBRARIES |
mutex_unlock(&GC_allocate_ml); |
GC_dont_gc = dont_gc_save; |
# endif |
# endif |
return(result); |
return(result); |
} |
} |
Line 195 void * GC_dlopen(const char *path, int mode) |
|
Line 224 void * GC_dlopen(const char *path, int mode) |
|
# define dlopen GC_dlopen |
# define dlopen GC_dlopen |
# endif |
# 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 |
# ifndef USE_PROC_FOR_LIBRARIES |
void GC_register_dynamic_libraries() |
void GC_register_dynamic_libraries() |
{ |
{ |
Line 283 void GC_register_dynamic_libraries() |
|
Line 320 void GC_register_dynamic_libraries() |
|
static struct link_map * |
static struct link_map * |
GC_FirstDLOpenedLinkMap() |
GC_FirstDLOpenedLinkMap() |
{ |
{ |
|
# ifdef __GNUC__ |
|
# pragma weak _DYNAMIC |
|
# endif |
extern ElfW(Dyn) _DYNAMIC[]; |
extern ElfW(Dyn) _DYNAMIC[]; |
ElfW(Dyn) *dp; |
ElfW(Dyn) *dp; |
struct r_debug *r; |
struct r_debug *r; |
Line 353 extern void * GC_roots_present(); |
|
Line 393 extern void * GC_roots_present(); |
|
/* The type is a lie, since the real type doesn't make sense here, */ |
/* The type is a lie, since the real type doesn't make sense here, */ |
/* and we only test for NULL. */ |
/* and we only test for NULL. */ |
|
|
|
#ifndef GC_scratch_last_end_ptr /* Never an extern any more? */ |
extern ptr_t GC_scratch_last_end_ptr; /* End of GC_scratch_alloc arena */ |
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 */ |
/* 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 */ |
/* mapped by the process, and throw out regions we know we shouldn't */ |
Line 655 void GC_register_dynamic_libraries() |
|
Line 697 void GC_register_dynamic_libraries() |
|
} |
} |
#endif |
#endif |
|
|
#if defined(HP_PA) |
#if defined(HPUX) |
|
|
#include <errno.h> |
#include <errno.h> |
#include <dl.h> |
#include <dl.h> |
Line 678 void GC_register_dynamic_libraries() |
|
Line 720 void GC_register_dynamic_libraries() |
|
|
|
/* Check if this is the end of the list or if some error occured */ |
/* Check if this is the end of the list or if some error occured */ |
if (status != 0) { |
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) { |
if (errno == EINVAL) { |
break; /* Moved past end of shared library list --> finished */ |
break; /* Moved past end of shared library list --> finished */ |
} else { |
} else { |
Line 688 void GC_register_dynamic_libraries() |
|
Line 735 void GC_register_dynamic_libraries() |
|
} |
} |
ABORT("shl_get failed"); |
ABORT("shl_get failed"); |
} |
} |
|
# endif |
} |
} |
|
|
# ifdef VERBOSE |
# ifdef VERBOSE |
Line 710 void GC_register_dynamic_libraries() |
|
Line 758 void GC_register_dynamic_libraries() |
|
index++; |
index++; |
} |
} |
} |
} |
#endif /* HP_PA */ |
#endif /* HPUX */ |
|
|
#ifdef RS6000 |
#ifdef RS6000 |
#pragma alloca |
#pragma alloca |