gc_dlopen.c 3.8 KB

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