diff options
Diffstat (limited to 'lib/System')
-rw-r--r-- | lib/System/Atomic.cpp | 28 | ||||
-rw-r--r-- | lib/System/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/System/Mutex.cpp | 20 | ||||
-rw-r--r-- | lib/System/RWMutex.cpp | 175 | ||||
-rw-r--r-- | lib/System/Threading.cpp | 63 | ||||
-rw-r--r-- | lib/System/Unix/Mutex.inc | 10 | ||||
-rw-r--r-- | lib/System/Unix/Path.inc | 8 | ||||
-rw-r--r-- | lib/System/Unix/RWMutex.inc | 43 | ||||
-rw-r--r-- | lib/System/Unix/Unix.h | 9 | ||||
-rw-r--r-- | lib/System/Win32/Mutex.inc | 10 | ||||
-rw-r--r-- | lib/System/Win32/Path.inc | 18 | ||||
-rw-r--r-- | lib/System/Win32/RWMutex.inc | 58 |
12 files changed, 422 insertions, 22 deletions
diff --git a/lib/System/Atomic.cpp b/lib/System/Atomic.cpp index 2827d88965945..416f981df8273 100644 --- a/lib/System/Atomic.cpp +++ b/lib/System/Atomic.cpp @@ -51,3 +51,31 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, # error No compare-and-swap implementation for your platform! #endif } + +sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + ++(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_add_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedIncrement(ptr); +#else +# error No atomic increment implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + --(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_sub_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedDecrement(ptr); +#else +# error No atomic decrement implementation for your platform! +#endif +} + + diff --git a/lib/System/CMakeLists.txt b/lib/System/CMakeLists.txt index 5415dd6e300c0..a5a56e832dc29 100644 --- a/lib/System/CMakeLists.txt +++ b/lib/System/CMakeLists.txt @@ -10,7 +10,9 @@ add_llvm_library(LLVMSystem Path.cpp Process.cpp Program.cpp + RWMutex.cpp Signals.cpp + Threading.cpp TimeValue.cpp ) diff --git a/lib/System/Mutex.cpp b/lib/System/Mutex.cpp index d95c25b39eef8..a5e9920ae3f03 100644 --- a/lib/System/Mutex.cpp +++ b/lib/System/Mutex.cpp @@ -23,11 +23,11 @@ // Define all methods as no-ops if threading is explicitly disabled namespace llvm { using namespace sys; -Mutex::Mutex( bool recursive) { } -Mutex::~Mutex() { } -bool Mutex::acquire() { return true; } -bool Mutex::release() { return true; } -bool Mutex::tryacquire() { return true; } +MutexImpl::MutexImpl( bool recursive) { } +MutexImpl::~MutexImpl() { } +bool MutexImpl::acquire() { return true; } +bool MutexImpl::release() { return true; } +bool MutexImpl::tryacquire() { return true; } } #else @@ -55,7 +55,7 @@ using namespace sys; static const bool pthread_enabled = true; // Construct a Mutex using pthread calls -Mutex::Mutex( bool recursive) +MutexImpl::MutexImpl( bool recursive) : data_(0) { if (pthread_enabled) @@ -94,7 +94,7 @@ Mutex::Mutex( bool recursive) } // Destruct a Mutex -Mutex::~Mutex() +MutexImpl::~MutexImpl() { if (pthread_enabled) { @@ -106,7 +106,7 @@ Mutex::~Mutex() } bool -Mutex::acquire() +MutexImpl::acquire() { if (pthread_enabled) { @@ -120,7 +120,7 @@ Mutex::acquire() } bool -Mutex::release() +MutexImpl::release() { if (pthread_enabled) { @@ -134,7 +134,7 @@ Mutex::release() } bool -Mutex::tryacquire() +MutexImpl::tryacquire() { if (pthread_enabled) { diff --git a/lib/System/RWMutex.cpp b/lib/System/RWMutex.cpp new file mode 100644 index 0000000000000..15d98cb8f418b --- /dev/null +++ b/lib/System/RWMutex.cpp @@ -0,0 +1,175 @@ +//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- 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::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/RWMutex.h" +#include <cstring> + +//===----------------------------------------------------------------------===// +//=== 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; +RWMutexImpl::RWMutexImpl() { } +RWMutexImpl::~RWMutexImpl() { } +bool RWMutexImpl::reader_acquire() { return true; } +bool RWMutexImpl::reader_release() { return true; } +bool RWMutexImpl::writer_acquire() { return true; } +bool RWMutexImpl::writer_release() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) + +#include <cassert> +#include <pthread.h> +#include <stdlib.h> + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_rwlock_init does have an address, then rwlock support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_rwlock_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a RWMutex using pthread calls +RWMutexImpl::RWMutexImpl() + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_rwlock data structures + pthread_rwlock_t* rwlock = + static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t))); + +#ifdef __APPLE__ + // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. + bzero(rwlock, sizeof(pthread_rwlock_t)); +#endif + + pthread_rwlockattr_t attr; + + // Initialize the rwlock attributes + int errorcode = pthread_rwlockattr_init(&attr); + assert(errorcode == 0); + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) + // Make it a process local rwlock + errorcode = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); +#endif + + // Initialize the rwlock + errorcode = pthread_rwlock_init(rwlock, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_rwlockattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = rwlock; + } +} + +// Destruct a RWMutex +RWMutexImpl::~RWMutexImpl() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + pthread_rwlock_destroy(rwlock); + free(rwlock); + } +} + +bool +RWMutexImpl::reader_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_rdlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutexImpl::reader_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutexImpl::writer_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_wrlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutexImpl::writer_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } + return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/RWMutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/RWMutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif diff --git a/lib/System/Threading.cpp b/lib/System/Threading.cpp new file mode 100644 index 0000000000000..a2d7f82715d94 --- /dev/null +++ b/lib/System/Threading.cpp @@ -0,0 +1,63 @@ +//===-- llvm/System/Threading.cpp- Control multithreading mode --*- 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 llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#include "llvm/System/Threading.h" +#include "llvm/System/Atomic.h" +#include "llvm/System/Mutex.h" +#include <cassert> + +using namespace llvm; + +static bool multithreaded_mode = false; + +static sys::Mutex* global_lock = 0; + +bool llvm::llvm_start_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(!multithreaded_mode && "Already multithreaded!"); + multithreaded_mode = true; + global_lock = new sys::Mutex(true); + + // We fence here to ensure that all initialization is complete BEFORE we + // return from llvm_start_multithreaded(). + sys::MemoryFence(); + return true; +#else + return false; +#endif +} + +void llvm::llvm_stop_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(multithreaded_mode && "Not currently multithreaded!"); + + // We fence here to insure that all threaded operations are complete BEFORE we + // return from llvm_stop_multithreaded(). + sys::MemoryFence(); + + multithreaded_mode = false; + delete global_lock; +#endif +} + +bool llvm::llvm_is_multithreaded() { + return multithreaded_mode; +} + +void llvm::llvm_acquire_global_lock() { + if (multithreaded_mode) global_lock->acquire(); +} + +void llvm::llvm_release_global_lock() { + if (multithreaded_mode) global_lock->release(); +} diff --git a/lib/System/Unix/Mutex.inc b/lib/System/Unix/Mutex.inc index 4a015a676fc74..10e7ecb75a5f7 100644 --- a/lib/System/Unix/Mutex.inc +++ b/lib/System/Unix/Mutex.inc @@ -20,28 +20,28 @@ namespace llvm { using namespace sys; -Mutex::Mutex( bool recursive) +MutexImpl::MutexImpl( bool recursive) { } -Mutex::~Mutex() +MutexImpl::~MutexImpl() { } bool -Mutex::acquire() +MutexImpl::MutexImpl() { return true; } bool -Mutex::release() +MutexImpl::release() { return true; } bool -Mutex::tryacquire( void ) +MutexImpl::tryacquire( void ) { return true; } diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc index d5edee1b03b3e..1f73571cf140b 100644 --- a/lib/System/Unix/Path.inc +++ b/lib/System/Unix/Path.inc @@ -104,6 +104,14 @@ Path::isValid() const { } bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + if (NameLen == 0) + return false; + return NameStart[0] == '/'; +} + +bool Path::isAbsolute() const { if (path.empty()) return false; diff --git a/lib/System/Unix/RWMutex.inc b/lib/System/Unix/RWMutex.inc new file mode 100644 index 0000000000000..e83d41ef4cfeb --- /dev/null +++ b/lib/System/Unix/RWMutex.inc @@ -0,0 +1,43 @@ +//= llvm/System/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =// +// +// 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) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { + +using namespace sys; + +RWMutexImpl::RWMutexImpl() { } + +RWMutexImpl::~RWMutexImpl() { } + +bool RWMutexImpl::reader_acquire() { + return true; +} + +bool RWMutexImpl::reader_release() { + return true; +} + +bool RWMutexImpl::writer_acquire() { + return true; +} + +bool RWMutexImpl::writer_release() { + return true; +} + +} diff --git a/lib/System/Unix/Unix.h b/lib/System/Unix/Unix.h index 452226f4f79ab..c2c06dd114e50 100644 --- a/lib/System/Unix/Unix.h +++ b/lib/System/Unix/Unix.h @@ -79,12 +79,19 @@ static inline bool MakeErrMsg( return true; char buffer[MAXPATHLEN]; buffer[0] = 0; + char* str = buffer; if (errnum == -1) errnum = errno; #ifdef HAVE_STRERROR_R // strerror_r is thread-safe. if (errnum) +# if defined(__GLIBC__) && defined(_GNU_SOURCE) + // glibc defines its own incompatible version of strerror_r + // which may not use the buffer supplied. + str = strerror_r(errnum,buffer,MAXPATHLEN-1); +# else strerror_r(errnum,buffer,MAXPATHLEN-1); +# endif #elif HAVE_STRERROR // Copy the thread un-safe result of strerror into // the buffer as fast as possible to minimize impact @@ -97,7 +104,7 @@ static inline bool MakeErrMsg( // but, oh well, just use a generic message sprintf(buffer, "Error #%d", errnum); #endif - *ErrMsg = prefix + ": " + buffer; + *ErrMsg = prefix + ": " + str; return true; } diff --git a/lib/System/Win32/Mutex.inc b/lib/System/Win32/Mutex.inc index 7c1723be73fce..75f01fefacbb0 100644 --- a/lib/System/Win32/Mutex.inc +++ b/lib/System/Win32/Mutex.inc @@ -22,13 +22,13 @@ namespace llvm { using namespace sys; -Mutex::Mutex(bool /*recursive*/) +MutexImpl::MutexImpl(bool /*recursive*/) { data_ = new CRITICAL_SECTION; InitializeCriticalSection((LPCRITICAL_SECTION)data_); } -Mutex::~Mutex() +MutexImpl::~MutexImpl() { DeleteCriticalSection((LPCRITICAL_SECTION)data_); delete (LPCRITICAL_SECTION)data_; @@ -36,21 +36,21 @@ Mutex::~Mutex() } bool -Mutex::acquire() +MutexImpl::acquire() { EnterCriticalSection((LPCRITICAL_SECTION)data_); return true; } bool -Mutex::release() +MutexImpl::release() { LeaveCriticalSection((LPCRITICAL_SECTION)data_); return true; } bool -Mutex::tryacquire() +MutexImpl::tryacquire() { return TryEnterCriticalSection((LPCRITICAL_SECTION)data_); } diff --git a/lib/System/Win32/Path.inc b/lib/System/Win32/Path.inc index fbf8f6688a57e..683c94bba44ee 100644 --- a/lib/System/Win32/Path.inc +++ b/lib/System/Win32/Path.inc @@ -125,6 +125,20 @@ Path::isValid() const { return true; } +bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + switch (NameLen) { + case 0: + return false; + case 1: + case 2: + return NameStart[0] == '/'; + default: + return NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/'); + } +} + bool Path::isAbsolute() const { switch (path.length()) { @@ -234,7 +248,9 @@ Path::GetCurrentDirectory() { /// GetMainExecutable - Return the path to the main executable, given the /// value of argv[0] from program startup. Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { - return Path(); + char pathname[MAX_PATH]; + DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH); + return ret != MAX_PATH ? Path(pathname) : Path(); } diff --git a/lib/System/Win32/RWMutex.inc b/lib/System/Win32/RWMutex.inc new file mode 100644 index 0000000000000..e2692269e3a0b --- /dev/null +++ b/lib/System/Win32/RWMutex.inc @@ -0,0 +1,58 @@ +//= llvm/System/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// +// +// 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) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Win32.h" + +// FIXME: Windows does not have reader-writer locks pre-Vista. If you want +// real reader-writer locks, you a pthreads implementation for Windows. + +namespace llvm { +using namespace sys; + +RWMutexImpl::RWMutexImpl() { + data_ = calloc(1, sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); +} + +RWMutexImpl::~RWMutexImpl() { + DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); + free(data_); +} + +bool RWMutexImpl::reader_acquire() { + EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); + return true; +} + +bool RWMutexImpl::reader_release() { + LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); + return true; +} + +bool RWMutexImpl::writer_acquire() { + EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); + return true; +} + +bool RWMutexImpl::writer_release() { + LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); + return true; +} + + +} |