1218885Sdim//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file implements the llvm::sys::ThreadLocal class.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#include "llvm/Config/config.h"
15218885Sdim#include "llvm/Support/ThreadLocal.h"
16218885Sdim
17218885Sdim//===----------------------------------------------------------------------===//
18218885Sdim//=== WARNING: Implementation here must contain only TRULY operating system
19218885Sdim//===          independent code.
20218885Sdim//===----------------------------------------------------------------------===//
21218885Sdim
22235633Sdim#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
23218885Sdim// Define all methods as no-ops if threading is explicitly disabled
24218885Sdimnamespace llvm {
25218885Sdimusing namespace sys;
26263509SdimThreadLocalImpl::ThreadLocalImpl() : data() { }
27218885SdimThreadLocalImpl::~ThreadLocalImpl() { }
28245431Sdimvoid ThreadLocalImpl::setInstance(const void* d) {
29245431Sdim  typedef int SIZE_TOO_BIG[sizeof(d) <= sizeof(data) ? 1 : -1];
30245431Sdim  void **pd = reinterpret_cast<void**>(&data);
31245431Sdim  *pd = const_cast<void*>(d);
32218885Sdim}
33245431Sdimconst void* ThreadLocalImpl::getInstance() {
34245431Sdim  void **pd = reinterpret_cast<void**>(&data);
35245431Sdim  return *pd;
36245431Sdim}
37245431Sdimvoid ThreadLocalImpl::removeInstance() {
38245431Sdim  setInstance(0);
39245431Sdim}
40245431Sdim}
41218885Sdim#else
42218885Sdim
43218885Sdim#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
44218885Sdim
45218885Sdim#include <cassert>
46218885Sdim#include <pthread.h>
47218885Sdim#include <stdlib.h>
48218885Sdim
49218885Sdimnamespace llvm {
50218885Sdimusing namespace sys;
51218885Sdim
52245431SdimThreadLocalImpl::ThreadLocalImpl() : data() {
53245431Sdim  typedef int SIZE_TOO_BIG[sizeof(pthread_key_t) <= sizeof(data) ? 1 : -1];
54245431Sdim  pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
55218885Sdim  int errorcode = pthread_key_create(key, NULL);
56218885Sdim  assert(errorcode == 0);
57218885Sdim  (void) errorcode;
58218885Sdim}
59218885Sdim
60218885SdimThreadLocalImpl::~ThreadLocalImpl() {
61245431Sdim  pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
62218885Sdim  int errorcode = pthread_key_delete(*key);
63218885Sdim  assert(errorcode == 0);
64218885Sdim  (void) errorcode;
65218885Sdim}
66218885Sdim
67218885Sdimvoid ThreadLocalImpl::setInstance(const void* d) {
68245431Sdim  pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
69218885Sdim  int errorcode = pthread_setspecific(*key, d);
70218885Sdim  assert(errorcode == 0);
71218885Sdim  (void) errorcode;
72218885Sdim}
73218885Sdim
74218885Sdimconst void* ThreadLocalImpl::getInstance() {
75245431Sdim  pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
76218885Sdim  return pthread_getspecific(*key);
77218885Sdim}
78218885Sdim
79218885Sdimvoid ThreadLocalImpl::removeInstance() {
80218885Sdim  setInstance(0);
81218885Sdim}
82218885Sdim
83218885Sdim}
84218885Sdim
85218885Sdim#elif defined(LLVM_ON_UNIX)
86218885Sdim#include "Unix/ThreadLocal.inc"
87218885Sdim#elif defined( LLVM_ON_WIN32)
88218885Sdim#include "Windows/ThreadLocal.inc"
89218885Sdim#else
90226890Sdim#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 set in Support/ThreadLocal.cpp
91218885Sdim#endif
92218885Sdim#endif
93