summaryrefslogtreecommitdiffstats
path: root/lib/System
diff options
context:
space:
mode:
Diffstat (limited to 'lib/System')
-rw-r--r--lib/System/Atomic.cpp42
-rw-r--r--lib/System/CMakeLists.txt1
-rw-r--r--lib/System/DynamicLibrary.cpp30
-rw-r--r--lib/System/ThreadLocal.cpp80
-rw-r--r--lib/System/Unix/ThreadLocal.inc25
-rw-r--r--lib/System/Win32/DynamicLibrary.inc19
-rw-r--r--lib/System/Win32/ThreadLocal.inc49
7 files changed, 215 insertions, 31 deletions
diff --git a/lib/System/Atomic.cpp b/lib/System/Atomic.cpp
index fda2708..f9b55a1 100644
--- a/lib/System/Atomic.cpp
+++ b/lib/System/Atomic.cpp
@@ -35,11 +35,11 @@ void sys::MemoryFence() {
#endif
}
-uint32_t sys::CompareAndSwap32(volatile uint32_t* ptr,
- uint32_t new_value,
- uint32_t old_value) {
+sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
+ sys::cas_flag new_value,
+ sys::cas_flag old_value) {
#if LLVM_MULTITHREADED==0
- uint32_t result = *ptr;
+ sys::cas_flag result = *ptr;
if (result == old_value)
*ptr = new_value;
return result;
@@ -52,7 +52,7 @@ uint32_t sys::CompareAndSwap32(volatile uint32_t* ptr,
#endif
}
-int32_t sys::AtomicIncrement32(volatile int32_t* ptr) {
+sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
#if LLVM_MULTITHREADED==0
++(*ptr);
return *ptr;
@@ -65,7 +65,7 @@ int32_t sys::AtomicIncrement32(volatile int32_t* ptr) {
#endif
}
-int32_t sys::AtomicDecrement32(volatile int32_t* ptr) {
+sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
#if LLVM_MULTITHREADED==0
--(*ptr);
return *ptr;
@@ -78,7 +78,7 @@ int32_t sys::AtomicDecrement32(volatile int32_t* ptr) {
#endif
}
-int32_t sys::AtomicAdd32(volatile int32_t* ptr, int32_t val) {
+sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
#if LLVM_MULTITHREADED==0
*ptr += val;
return *ptr;
@@ -91,16 +91,22 @@ int32_t sys::AtomicAdd32(volatile int32_t* ptr, int32_t val) {
#endif
}
-int64_t sys::AtomicAdd64(volatile int64_t* ptr, int64_t val) {
-#if LLVM_MULTITHREADED==0
- *ptr += val;
- return *ptr;
-#elif defined(__GNUC__)
- return __sync_add_and_fetch(ptr, val);
-#elif defined(_MSC_VER)
- return InterlockedAdd64(ptr, val);
-#else
-# error No atomic add implementation for your platform!
-#endif
+sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
+ sys::cas_flag original, result;
+ do {
+ original = *ptr;
+ result = original * val;
+ } while (sys::CompareAndSwap(ptr, result, original) != original);
+
+ return result;
}
+sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
+ sys::cas_flag original, result;
+ do {
+ original = *ptr;
+ result = original / val;
+ } while (sys::CompareAndSwap(ptr, result, original) != original);
+
+ return result;
+}
diff --git a/lib/System/CMakeLists.txt b/lib/System/CMakeLists.txt
index a5a56e8..431629a 100644
--- a/lib/System/CMakeLists.txt
+++ b/lib/System/CMakeLists.txt
@@ -14,6 +14,7 @@ add_llvm_library(LLVMSystem
Signals.cpp
Threading.cpp
TimeValue.cpp
+ ThreadLocal.cpp
)
if( BUILD_SHARED_LIBS AND NOT WIN32 )
diff --git a/lib/System/DynamicLibrary.cpp b/lib/System/DynamicLibrary.cpp
index 3bf172c..ef5c9e6 100644
--- a/lib/System/DynamicLibrary.cpp
+++ b/lib/System/DynamicLibrary.cpp
@@ -12,20 +12,22 @@
//===----------------------------------------------------------------------===//
#include "llvm/System/DynamicLibrary.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/System/RWMutex.h"
#include "llvm/Config/config.h"
#include <cstdio>
#include <cstring>
#include <map>
// Collection of symbol name/value pairs to be searched prior to any libraries.
-std::map<std::string, void *> &g_symbols() {
- static std::map<std::string, void *> symbols;
- return symbols;
-}
+static std::map<std::string, void*> symbols;
+static llvm::sys::SmartRWMutex<true> SymbolsLock;
+
void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
void *symbolValue) {
- g_symbols()[symbolName] = symbolValue;
+ llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
+ symbols[symbolName] = symbolValue;
}
// It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL
@@ -57,6 +59,7 @@ static std::vector<void *> OpenedHandles;
DynamicLibrary::DynamicLibrary() {}
DynamicLibrary::~DynamicLibrary() {
+ SmartScopedWriter<true> Writer(&SymbolsLock);
while(!OpenedHandles.empty()) {
void *H = OpenedHandles.back(); OpenedHandles.pop_back();
dlclose(H);
@@ -65,6 +68,7 @@ DynamicLibrary::~DynamicLibrary() {
bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
std::string *ErrMsg) {
+ SmartScopedWriter<true> Writer(&SymbolsLock);
void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL);
if (H == 0) {
if (ErrMsg)
@@ -77,20 +81,28 @@ bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
// check_ltdl_initialization();
-
+
// First check symbols added via AddSymbol().
- std::map<std::string, void *>::iterator I = g_symbols().find(symbolName);
- if (I != g_symbols().end())
+ SymbolsLock.reader_acquire();
+ std::map<std::string, void *>::iterator I = symbols.find(symbolName);
+ std::map<std::string, void *>::iterator E = symbols.end();
+ SymbolsLock.reader_release();
+
+ if (I != E)
return I->second;
+ SymbolsLock.writer_acquire();
// Now search the libraries.
for (std::vector<void *>::iterator I = OpenedHandles.begin(),
E = OpenedHandles.end(); I != E; ++I) {
//lt_ptr ptr = lt_dlsym(*I, symbolName);
void *ptr = dlsym(*I, symbolName);
- if (ptr)
+ if (ptr) {
+ SymbolsLock.writer_release();
return ptr;
+ }
}
+ SymbolsLock.writer_release();
#define EXPLICIT_SYMBOL(SYM) \
extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
diff --git a/lib/System/ThreadLocal.cpp b/lib/System/ThreadLocal.cpp
new file mode 100644
index 0000000..8884e79
--- /dev/null
+++ b/lib/System/ThreadLocal.cpp
@@ -0,0 +1,80 @@
+//===- 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(const void* d) { data = const_cast<void*>(d);}
+const void* ThreadLocalImpl::getInstance() { return data; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+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);
+ (void) errorcode;
+ data = key;
+}
+
+ThreadLocalImpl::~ThreadLocalImpl() {
+ pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ int errorcode = pthread_key_delete(*key);
+ assert(errorcode == 0);
+ (void) errorcode;
+ delete key;
+}
+
+void ThreadLocalImpl::setInstance(const void* d) {
+ pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ int errorcode = pthread_setspecific(*key, d);
+ assert(errorcode == 0);
+ (void) errorcode;
+}
+
+const void* ThreadLocalImpl::getInstance() {
+ pthread_key_t* key = static_cast<pthread_key_t*>(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/lib/System/Unix/ThreadLocal.inc b/lib/System/Unix/ThreadLocal.inc
new file mode 100644
index 0000000..83d554d3
--- /dev/null
+++ b/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(const void* d) { data = const_cast<void*>(d);}
+const void* ThreadLocalImpl::getInstance() { return data; }
+}
diff --git a/lib/System/Win32/DynamicLibrary.inc b/lib/System/Win32/DynamicLibrary.inc
index 1ddf6ce..aa04268 100644
--- a/lib/System/Win32/DynamicLibrary.inc
+++ b/lib/System/Win32/DynamicLibrary.inc
@@ -67,6 +67,7 @@ extern "C" {
PVOID UserContext)
#endif
{
+ llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
// Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded
// into the process.
if (stricmp(ModuleName, "msvci70") != 0 &&
@@ -89,11 +90,13 @@ extern "C" {
}
DynamicLibrary::DynamicLibrary() : handle(0) {
+ SmartScopedWriter<true> Writer(&SymbolsLock);
handle = GetModuleHandle(NULL);
OpenedHandles.push_back((HMODULE)handle);
}
DynamicLibrary::~DynamicLibrary() {
+ llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
if (handle == 0)
return;
@@ -113,8 +116,9 @@ DynamicLibrary::~DynamicLibrary() {
}
bool DynamicLibrary::LoadLibraryPermanently(const char *filename,
- std::string *ErrMsg) {
+ std::string *ErrMsg) {
if (filename) {
+ llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
HMODULE a_handle = LoadLibrary(filename);
if (a_handle == 0)
@@ -166,17 +170,24 @@ bool DynamicLibrary::LoadLibraryPermanently(const char *filename,
void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
// First check symbols added via AddSymbol().
- std::map<std::string, void *>::iterator I = g_symbols().find(symbolName);
- if (I != g_symbols().end())
+ SymbolsLock.reader_acquire();
+ std::map<std::string, void *>::iterator I = symbols.find(symbolName);
+ std::map<std::string, void *>::iterator E = symbols.end();
+ SymbolsLock.reader_release();
+ if (I != E)
return I->second;
// Now search the libraries.
+ SymbolsLock.writer_acquire();
for (std::vector<HMODULE>::iterator I = OpenedHandles.begin(),
E = OpenedHandles.end(); I != E; ++I) {
FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
- if (ptr)
+ if (ptr) {
+ SymbolsLock.writer_release();
return (void *) ptr;
+ }
}
+ SymbolsLock.writer_release();
#if defined(__MINGW32__)
{
diff --git a/lib/System/Win32/ThreadLocal.inc b/lib/System/Win32/ThreadLocal.inc
new file mode 100644
index 0000000..8ab37d9
--- /dev/null
+++ b/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<DWORD*>(data);
+ TlsFree(*tls);
+ delete tls;
+}
+
+const void* ThreadLocalImpl::getInstance() {
+ DWORD* tls = static_cast<DWORD*>(data);
+ return TlsGetValue(*tls);
+}
+
+void ThreadLocalImpl::setInstance(const void* d){
+ DWORD* tls = static_cast<DWORD*>(data);
+ int errorcode = TlsSetValue(*tls, const_cast<void*>(d));
+ assert(errorcode == 0);
+}
+
+}
OpenPOWER on IntegriCloud