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 14 /* Included indirectly from a thread-library-specific file. */ 15 /* This is the interface for thread-local allocation, whose */ 16 /* implementation is mostly thread-library-independent. */ 17 /* Here we describe only the interface that needs to be known */ 18 /* and invoked from the thread support layer; the actual */ 19 /* implementation also exports GC_malloc and friends, which */ 20 /* are declared in gc.h. */ 21 22 #include "private/gc_priv.h" 23 24 #if defined(THREAD_LOCAL_ALLOC) 25 26 #include "gc_inline.h" 27 28 29 # if defined USE_HPUX_TLS 30 # error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS 31 # endif 32 33 # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) && \ 34 !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) && \ 35 !defined(USE_CUSTOM_SPECIFIC) 36 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) 37 # if defined(__GNUC__) /* Fixed for versions past 2.95? */ 38 # define USE_WIN32_SPECIFIC 39 # else 40 # define USE_WIN32_COMPILER_TLS 41 # endif /* !GNU */ 42 # elif defined(LINUX) && !defined(ARM32) && \ 43 (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >=3)) 44 # define USE_COMPILER_TLS 45 # elif (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ 46 defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ 47 defined(GC_NETBSD_THREADS) 48 # define USE_PTHREAD_SPECIFIC 49 # elif defined(GC_HPUX_THREADS) 50 # ifdef __GNUC__ 51 # define USE_PTHREAD_SPECIFIC 52 /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work. */ 53 # else 54 # define USE_COMPILER_TLS 55 # endif 56 # else 57 # define USE_CUSTOM_SPECIFIC /* Use our own. */ 58 # endif 59 # endif 60 61 # include <stdlib.h> 62 63 /* One of these should be declared as the tlfs field in the */ 64 /* structure pointed to by a GC_thread. */ 65 typedef struct thread_local_freelists { 66 # ifdef THREAD_LOCAL_ALLOC 67 void * ptrfree_freelists[TINY_FREELISTS]; 68 void * normal_freelists[TINY_FREELISTS]; 69 # ifdef GC_GCJ_SUPPORT 70 void * gcj_freelists[TINY_FREELISTS]; 71 # define ERROR_FL (void *)(-1) 72 /* Value used for gcj_freelist[-1]; allocation is */ 73 /* erroneous. */ 74 # endif 75 /* Free lists contain either a pointer or a small count */ 76 /* reflecting the number of granules allocated at that */ 77 /* size. */ 78 /* 0 ==> thread-local allocation in use, free list */ 79 /* empty. */ 80 /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */ 81 /* too few objects of this size have been */ 82 /* allocated by this thread. */ 83 /* >= HBLKSIZE => pointer to nonempty free list. */ 84 /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */ 85 /* local alloc, equivalent to 0. */ 86 # define DIRECT_GRANULES (HBLKSIZE/GRANULE_BYTES) 87 /* Don't use local free lists for up to this much */ 88 /* allocation. */ 89 90 # endif 91 } *GC_tlfs; 92 93 # if defined(USE_PTHREAD_SPECIFIC) 94 # define GC_getspecific pthread_getspecific 95 # define GC_setspecific pthread_setspecific 96 # define GC_key_create pthread_key_create 97 # define GC_remove_specific(key) /* No need for cleanup on exit. */ 98 typedef pthread_key_t GC_key_t; 99 # elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) 100 # define GC_getspecific(x) (x) 101 # define GC_setspecific(key, v) ((key) = (v), 0) 102 # define GC_key_create(key, d) 0 103 # define GC_remove_specific(key) /* No need for cleanup on exit. */ 104 typedef void * GC_key_t; 105 # elif defined(USE_WIN32_SPECIFIC) 106 # include <windows.h> 107 # define GC_getspecific TlsGetValue 108 # define GC_setspecific(key, v) !TlsSetValue(key, v) 109 /* We assume 0 == success, msft does the opposite. */ 110 # define GC_key_create(key, d) \ 111 ((d) != 0? (ABORT("Destructor unsupported by TlsAlloc"),0) \ 112 : (*(key) = TlsAlloc(), 0)) 113 # define GC_remove_specific(key) /* No need for cleanup on thread exit. */ 114 /* Need TlsFree on process exit/detach ? */ 115 typedef DWORD GC_key_t; 116 # elif defined(USE_CUSTOM_SPECIFIC) 117 # include "private/specific.h" 118 # else 119 # error implement me 120 # endif 121 122 123 /* Each thread structure must be initialized. */ 124 /* This call must be made from the new thread. */ 125 /* Caller holds allocation lock. */ 126 void GC_init_thread_local(GC_tlfs p); 127 128 /* Called when a thread is unregistered, or exits. */ 129 /* We hold the allocator lock. */ 130 void GC_destroy_thread_local(GC_tlfs p); 131 132 /* The thread support layer must arrange to mark thread-local */ 133 /* free lists explicitly, since the link field is often */ 134 /* invisible to the marker. It knows hoe to find all threads; */ 135 /* we take care of an individual thread freelist structure. */ 136 void GC_mark_thread_local_fls_for(GC_tlfs p); 137 138 extern 139 #if defined(USE_COMPILER_TLS) 140 __thread 141 #elif defined(USE_WIN32_COMPILER_TLS) 142 __declspec(thread) 143 #endif 144 GC_key_t GC_thread_key; 145 146 /* This is set up by the thread_local_alloc implementation. But the */ 147 /* thread support layer calls GC_remove_specific(GC_thread_key) */ 148 /* before a thread exits. */ 149 /* And the thread support layer makes sure that GC_thread_key is traced,*/ 150 /* if necessary. */ 151 152 #endif /* THREAD_LOCAL_ALLOC */ 153