2 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
3 * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
4 * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9 * Permission is hereby granted to use or copy this program
10 * for any purpose, provided the above notices are retained on all copies.
11 * Permission to modify the code and to distribute modified code is granted,
12 * provided the above notices are retained, and a notice that the code was
13 * modified is included with the above copyright notice.
15 * Original author: Bill Janssen
16 * Heavily modified by Hans Boehm and others
19 #include "private/gc_priv.h"
22 * This used to be in dyn_load.c. It was extracted into a separate file
23 * to avoid having to link against libdl.{a,so} if the client doesn't call
24 * dlopen. Of course this fails if the collector is in a dynamic
28 # if defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS) \
29 && !defined(GC_WIN32_PTHREADS)
31 # undef GC_MUST_RESTORE_REDEFINED_DLOPEN
32 # if defined(dlopen) && !defined(GC_USE_LD_WRAP)
33 /* To support various threads pkgs, gc.h interposes on dlopen by */
34 /* defining "dlopen" to be "GC_dlopen", which is implemented below. */
35 /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */
36 /* real system dlopen() in their implementation. We first remove */
37 /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
39 # define GC_MUST_RESTORE_REDEFINED_DLOPEN
42 /* Make sure we're not in the middle of a collection, and make */
43 /* sure we don't start any. Returns previous value of GC_dont_gc. */
44 /* This is invoked prior to a dlopen call to avoid synchronization */
45 /* issues. We can't just acquire the allocation lock, since startup */
46 /* code in dlopen may try to allocate. */
47 /* This solution risks heap growth in the presence of many dlopen */
48 /* calls in either a multithreaded environment, or if the library */
49 /* initialization code allocates substantial amounts of GC'ed memory. */
50 /* But I don't know of a better solution. */
51 static void disable_gc_for_dlopen(void)
54 while (GC_incremental && GC_collection_in_progress()) {
55 GC_collect_a_little_inner(1000);
61 /* Redefine dlopen to guarantee mutual exclusion with */
62 /* GC_register_dynamic_libraries. */
63 /* Should probably happen for other operating systems, too. */
67 /* This is similar to WRAP/REAL_FUNC() in pthread_support.c. */
69 # define WRAP_DLFUNC(f) __wrap_##f
70 # define REAL_DLFUNC(f) __real_##f
72 # define WRAP_DLFUNC(f) GC_##f
73 # define REAL_DLFUNC(f) f
76 GC_API void * WRAP_DLFUNC(dlopen)(const char *path, int mode)
80 # ifndef USE_PROC_FOR_LIBRARIES
81 disable_gc_for_dlopen();
83 result = (void *)REAL_DLFUNC(dlopen)(path, mode);
84 # ifndef USE_PROC_FOR_LIBRARIES
85 GC_enable(); /* undoes disable_gc_for_dlopen */
91 /* Define GC_ function as an alias for the plain one, which will be */
92 /* intercepted. This allows files which include gc.h, and hence */
93 /* generate references to the GC_ symbol, to see the right symbol. */
94 GC_API int GC_dlopen(const char *path, int mode)
96 return dlopen(path, mode);
98 #endif /* Linker-based interception. */
100 # ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN
101 # define dlopen GC_dlopen
104 #endif /* GC_PTHREADS */