1447762daSMichael J. Spencer //===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
2447762daSMichael J. Spencer //
3447762daSMichael J. Spencer //                     The LLVM Compiler Infrastructure
4447762daSMichael J. Spencer //
5447762daSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
6447762daSMichael J. Spencer // License. See LICENSE.TXT for details.
7447762daSMichael J. Spencer //
8447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
9447762daSMichael J. Spencer //
10447762daSMichael J. Spencer // This file implements the llvm::sys::ThreadLocal class.
11447762daSMichael J. Spencer //
12447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
13447762daSMichael J. Spencer 
14447762daSMichael J. Spencer #include "llvm/Config/config.h"
15447762daSMichael J. Spencer #include "llvm/Support/ThreadLocal.h"
16447762daSMichael J. Spencer 
17447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
18447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system
19447762daSMichael J. Spencer //===          independent code.
20447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
21447762daSMichael J. Spencer 
22efddf201SDylan Noblesmith #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
23447762daSMichael J. Spencer // Define all methods as no-ops if threading is explicitly disabled
24447762daSMichael J. Spencer namespace llvm {
25447762daSMichael J. Spencer using namespace sys;
26*fabf8bfdSHans Wennborg ThreadLocalImpl::ThreadLocalImpl() : data() { }
27447762daSMichael J. Spencer ThreadLocalImpl::~ThreadLocalImpl() { }
28444fd426SArgyrios Kyrtzidis void ThreadLocalImpl::setInstance(const void* d) {
29444fd426SArgyrios Kyrtzidis   typedef int SIZE_TOO_BIG[sizeof(d) <= sizeof(data) ? 1 : -1];
30444fd426SArgyrios Kyrtzidis   void **pd = reinterpret_cast<void**>(&data);
31444fd426SArgyrios Kyrtzidis   *pd = const_cast<void*>(d);
32444fd426SArgyrios Kyrtzidis }
3346785f94SArgyrios Kyrtzidis const void* ThreadLocalImpl::getInstance() {
34444fd426SArgyrios Kyrtzidis   void **pd = reinterpret_cast<void**>(&data);
3546785f94SArgyrios Kyrtzidis   return *pd;
3646785f94SArgyrios Kyrtzidis }
3746785f94SArgyrios Kyrtzidis void ThreadLocalImpl::removeInstance() {
3846785f94SArgyrios Kyrtzidis   setInstance(0);
39444fd426SArgyrios Kyrtzidis }
40447762daSMichael J. Spencer }
41447762daSMichael J. Spencer #else
42447762daSMichael J. Spencer 
43447762daSMichael J. Spencer #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
44447762daSMichael J. Spencer 
45447762daSMichael J. Spencer #include <cassert>
46447762daSMichael J. Spencer #include <pthread.h>
47447762daSMichael J. Spencer #include <stdlib.h>
48447762daSMichael J. Spencer 
49447762daSMichael J. Spencer namespace llvm {
50447762daSMichael J. Spencer using namespace sys;
51447762daSMichael J. Spencer 
52c6dc4d75SArgyrios Kyrtzidis ThreadLocalImpl::ThreadLocalImpl() : data() {
538d19c86cSArgyrios Kyrtzidis   typedef int SIZE_TOO_BIG[sizeof(pthread_key_t) <= sizeof(data) ? 1 : -1];
548d19c86cSArgyrios Kyrtzidis   pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
55447762daSMichael J. Spencer   int errorcode = pthread_key_create(key, NULL);
56447762daSMichael J. Spencer   assert(errorcode == 0);
57447762daSMichael J. Spencer   (void) errorcode;
58447762daSMichael J. Spencer }
59447762daSMichael J. Spencer 
60447762daSMichael J. Spencer ThreadLocalImpl::~ThreadLocalImpl() {
618d19c86cSArgyrios Kyrtzidis   pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
62447762daSMichael J. Spencer   int errorcode = pthread_key_delete(*key);
63447762daSMichael J. Spencer   assert(errorcode == 0);
64447762daSMichael J. Spencer   (void) errorcode;
65447762daSMichael J. Spencer }
66447762daSMichael J. Spencer 
67447762daSMichael J. Spencer void ThreadLocalImpl::setInstance(const void* d) {
688d19c86cSArgyrios Kyrtzidis   pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
69447762daSMichael J. Spencer   int errorcode = pthread_setspecific(*key, d);
70447762daSMichael J. Spencer   assert(errorcode == 0);
71447762daSMichael J. Spencer   (void) errorcode;
72447762daSMichael J. Spencer }
73447762daSMichael J. Spencer 
74447762daSMichael J. Spencer const void* ThreadLocalImpl::getInstance() {
758d19c86cSArgyrios Kyrtzidis   pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
76447762daSMichael J. Spencer   return pthread_getspecific(*key);
77447762daSMichael J. Spencer }
78447762daSMichael J. Spencer 
79447762daSMichael J. Spencer void ThreadLocalImpl::removeInstance() {
80447762daSMichael J. Spencer   setInstance(0);
81447762daSMichael J. Spencer }
82447762daSMichael J. Spencer 
83447762daSMichael J. Spencer }
84447762daSMichael J. Spencer 
85447762daSMichael J. Spencer #elif defined(LLVM_ON_UNIX)
86447762daSMichael J. Spencer #include "Unix/ThreadLocal.inc"
87447762daSMichael J. Spencer #elif defined( LLVM_ON_WIN32)
88447762daSMichael J. Spencer #include "Windows/ThreadLocal.inc"
89447762daSMichael J. Spencer #else
90037fc931SDaniel Dunbar #warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 set in Support/ThreadLocal.cpp
91447762daSMichael J. Spencer #endif
92447762daSMichael J. Spencer #endif
93