OSDN Git Service

* testsuite/27_io/istream_seeks.cc: Inform DejaGnu of required files.
[pf3gnuchains/gcc-fork.git] / boehm-gc / dyn_load.c
index 0785a6e..ec909ca 100644 (file)
@@ -32,7 +32,9 @@
 #include "gc_priv.h"
 
 /* BTL: avoid circular redefinition of dlopen if SOLARIS_THREADS defined */
-# if defined(SOLARIS_THREADS) && defined(dlopen)
+# if (defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \
+      || defined(HPUX_THREADS) || defined(IRIX_THREADS)) && defined(dlopen) \
+     && !defined(USE_LD_WRAP)
     /* To support threads in Solaris, 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   */
@@ -47,7 +49,7 @@
 #if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR)
 #if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
     !defined(MSWIN32) && !(defined(ALPHA) && defined(OSF1)) && \
-    !defined(HP_PA) && (!defined(LINUX) && !defined(__ELF__)) && \
+    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
     !defined(RS6000) && !defined(SCO_ELF)
  --> We only know how to find data segments of dynamic libraries for the
  --> above.  Additional SVR4 variants might not be too
@@ -159,32 +161,59 @@ static ptr_t GC_first_common()
 
 #endif  /* SUNOS4 ... */
 
-# if defined(SUNOS4) || defined(SUNOS5DL)
-/* Add dynamic library data sections to the root set.          */
-# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS)
-#   ifndef SRC_M3
-       --> fix mutual exclusion with dlopen
-#   endif  /* We assume M3 programs don't call dlopen for now */
-# endif
+# if defined(LINUX_THREADS) || defined(SOLARIS_THREADS) \
+     || defined(HPUX_THREADS) || defined(IRIX_THREADS)
+  /* 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.                            */
+  /* This can still deadlock if the client explicitly starts a GC      */
+  /* during the dlopen.  He shouldn't do that.                         */
+  static GC_bool disable_gc_for_dlopen()
+  {
+    GC_bool result;
+    LOCK();
+    result = GC_dont_gc;
+    while (GC_incremental && GC_collection_in_progress()) {
+       GC_collect_a_little_inner(1000);
+    }
+    GC_dont_gc = TRUE;
+    UNLOCK();
+    return(result);
+  }
 
-# ifdef SOLARIS_THREADS
   /* Redefine dlopen to guarantee mutual exclusion with        */
   /* GC_register_dynamic_libraries.                    */
-  /* assumes that dlopen doesn't need to call GC_malloc        */
-  /* and friends.                                      */
-# include <thread.h>
-# include <synch.h>
+  /* Should probably happen for other operating        systems, too. */
+
+#include <dlfcn.h>
 
-void * GC_dlopen(const char *path, int mode)
+#ifdef 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;
+    GC_bool dont_gc_save;
     
 #   ifndef USE_PROC_FOR_LIBRARIES
-      mutex_lock(&GC_allocate_ml);
+      dont_gc_save = disable_gc_for_dlopen();
+#   endif
+#   ifdef USE_LD_WRAP
+      result = __real_dlopen(path, mode);
+#   else
+      result = dlopen(path, mode);
 #   endif
-    result = dlopen(path, mode);
 #   ifndef USE_PROC_FOR_LIBRARIES
-      mutex_unlock(&GC_allocate_ml);
+      GC_dont_gc = dont_gc_save;
 #   endif
     return(result);
 }
@@ -195,6 +224,14 @@ void * GC_dlopen(const char *path, int mode)
 #   define dlopen GC_dlopen
 # endif
 
+# if defined(SUNOS4) || defined(SUNOS5DL)
+/* Add dynamic library data sections to the root set.          */
+# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS)
+#   ifndef SRC_M3
+       --> fix mutual exclusion with dlopen
+#   endif  /* We assume M3 programs don't call dlopen for now */
+# endif
+
 # ifndef USE_PROC_FOR_LIBRARIES
 void GC_register_dynamic_libraries()
 {
@@ -283,6 +320,9 @@ void GC_register_dynamic_libraries()
 static struct link_map *
 GC_FirstDLOpenedLinkMap()
 {
+#   ifdef __GNUC__
+#     pragma weak _DYNAMIC
+#   endif
     extern ElfW(Dyn) _DYNAMIC[];
     ElfW(Dyn) *dp;
     struct r_debug *r;
@@ -350,8 +390,12 @@ void GC_register_dynamic_libraries()
 #include <errno.h>
 
 extern void * GC_roots_present();
+       /* The type is a lie, since the real type doesn't make sense here, */
+       /* and we only test for NULL.                                      */
 
+#ifndef GC_scratch_last_end_ptr
 extern ptr_t GC_scratch_last_end_ptr; /* End of GC_scratch_alloc arena */
+#endif
 
 /* We use /proc to track down all parts of the address space that are  */
 /* mapped by the process, and throw out regions we know we shouldn't   */
@@ -376,6 +420,8 @@ void GC_register_dynamic_libraries()
 
     if (fd < 0) {
       sprintf(buf, "/proc/%d", getpid());
+       /* The above generates a lint complaint, since pid_t varies.    */
+       /* It's unclear how to improve this.                            */
       fd = open(buf, O_RDONLY);
       if (fd < 0) {
        ABORT("/proc open failed");
@@ -388,7 +434,8 @@ void GC_register_dynamic_libraries()
     if (needed_sz >= current_sz) {
         current_sz = needed_sz * 2 + 1;
                        /* Expansion, plus room for 0 record */
-        addr_map = (prmap_t *)GC_scratch_alloc(current_sz * sizeof(prmap_t));
+        addr_map = (prmap_t *)GC_scratch_alloc((word)
+                                               (current_sz * sizeof(prmap_t)));
     }
     if (ioctl(fd, PIOCMAP, addr_map) < 0) {
         GC_err_printf4("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
@@ -650,7 +697,7 @@ void GC_register_dynamic_libraries()
 }
 #endif
 
-#if defined(HP_PA)
+#if defined(HPUX)
 
 #include <errno.h>
 #include <dl.h>
@@ -673,6 +720,11 @@ void GC_register_dynamic_libraries()
 
       /* Check if this is the end of the list or if some error occured */
         if (status != 0) {
+#       ifdef HPUX_THREADS
+          /* I've seen errno values of 0.  The man page is not clear   */
+          /* as to whether errno should get set on a -1 return.        */
+          break;
+#       else
           if (errno == EINVAL) {
               break; /* Moved past end of shared library list --> finished */
           } else {
@@ -683,6 +735,7 @@ void GC_register_dynamic_libraries()
              }
               ABORT("shl_get failed");
           }
+#       endif
         }
 
 #     ifdef VERBOSE
@@ -705,7 +758,7 @@ void GC_register_dynamic_libraries()
         index++;
     }
 }
-#endif /* HP_PA */
+#endif /* HPUX */
 
 #ifdef RS6000
 #pragma alloca