diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2005-07-12 15:51:55 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2005-07-12 15:51:55 +0000 |
commit | ee448630bdf7eb6037fe2c50518d32010c433ca3 (patch) | |
tree | f8ecc527ec9e16ba1b610b08cbb35e2e05e5ebef /include/llvm | |
parent | b2164e5cb5086f0595e96fdbb5ffc614dea9c441 (diff) |
For PR540:
This patch completes the changes for making lli thread-safe. Here's the list
of changes:
* The Support/ThreadSupport* files were removed and replaced with the
MutexGuard.h file since all ThreadSupport* declared was a Mutex Guard.
The implementation of MutexGuard.h is now based on sys::Mutex which hides
its implementation and makes it unnecessary to have the -NoSupport.h and
-PThreads.h versions of ThreadSupport.
* All places in ExecutionEngine that previously referred to "Mutex" now
refer to sys::Mutex
* All places in ExecutionEngine that previously referred to "MutexLocker"
now refer to MutexGuard (this is frivolous but I believe the technically
correct name for such a class is "Guard" not a "Locker").
These changes passed all of llvm-test. All we need now are some test cases
that actually use multiple threads.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22404 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm')
-rw-r--r-- | include/llvm/ExecutionEngine/ExecutionEngine.h | 60 | ||||
-rw-r--r-- | include/llvm/Support/MutexGuard.h | 47 | ||||
-rw-r--r-- | include/llvm/Support/ThreadSupport-NoSupport.h | 34 | ||||
-rw-r--r-- | include/llvm/Support/ThreadSupport-PThreads.h | 65 | ||||
-rw-r--r-- | include/llvm/Support/ThreadSupport.h.in | 42 |
5 files changed, 68 insertions, 180 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 13bc9ccc13..301b6d6eeb 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -19,6 +19,7 @@ #include <map> #include <cassert> #include <string> +#include "llvm/Support/MutexGuard.h" namespace llvm { @@ -33,10 +34,9 @@ class TargetData; class Type; class IntrinsicLowering; -class ExecutionEngine { - Module &CurMod; - const TargetData *TD; +class ExecutionEngineState { +private: /// GlobalAddressMap - A mapping between LLVM global values and their /// actualized version... std::map<const GlobalValue*, void *> GlobalAddressMap; @@ -46,6 +46,24 @@ class ExecutionEngine { /// at the address. This map is not computed unless getGlobalValueAtAddress /// is called at some point. std::map<void *, const GlobalValue*> GlobalAddressReverseMap; + +public: + std::map<const GlobalValue*, void *>& getGlobalAddressMap(const MutexGuard& locked) { + return GlobalAddressMap; + } + + std::map<void *, const GlobalValue*>& getGlobalAddressReverseMap(const MutexGuard& locked) { + return GlobalAddressReverseMap; + } +}; + + +class ExecutionEngine { + Module &CurMod; + const TargetData *TD; + + ExecutionEngineState state; + protected: ModuleProvider *MP; @@ -54,6 +72,10 @@ protected: } public: + /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and JITEmitter classes. + /// It must be held while changing the internal state of any of those classes. + sys::Mutex lock; // Used to make this class and subclasses thread-safe + ExecutionEngine(ModuleProvider *P); ExecutionEngine(Module *M); virtual ~ExecutionEngine(); @@ -81,13 +103,15 @@ public: void addGlobalMapping(const GlobalValue *GV, void *Addr) { - void *&CurVal = GlobalAddressMap[GV]; + MutexGuard locked(lock); + + void *&CurVal = state.getGlobalAddressMap(locked)[GV]; assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!"); CurVal = Addr; // If we are using the reverse mapping, add it too - if (!GlobalAddressReverseMap.empty()) { - const GlobalValue *&V = GlobalAddressReverseMap[Addr]; + if (!state.getGlobalAddressReverseMap(locked).empty()) { + const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr]; assert((V == 0 || GV == 0) && "GlobalMapping already established!"); V = GV; } @@ -96,21 +120,25 @@ public: /// clearAllGlobalMappings - Clear all global mappings and start over again /// use in dynamic compilation scenarios when you want to move globals void clearAllGlobalMappings() { - GlobalAddressMap.clear(); - GlobalAddressReverseMap.clear(); + MutexGuard locked(lock); + + state.getGlobalAddressMap(locked).clear(); + state.getGlobalAddressReverseMap(locked).clear(); } /// updateGlobalMapping - Replace an existing mapping for GV with a new /// address. This updates both maps as required. void updateGlobalMapping(const GlobalValue *GV, void *Addr) { - void *&CurVal = GlobalAddressMap[GV]; - if (CurVal && !GlobalAddressReverseMap.empty()) - GlobalAddressReverseMap.erase(CurVal); + MutexGuard locked(lock); + + void *&CurVal = state.getGlobalAddressMap(locked)[GV]; + if (CurVal && !state.getGlobalAddressReverseMap(locked).empty()) + state.getGlobalAddressReverseMap(locked).erase(CurVal); CurVal = Addr; // If we are using the reverse mapping, add it too - if (!GlobalAddressReverseMap.empty()) { - const GlobalValue *&V = GlobalAddressReverseMap[Addr]; + if (!state.getGlobalAddressReverseMap(locked).empty()) { + const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr]; assert((V == 0 || GV == 0) && "GlobalMapping already established!"); V = GV; } @@ -120,8 +148,10 @@ public: /// global value if it is available, otherwise it returns null. /// void *getPointerToGlobalIfAvailable(const GlobalValue *GV) { - std::map<const GlobalValue*, void*>::iterator I = GlobalAddressMap.find(GV); - return I != GlobalAddressMap.end() ? I->second : 0; + MutexGuard locked(lock); + + std::map<const GlobalValue*, void*>::iterator I = state.getGlobalAddressMap(locked).find(GV); + return I != state.getGlobalAddressMap(locked).end() ? I->second : 0; } /// getPointerToGlobal - This returns the address of the specified global diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index bed1a9cec7..24bbbe1bb3 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -1,4 +1,4 @@ -//===-- Support/ThreadSupport.h - Generic threading support -----*- C++ -*-===// +//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,36 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file defines platform-agnostic interfaces that can be used to write -// multi-threaded programs. Autoconf is used to chose the correct -// implementation of these interfaces, or default to a non-thread-capable system -// if no matching system support is available. +// This file defines a guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_THREADSUPPORT_H -#define LLVM_SUPPORT_THREADSUPPORT_H +#ifndef LLVM_SUPPORT_MUTEXGUARD_H +#define LLVM_SUPPORT_MUTEXGUARD_H -#undef HAVE_PTHREAD_MUTEX_LOCK - -#ifdef HAVE_PTHREAD_MUTEX_LOCK -#include "llvm/Support/ThreadSupport-PThreads.h" -#else -#include "llvm/Support/ThreadSupport-NoSupport.h" -#endif // If no system support is available +#include <llvm/System/Mutex.h> namespace llvm { - /// MutexLocker - Instances of this class acquire a given Lock when - /// constructed and hold that lock until destruction. - /// - class MutexLocker { - Mutex &M; - MutexLocker(const MutexLocker &); // DO NOT IMPLEMENT - void operator=(const MutexLocker &); // DO NOT IMPLEMENT + /// Instances of this class acquire a given Mutex Lock when constructed and + /// hold that lock until destruction. The intention is to instantiate one of + /// these on the stack at the top of some scope to be assured that C++ + /// destruction of the object will always release the Mutex and thus avoid + /// a host of nasty multi-threading problems in the face of exceptions, etc. + /// @brief Guard a section of code with a Mutex. + class MutexGuard { + sys::Mutex &M; + MutexGuard(const MutexGuard &); // DO NOT IMPLEMENT + void operator=(const MutexGuard &); // DO NOT IMPLEMENT public: - MutexLocker(Mutex &m) : M(m) { M.acquire(); } - ~MutexLocker() { M.release(); } + MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } + ~MutexGuard() { M.release(); } + /// holds - Returns true if this locker instance holds the specified lock. + /// This is mostly used in assertions to validate that the correct mutex + /// is held. + bool holds(const sys::Mutex& lock) const { return &M == &lock; } }; } -#endif // SUPPORT_THREADSUPPORT_H +#endif // LLVM_SUPPORT_MUTEXGUARD_H diff --git a/include/llvm/Support/ThreadSupport-NoSupport.h b/include/llvm/Support/ThreadSupport-NoSupport.h deleted file mode 100644 index 058f82b41f..0000000000 --- a/include/llvm/Support/ThreadSupport-NoSupport.h +++ /dev/null @@ -1,34 +0,0 @@ -//===-- llvm/Support/ThreadSupport-NoSupport.h - Generic Impl ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a generic ThreadSupport implementation used when there is -// no supported threading mechanism on the current system. Users should never -// #include this file directly! -// -//===----------------------------------------------------------------------===// - -// Users should never #include this file directly! As such, no include guards -// are needed. - -#ifndef LLVM_SUPPORT_THREADSUPPORT_H -#error "Code should not #include Support/ThreadSupport-NoSupport.h directly!" -#endif - -namespace llvm { - /// Mutex - This class allows user code to protect variables shared between - /// threads. It implements a "recursive" mutex, to simplify user code. - /// - /// Since there is no platform support for _creating threads_, the non-thread - /// implementation of this class is a noop. - /// - struct Mutex { - void acquire () {} - void release () {} - }; -} diff --git a/include/llvm/Support/ThreadSupport-PThreads.h b/include/llvm/Support/ThreadSupport-PThreads.h deleted file mode 100644 index 84c6fac588..0000000000 --- a/include/llvm/Support/ThreadSupport-PThreads.h +++ /dev/null @@ -1,65 +0,0 @@ -//===-- llvm/Support/ThreadSupport-PThreads.h - PThreads support *- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines pthreads implementations of the generic threading -// mechanisms. Users should never #include this file directly! -// -//===----------------------------------------------------------------------===// - -// Users should never #include this file directly! As such, no include guards -// are needed. - -#ifndef LLVM_SUPPORT_THREADSUPPORT_H -#error "Code should not #include Support/ThreadSupport/PThreads.h directly!" -#endif - -#include <pthread.h> - -namespace llvm { - - /// Mutex - This class allows user code to protect variables shared between - /// threads. It implements a "recursive" mutex, to simplify user code. - /// - class Mutex { - pthread_mutex_t mutex; - Mutex(const Mutex &); // DO NOT IMPLEMENT - void operator=(const Mutex &); // DO NOT IMPLEMENT - public: - Mutex() { - // Initialize the mutex as a recursive mutex - pthread_mutexattr_t Attr; - int errorcode = pthread_mutexattr_init(&Attr); - assert(errorcode == 0); - - errorcode = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); - assert(errorcode == 0); - - errorcode = pthread_mutex_init(&mutex, &Attr); - assert(errorcode == 0); - - errorcode = pthread_mutexattr_destroy(&Attr); - assert(errorcode == 0); - } - - ~Mutex() { - int errorcode = pthread_mutex_destroy(&mutex); - assert(errorcode == 0); - } - - void acquire () { - int errorcode = pthread_mutex_lock(&mutex); - assert(errorcode == 0); - } - - void release () { - int errorcode = pthread_mutex_unlock(&mutex); - assert(errorcode == 0); - } - }; -} // end namespace llvm diff --git a/include/llvm/Support/ThreadSupport.h.in b/include/llvm/Support/ThreadSupport.h.in deleted file mode 100644 index bed1a9cec7..0000000000 --- a/include/llvm/Support/ThreadSupport.h.in +++ /dev/null @@ -1,42 +0,0 @@ -//===-- Support/ThreadSupport.h - Generic threading support -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines platform-agnostic interfaces that can be used to write -// multi-threaded programs. Autoconf is used to chose the correct -// implementation of these interfaces, or default to a non-thread-capable system -// if no matching system support is available. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_THREADSUPPORT_H -#define LLVM_SUPPORT_THREADSUPPORT_H - -#undef HAVE_PTHREAD_MUTEX_LOCK - -#ifdef HAVE_PTHREAD_MUTEX_LOCK -#include "llvm/Support/ThreadSupport-PThreads.h" -#else -#include "llvm/Support/ThreadSupport-NoSupport.h" -#endif // If no system support is available - -namespace llvm { - /// MutexLocker - Instances of this class acquire a given Lock when - /// constructed and hold that lock until destruction. - /// - class MutexLocker { - Mutex &M; - MutexLocker(const MutexLocker &); // DO NOT IMPLEMENT - void operator=(const MutexLocker &); // DO NOT IMPLEMENT - public: - MutexLocker(Mutex &m) : M(m) { M.acquire(); } - ~MutexLocker() { M.release(); } - }; -} - -#endif // SUPPORT_THREADSUPPORT_H |