From f17f6f06faa4c034c9b0f778b99839978c87fa4b Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Thu, 25 Jun 2009 21:58:01 +0000 Subject: [PATCH] Add a class for supporting platform independent thread-local storage. Windows people, please double-check/patch this. llvm-svn: 74209 --- llvm/include/llvm/System/ThreadLocal.h | 41 ++++++++++++++ llvm/lib/System/ThreadLocal.cpp | 77 ++++++++++++++++++++++++++ llvm/lib/System/Unix/ThreadLocal.inc | 25 +++++++++ llvm/lib/System/Win32/ThreadLocal.inc | 49 ++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 llvm/include/llvm/System/ThreadLocal.h create mode 100644 llvm/lib/System/ThreadLocal.cpp create mode 100644 llvm/lib/System/Unix/ThreadLocal.inc create mode 100644 llvm/lib/System/Win32/ThreadLocal.inc diff --git a/llvm/include/llvm/System/ThreadLocal.h b/llvm/include/llvm/System/ThreadLocal.h new file mode 100644 index 000000000000..7627be26d2e7 --- /dev/null +++ b/llvm/include/llvm/System/ThreadLocal.h @@ -0,0 +1,41 @@ +//===- llvm/System/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREAD_LOCAL_H +#define LLVM_SYSTEM_THREAD_LOCAL_H + +#include "llvm/System/Threading.h" +#include + +namespace llvm { + namespace sys { + class ThreadLocalImpl { + void* data; + public: + ThreadLocalImpl(); + virtual ~ThreadLocalImpl(); + void setInstance(void* d); + void* getInstance(); + }; + + template + class ThreadLocal : public ThreadLocalImpl { + public: + ThreadLocal() : ThreadLocalImpl() { } + T* get() { return static_cast(getInstance()); } + void set(T* d) { setInstance(d); } + }; + } +} + +#endif diff --git a/llvm/lib/System/ThreadLocal.cpp b/llvm/lib/System/ThreadLocal.cpp new file mode 100644 index 000000000000..1c0703667095 --- /dev/null +++ b/llvm/lib/System/ThreadLocal.cpp @@ -0,0 +1,77 @@ +//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/ThreadLocal.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(void* d) { data = d; } +void* ThreadLocalImpl::getInstance() { return data; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) + +#include +#include +#include + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() : data(0) { + pthread_key_t* key = new pthread_key_t; + int errorcode = pthread_key_create(key, NULL); + assert(errorcode == 0); + data = key; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_key_delete(*key); + assert(errorcode = 0); + delete key; +} + +void ThreadLocalImpl::setInstance(void* d) { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_setspecific(*key, d); + assert(errorcode == 0); +} + +void* ThreadLocalImpl::getInstance() { + pthread_key_t* key = static_cast(data); + return pthread_getspecific(*key); +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/ThreadLocal.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/ThreadLocal.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp +#endif +#endif + diff --git a/llvm/lib/System/Unix/ThreadLocal.inc b/llvm/lib/System/Unix/ThreadLocal.inc new file mode 100644 index 000000000000..6ee840d72554 --- /dev/null +++ b/llvm/lib/System/Unix/ThreadLocal.inc @@ -0,0 +1,25 @@ +//=== llvm/System/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(void* d) { data = d; } +void* ThreadLocalImpl::getInstance() { return data; } +} \ No newline at end of file diff --git a/llvm/lib/System/Win32/ThreadLocal.inc b/llvm/lib/System/Win32/ThreadLocal.inc new file mode 100644 index 000000000000..5bba8b58f901 --- /dev/null +++ b/llvm/lib/System/Win32/ThreadLocal.inc @@ -0,0 +1,49 @@ +//= llvm/System/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" +#include "llvm/System/ThreadLocal.h" + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() { + DWORD* tls = new DWORD; + *tls = TlsAlloc(); + assert(*tls != TLS_OUT_OF_INDEXES); + data = tls; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + DWORD* tls = static_cast(data); + TlsFree(*tls); + delete tls; +} + +void* ThreadLocalImpl::getInstance() { + DWORD* tls = static_cast(data); + return TlsGetValue(*tls); +} + +void ThreadLocalImpl::setInstance(void* d){ + DWORD* tls = static_cast(data); + int errorcode = TlsSetValue(*tls, d); + assert(errorcode == 0); +} + +}