/* * 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. Of course this fails if the collector is in a dynamic * library. -HB */ #include "private/gc_priv.h" # if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) \ || defined(GC_SOLARIS_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. */ static void disable_gc_for_dlopen() { LOCK(); while (GC_incremental && GC_collection_in_progress()) { GC_collect_a_little_inner(1000); } ++GC_dont_gc; UNLOCK(); } /* Redefine dlopen to guarantee mutual exclusion with */ /* GC_register_dynamic_libraries. */ /* Should probably happen for other operating systems, too. */ #include #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; # ifndef USE_PROC_FOR_LIBRARIES 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_enable(); /* undoes disable_gc_for_dlopen */ # endif return(result); } # endif /* GC_PTHREADS || GC_SOLARIS_THREADS ... */