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