Line data Source code
1 : /*
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.
5 : *
6 : * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7 : * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
8 : *
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.
14 : *
15 : * Original author: Bill Janssen
16 : * Heavily modified by Hans Boehm and others
17 : */
18 :
19 : #include "private/gc_priv.h"
20 :
21 : /* This used to be in dyn_load.c. It was extracted into a separate */
22 : /* file to avoid having to link against libdl.{a,so} if the client */
23 : /* doesn't call dlopen. Of course this fails if the collector is in */
24 : /* a dynamic library. -HB */
25 : #if defined(GC_PTHREADS) && !defined(GC_NO_DLOPEN)
26 :
27 : #undef GC_MUST_RESTORE_REDEFINED_DLOPEN
28 : #if defined(dlopen) && !defined(GC_USE_LD_WRAP)
29 : /* To support various threads pkgs, gc.h interposes on dlopen by */
30 : /* defining "dlopen" to be "GC_dlopen", which is implemented below. */
31 : /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */
32 : /* real system dlopen() in their implementation. We first remove */
33 : /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
34 : # undef dlopen
35 : # define GC_MUST_RESTORE_REDEFINED_DLOPEN
36 : #endif
37 :
38 : /* Make sure we're not in the middle of a collection, and make sure we */
39 : /* don't start any. This is invoked prior to a dlopen call to avoid */
40 : /* synchronization issues. We can't just acquire the allocation lock, */
41 : /* since startup code in dlopen may try to allocate. This solution */
42 : /* risks heap growth (or, even, heap overflow) in the presence of many */
43 : /* dlopen calls in either a multi-threaded environment, or if the */
44 : /* library initialization code allocates substantial amounts of GC'ed */
45 : /* memory. */
46 : #ifndef USE_PROC_FOR_LIBRARIES
47 0 : static void disable_gc_for_dlopen(void)
48 : {
49 : DCL_LOCK_STATE;
50 0 : LOCK();
51 0 : while (GC_incremental && GC_collection_in_progress()) {
52 0 : GC_collect_a_little_inner(1000);
53 : }
54 0 : ++GC_dont_gc;
55 0 : UNLOCK();
56 0 : }
57 : #endif
58 :
59 : /* Redefine dlopen to guarantee mutual exclusion with */
60 : /* GC_register_dynamic_libraries. Should probably happen for */
61 : /* other operating systems, too. */
62 :
63 : /* This is similar to WRAP/REAL_FUNC() in pthread_support.c. */
64 : #ifdef GC_USE_LD_WRAP
65 : # define WRAP_DLFUNC(f) __wrap_##f
66 : # define REAL_DLFUNC(f) __real_##f
67 : void * REAL_DLFUNC(dlopen)(const char *, int);
68 : #else
69 : # define WRAP_DLFUNC(f) GC_##f
70 : # define REAL_DLFUNC(f) f
71 : #endif
72 :
73 0 : GC_API void * WRAP_DLFUNC(dlopen)(const char *path, int mode)
74 : {
75 : void * result;
76 :
77 : # ifndef USE_PROC_FOR_LIBRARIES
78 : /* Disable collections. This solution risks heap growth (or, */
79 : /* even, heap overflow) but there seems no better solutions. */
80 0 : disable_gc_for_dlopen();
81 : # endif
82 0 : result = REAL_DLFUNC(dlopen)(path, mode);
83 : # ifndef USE_PROC_FOR_LIBRARIES
84 0 : GC_enable(); /* undoes disable_gc_for_dlopen */
85 : # endif
86 0 : return(result);
87 : }
88 :
89 : #ifdef GC_USE_LD_WRAP
90 : /* Define GC_ function as an alias for the plain one, which will be */
91 : /* intercepted. This allows files which include gc.h, and hence */
92 : /* generate references to the GC_ symbol, to see the right symbol. */
93 : GC_API void *GC_dlopen(const char *path, int mode)
94 : {
95 : return dlopen(path, mode);
96 : }
97 : #endif /* GC_USE_LD_WRAP */
98 :
99 : #ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN
100 : # define dlopen GC_dlopen
101 : #endif
102 :
103 : #endif /* GC_PTHREADS && !GC_NO_DLOPEN */
|