thread_local_alloc.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
  3. *
  4. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  6. *
  7. * Permission is hereby granted to use or copy this program
  8. * for any purpose, provided the above notices are retained on all copies.
  9. * Permission to modify the code and to distribute modified code is granted,
  10. * provided the above notices are retained, and a notice that the code was
  11. * modified is included with the above copyright notice.
  12. */
  13. /* Included indirectly from a thread-library-specific file. */
  14. /* This is the interface for thread-local allocation, whose */
  15. /* implementation is mostly thread-library-independent. */
  16. /* Here we describe only the interface that needs to be known */
  17. /* and invoked from the thread support layer; the actual */
  18. /* implementation also exports GC_malloc and friends, which */
  19. /* are declared in gc.h. */
  20. #ifndef GC_THREAD_LOCAL_ALLOC_H
  21. #define GC_THREAD_LOCAL_ALLOC_H
  22. #include "private/gc_priv.h"
  23. #ifdef THREAD_LOCAL_ALLOC
  24. #include "gc_inline.h"
  25. #if defined(USE_HPUX_TLS)
  26. # error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS
  27. #endif
  28. #if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) \
  29. && !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) \
  30. && !defined(USE_CUSTOM_SPECIFIC)
  31. # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
  32. # if defined(CYGWIN32) && (__GNUC__ >= 4)
  33. # if defined(__clang__)
  34. /* As of Cygwin clang3.1, thread-local storage is unsupported. */
  35. # define USE_PTHREAD_SPECIFIC
  36. # else
  37. # define USE_COMPILER_TLS
  38. # endif
  39. # elif defined(__GNUC__) || defined(MSWINCE)
  40. # define USE_WIN32_SPECIFIC
  41. # else
  42. # define USE_WIN32_COMPILER_TLS
  43. # endif /* !GNU */
  44. # elif (defined(LINUX) && !defined(ARM32) && !defined(AVR32) \
  45. && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) \
  46. && !(defined(__clang__) && defined(PLATFORM_ANDROID))) \
  47. || (defined(PLATFORM_ANDROID) && defined(ARM32) \
  48. && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
  49. /* As of Android NDK r8e, Clang cannot find __tls_get_addr. */
  50. # define USE_COMPILER_TLS
  51. # elif defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) \
  52. || defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \
  53. || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS) \
  54. || defined(GC_LINUX_THREADS) || defined(GC_RTEMS_PTHREADS)
  55. # define USE_PTHREAD_SPECIFIC
  56. # elif defined(GC_HPUX_THREADS)
  57. # ifdef __GNUC__
  58. # define USE_PTHREAD_SPECIFIC
  59. /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work. */
  60. # else
  61. # define USE_COMPILER_TLS
  62. # endif
  63. # else
  64. # define USE_CUSTOM_SPECIFIC /* Use our own. */
  65. # endif
  66. #endif
  67. #include <stdlib.h>
  68. /* One of these should be declared as the tlfs field in the */
  69. /* structure pointed to by a GC_thread. */
  70. typedef struct thread_local_freelists {
  71. void * ptrfree_freelists[TINY_FREELISTS];
  72. void * normal_freelists[TINY_FREELISTS];
  73. # ifdef GC_GCJ_SUPPORT
  74. void * gcj_freelists[TINY_FREELISTS];
  75. # define ERROR_FL ((void *)(word)-1)
  76. /* Value used for gcj_freelist[-1]; allocation is */
  77. /* erroneous. */
  78. # endif
  79. # ifdef ENABLE_DISCLAIM
  80. void * finalized_freelists[TINY_FREELISTS];
  81. # endif
  82. /* Free lists contain either a pointer or a small count */
  83. /* reflecting the number of granules allocated at that */
  84. /* size. */
  85. /* 0 ==> thread-local allocation in use, free list */
  86. /* empty. */
  87. /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */
  88. /* too few objects of this size have been */
  89. /* allocated by this thread. */
  90. /* >= HBLKSIZE => pointer to nonempty free list. */
  91. /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */
  92. /* local alloc, equivalent to 0. */
  93. # define DIRECT_GRANULES (HBLKSIZE/GRANULE_BYTES)
  94. /* Don't use local free lists for up to this much */
  95. /* allocation. */
  96. } *GC_tlfs;
  97. #if defined(USE_PTHREAD_SPECIFIC)
  98. # define GC_getspecific pthread_getspecific
  99. # define GC_setspecific pthread_setspecific
  100. # define GC_key_create pthread_key_create
  101. # define GC_remove_specific(key) /* No need for cleanup on exit. */
  102. typedef pthread_key_t GC_key_t;
  103. #elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS)
  104. # define GC_getspecific(x) (x)
  105. # define GC_setspecific(key, v) ((key) = (v), 0)
  106. # define GC_key_create(key, d) 0
  107. # define GC_remove_specific(key) /* No need for cleanup on exit. */
  108. typedef void * GC_key_t;
  109. #elif defined(USE_WIN32_SPECIFIC)
  110. # ifndef WIN32_LEAN_AND_MEAN
  111. # define WIN32_LEAN_AND_MEAN 1
  112. # endif
  113. # define NOSERVICE
  114. # include <windows.h>
  115. # define GC_getspecific TlsGetValue
  116. # define GC_setspecific(key, v) !TlsSetValue(key, v)
  117. /* We assume 0 == success, msft does the opposite. */
  118. # ifndef TLS_OUT_OF_INDEXES
  119. /* this is currently missing in WinCE */
  120. # define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
  121. # endif
  122. # define GC_key_create(key, d) \
  123. ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0)
  124. # define GC_remove_specific(key) /* No need for cleanup on exit. */
  125. /* Need TlsFree on process exit/detach? */
  126. typedef DWORD GC_key_t;
  127. #elif defined(USE_CUSTOM_SPECIFIC)
  128. # include "private/specific.h"
  129. #else
  130. # error implement me
  131. #endif
  132. /* Each thread structure must be initialized. */
  133. /* This call must be made from the new thread. */
  134. /* Caller holds allocation lock. */
  135. GC_INNER void GC_init_thread_local(GC_tlfs p);
  136. /* Called when a thread is unregistered, or exits. */
  137. /* We hold the allocator lock. */
  138. GC_INNER void GC_destroy_thread_local(GC_tlfs p);
  139. /* The thread support layer must arrange to mark thread-local */
  140. /* free lists explicitly, since the link field is often */
  141. /* invisible to the marker. It knows how to find all threads; */
  142. /* we take care of an individual thread freelist structure. */
  143. GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p);
  144. #ifdef ENABLE_DISCLAIM
  145. GC_EXTERN ptr_t * GC_finalized_objfreelist;
  146. #endif
  147. extern
  148. #if defined(USE_COMPILER_TLS)
  149. __thread
  150. #elif defined(USE_WIN32_COMPILER_TLS)
  151. __declspec(thread)
  152. #endif
  153. GC_key_t GC_thread_key;
  154. /* This is set up by the thread_local_alloc implementation. No need */
  155. /* for cleanup on thread exit. But the thread support layer makes sure */
  156. /* that GC_thread_key is traced, if necessary. */
  157. #endif /* THREAD_LOCAL_ALLOC */
  158. #endif /* GC_THREAD_LOCAL_ALLOC_H */