1 |
12 |
jlechner |
/*
|
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 |
|
|
/*
|
20 |
|
|
* This used to be in dyn_load.c. It was extracted into a separate file
|
21 |
|
|
* to avoid having to link against libdl.{a,so} if the client doesn't call
|
22 |
|
|
* dlopen. Of course this fails if the collector is in a dynamic
|
23 |
|
|
* library. -HB
|
24 |
|
|
*/
|
25 |
|
|
|
26 |
|
|
#include "private/gc_priv.h"
|
27 |
|
|
|
28 |
|
|
# if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) \
|
29 |
|
|
|| defined(GC_SOLARIS_THREADS)
|
30 |
|
|
|
31 |
|
|
# if defined(dlopen) && !defined(GC_USE_LD_WRAP)
|
32 |
|
|
/* To support various threads pkgs, gc.h interposes on dlopen by */
|
33 |
|
|
/* defining "dlopen" to be "GC_dlopen", which is implemented below. */
|
34 |
|
|
/* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */
|
35 |
|
|
/* real system dlopen() in their implementation. We first remove */
|
36 |
|
|
/* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
|
37 |
|
|
# undef dlopen
|
38 |
|
|
# endif
|
39 |
|
|
|
40 |
|
|
/* Make sure we're not in the middle of a collection, and make */
|
41 |
|
|
/* sure we don't start any. Returns previous value of GC_dont_gc. */
|
42 |
|
|
/* This is invoked prior to a dlopen call to avoid synchronization */
|
43 |
|
|
/* issues. We can't just acquire the allocation lock, since startup */
|
44 |
|
|
/* code in dlopen may try to allocate. */
|
45 |
|
|
/* This solution risks heap growth in the presence of many dlopen */
|
46 |
|
|
/* calls in either a multithreaded environment, or if the library */
|
47 |
|
|
/* initialization code allocates substantial amounts of GC'ed memory. */
|
48 |
|
|
/* But I don't know of a better solution. */
|
49 |
|
|
static void disable_gc_for_dlopen()
|
50 |
|
|
{
|
51 |
|
|
LOCK();
|
52 |
|
|
while (GC_incremental && GC_collection_in_progress()) {
|
53 |
|
|
GC_collect_a_little_inner(1000);
|
54 |
|
|
}
|
55 |
|
|
++GC_dont_gc;
|
56 |
|
|
UNLOCK();
|
57 |
|
|
}
|
58 |
|
|
|
59 |
|
|
/* Redefine dlopen to guarantee mutual exclusion with */
|
60 |
|
|
/* GC_register_dynamic_libraries. */
|
61 |
|
|
/* Should probably happen for other operating systems, too. */
|
62 |
|
|
|
63 |
|
|
#include <dlfcn.h>
|
64 |
|
|
|
65 |
|
|
#ifdef GC_USE_LD_WRAP
|
66 |
|
|
void * __wrap_dlopen(const char *path, int mode)
|
67 |
|
|
#else
|
68 |
|
|
void * GC_dlopen(path, mode)
|
69 |
|
|
GC_CONST char * path;
|
70 |
|
|
int mode;
|
71 |
|
|
#endif
|
72 |
|
|
{
|
73 |
|
|
void * result;
|
74 |
|
|
|
75 |
|
|
# ifndef USE_PROC_FOR_LIBRARIES
|
76 |
|
|
disable_gc_for_dlopen();
|
77 |
|
|
# endif
|
78 |
|
|
# ifdef GC_USE_LD_WRAP
|
79 |
|
|
result = (void *)__real_dlopen(path, mode);
|
80 |
|
|
# else
|
81 |
|
|
result = dlopen(path, mode);
|
82 |
|
|
# endif
|
83 |
|
|
# ifndef USE_PROC_FOR_LIBRARIES
|
84 |
|
|
GC_enable(); /* undoes disable_gc_for_dlopen */
|
85 |
|
|
# endif
|
86 |
|
|
return(result);
|
87 |
|
|
}
|
88 |
|
|
# endif /* GC_PTHREADS || GC_SOLARIS_THREADS ... */
|
89 |
|
|
|
90 |
|
|
|
91 |
|
|
|