implemented Setup.hs to build boehm cpp libs and install them;
[hs-boehmgc.git] / gc-7.2 / gc_dlopen.c
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   static void disable_gc_for_dlopen(void)
48   {
49     DCL_LOCK_STATE;
50     LOCK();
51     while (GC_incremental && GC_collection_in_progress()) {
52       GC_collect_a_little_inner(1000);
53     }
54     ++GC_dont_gc;
55     UNLOCK();
56   }
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 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     disable_gc_for_dlopen();
81 # endif
82   result = REAL_DLFUNC(dlopen)(path, mode);
83 # ifndef USE_PROC_FOR_LIBRARIES
84     GC_enable(); /* undoes disable_gc_for_dlopen */
85 # endif
86   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 */