source: proiecte/swift/trunk/lib/hoard-371/src/userealtls.cpp @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 6.3 KB
Line 
1/**
2 * @file userealtls.cpp
3 * @author Emery Berger <http://www.cs.umass.edu/~emery>
4 *
5 * This file leverages compiler support for thread-local variables for
6 * access to thread-local heaps. It also intercepts thread completions
7 * to flush these local heaps, returning any unused memory to the
8 * global Hoard heap. On Windows, this happens in DllMain. On Unix
9 * platforms, we interpose our own versions of pthread_create and
10 * pthread_exit.
11*/
12
13#include "VERSION.h"
14
15#if defined(_WIN32)
16DWORD LocalTLABIndex;
17#endif
18
19#include <new>
20
21// For now, we only use thread-local variables (__thread)
22//   (a) for Linux x86-32 platforms with gcc version > 3.3.0, and
23//   (b) when compiling with the SunPro compilers.
24
25#if ((GCC_VERSION >= 30300) && !defined(__x86_64) && !defined(__SVR4) && !defined(__MACH__)) \
26    || defined(__SUNPRO_CC)
27#define USE_THREAD_KEYWORD 1
28#endif
29
30
31#if defined(USE_THREAD_KEYWORD)
32
33static __thread double tlabBuffer[sizeof(TheCustomHeapType) / sizeof(double) + 1];
34
35static __thread TheCustomHeapType * theTLAB = NULL;
36
37static TheCustomHeapType * initializeCustomHeap (void) {
38  new ((char *) &tlabBuffer) TheCustomHeapType (getMainHoardHeap());
39  return (theTLAB = (TheCustomHeapType *) &tlabBuffer);
40}
41
42inline TheCustomHeapType * getCustomHeap (void) {
43  // The pointer to the TLAB itself.
44  theTLAB = (theTLAB ? theTLAB : initializeCustomHeap());
45  return theTLAB;
46}
47
48#else
49
50#if !defined(_WIN32)
51static pthread_key_t theHeapKey;
52static pthread_once_t key_once = PTHREAD_ONCE_INIT;
53
54static void deleteThatHeap (void * p) {
55  // Called when the thread goes away - reclaims the heap.
56  TheCustomHeapType * heap = (TheCustomHeapType *) p;
57  heap->~TheCustomHeapType();
58  getMainHoardHeap()->free ((void *) heap);
59}
60
61static void make_heap_key (void)
62{
63  if (pthread_key_create (&theHeapKey, deleteThatHeap) != 0) {
64    // This should never happen.
65  }
66}
67
68static void createKey (void) {
69  // Ensure that the key is initialized.
70  pthread_once (&key_once, make_heap_key);
71}
72
73#endif
74
75
76static TheCustomHeapType * initializeCustomHeap (void)
77{
78#if !defined(_WIN32)
79  createKey();
80  assert (pthread_getspecific (theHeapKey) == NULL);
81#endif
82  // Allocate a per-thread heap.
83  TheCustomHeapType * heap;
84  size_t sz = sizeof(TheCustomHeapType) + sizeof(double);
85  void * mh = getMainHoardHeap()->malloc(sz);
86  heap = new ((char *) mh) TheCustomHeapType (getMainHoardHeap());
87
88  // Store it in the appropriate thread-local area.
89#if defined(_WIN32)
90  TlsSetValue (LocalTLABIndex, heap);
91#else
92  int r = pthread_setspecific (theHeapKey, (void *) heap);
93  assert (!r);
94#endif
95
96  return heap;
97}
98
99
100inline TheCustomHeapType * getCustomHeap (void) {
101  TheCustomHeapType * heap;
102#if defined(_WIN32)
103  heap = (TheCustomHeapType *) TlsGetValue (LocalTLABIndex);
104#else
105  createKey();
106  heap = (TheCustomHeapType *) pthread_getspecific (theHeapKey);
107#endif
108  if (heap == NULL)  {
109    heap = initializeCustomHeap();
110  }
111  return heap;
112}
113
114
115
116#endif
117
118//
119// Intercept thread creation and destruction to flush the TLABs.
120//
121
122#if defined(_WIN32)
123
124#ifndef HOARD_PRE_ACTION
125#define HOARD_PRE_ACTION
126#endif
127
128#ifndef HOARD_POST_ACTION
129#define HOARD_POST_ACTION
130#endif
131
132#include <stdio.h>
133
134#ifndef CUSTOM_DLLNAME
135#define CUSTOM_DLLNAME DllMain
136#endif
137
138extern "C" {
139
140BOOL WINAPI CUSTOM_DLLNAME (HANDLE hinstDLL, DWORD fdwReason, LPVOID lpreserved)
141{
142  int i;
143  int tid;
144  static int np = HL::CPUInfo::computeNumProcessors();
145
146  switch (fdwReason) {
147
148  case DLL_PROCESS_ATTACH:
149    {
150      LocalTLABIndex = TlsAlloc();
151      if (LocalTLABIndex == TLS_OUT_OF_INDEXES) {
152        // Not sure what to do here!
153      }
154      HOARD_PRE_ACTION;
155      getCustomHeap();
156    }
157    break;
158
159  case DLL_THREAD_ATTACH:
160    if (np == 1) {
161      // We have exactly one processor - just assign the thread to
162      // heap 0.
163      getMainHoardHeap()->chooseZero();
164    } else {
165      getMainHoardHeap()->findUnusedHeap();
166    }
167    getCustomHeap();
168    break;
169
170  case DLL_THREAD_DETACH:
171    {
172      // Dump the memory from the TLAB.
173      getCustomHeap()->clear();
174
175      TheCustomHeapType *heap
176        = (TheCustomHeapType *) TlsGetValue(LocalTLABIndex);
177
178      if (np != 1) {
179        // If we're on a multiprocessor box, relinquish the heap
180        // assigned to this thread.
181        getMainHoardHeap()->releaseHeap();
182      }
183
184      if (heap != 0) {
185        TlsSetValue (LocalTLABIndex, 0);
186      }
187    }
188    break;
189
190  case DLL_PROCESS_DETACH:
191    HOARD_POST_ACTION;
192    break;
193
194  default:
195    return TRUE;
196  }
197
198  return TRUE;
199}
200
201}
202
203#else
204
205extern "C" {
206
207typedef void * (*threadFunctionType) (void *);
208
209typedef
210int (*pthread_create_function) (pthread_t *thread,
211                                const pthread_attr_t *attr,
212                                threadFunctionType start_routine,
213                                void *arg);
214}
215
216// A special routine we call on thread exits to free up some resources.
217static void exitRoutine (void) {
218  // Clear the TLAB's buffer.
219  getCustomHeap()->clear();
220
221  // Relinquish the assigned heap.
222  getMainHoardHeap()->releaseHeap();
223}
224
225
226extern "C" {
227
228static void * startMeUp (void * a)
229{
230  getCustomHeap();
231  getMainHoardHeap()->findUnusedHeap();
232
233  pair<threadFunctionType, void *> * z
234    = (pair<threadFunctionType, void *> *) a;
235
236  threadFunctionType f = z->first;
237  void * arg = z->second;
238  void * result = (*f)(arg);
239  exitRoutine();
240  delete z;
241  return result;
242}
243
244}
245
246#include <dlfcn.h>
247
248
249extern "C" int pthread_create (pthread_t *thread,
250                               const pthread_attr_t *attr,
251                               void * (*start_routine) (void *),
252                               void * arg)
253#if !defined(__SUNPRO_CC)
254  throw ()
255#endif
256{
257  // A pointer to the library version of pthread_create.
258  static pthread_create_function real_pthread_create = NULL;
259
260  // Force initialization of the TLAB before our first thread is created.
261  volatile static TheCustomHeapType * t = getCustomHeap();
262
263#if defined(linux)
264  char fname[] = "pthread_create";
265#else
266  char fname[] = "_pthread_create";
267#endif
268
269  // Instantiate the pointer to pthread_create, if it hasn't been
270  // instantiated yet.
271
272  if (real_pthread_create == NULL) {
273    real_pthread_create = (pthread_create_function) dlsym (RTLD_NEXT, fname);
274    if (real_pthread_create == NULL) {
275      fprintf (stderr, "Could not find the pthread_create function!\n");
276      fprintf (stderr, "Please report this problem to emery@cs.umass.edu.\n");
277      abort();
278    }
279  }
280
281  anyThreadCreated = 1;
282
283  pair<threadFunctionType, void *> * args =
284    new pair<threadFunctionType, void *> (start_routine, arg);
285
286  int result = (*real_pthread_create)(thread, attr, startMeUp, args);
287
288  return result;
289}
290
291#endif
Note: See TracBrowser for help on using the repository browser.