[llvm] r216338 - Support: add llvm::unique_lock
Dylan Noblesmith
nobled at dreamwidth.org
Sat Aug 23 16:07:14 PDT 2014
Author: nobled
Date: Sat Aug 23 18:07:14 2014
New Revision: 216338
URL: http://llvm.org/viewvc/llvm-project?rev=216338&view=rev
Log:
Support: add llvm::unique_lock
Based on the STL class of the same name, it guards a mutex
while also allowing it to be unlocked conditionally before
destruction.
This eliminates the last naked usages of mutexes in LLVM and
clang.
It also uncovered and fixed a bug in callExternalFunction()
when compiled without USE_LIBFFI, where the mutex would never
be unlocked if the end of the function was reached.
Added:
llvm/trunk/include/llvm/Support/UniqueLock.h
Modified:
llvm/trunk/include/llvm/IR/ValueMap.h
llvm/trunk/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
llvm/trunk/lib/Support/Unix/Signals.inc
Modified: llvm/trunk/include/llvm/IR/ValueMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ValueMap.h?rev=216338&r1=216337&r2=216338&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ValueMap.h (original)
+++ llvm/trunk/include/llvm/IR/ValueMap.h Sat Aug 23 18:07:14 2014
@@ -29,6 +29,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/type_traits.h"
#include <iterator>
@@ -216,12 +217,11 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->lock();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
Copy.Map->Map.erase(Copy); // Definitely destroys *this.
- if (M)
- M->unlock();
}
void allUsesReplacedWith(Value *new_key) override {
assert(isa<KeySansPointerT>(new_key) &&
@@ -229,8 +229,9 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->lock();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
KeyT typed_new_key = cast<KeySansPointerT>(new_key);
// Can destroy *this:
@@ -245,8 +246,6 @@ public:
Copy.Map->insert(std::make_pair(typed_new_key, Target));
}
}
- if (M)
- M->unlock();
}
};
Added: llvm/trunk/include/llvm/Support/UniqueLock.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/UniqueLock.h?rev=216338&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/UniqueLock.h (added)
+++ llvm/trunk/include/llvm/Support/UniqueLock.h Sat Aug 23 18:07:14 2014
@@ -0,0 +1,67 @@
+//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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_UNIQUE_LOCK_H
+#define LLVM_SUPPORT_UNIQUE_LOCK_H
+
+#include "llvm/Support/Mutex.h"
+
+namespace llvm {
+ /// A pared-down imitation of std::unique_lock from C++11. Contrary to the
+ /// name, it's really more of a wrapper for a lock. It may or may not have
+ /// an associated mutex, which is guaranteed to be locked upon creation
+ /// and unlocked after destruction. unique_lock can also unlock the mutex
+ /// and re-lock it freely during its lifetime.
+ /// @brief Guard a section of code with a mutex.
+ template<typename MutexT>
+ class unique_lock {
+ MutexT *M;
+ bool locked;
+
+ unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION;
+ void operator=(const unique_lock &) LLVM_DELETED_FUNCTION;
+ public:
+ unique_lock() : M(nullptr), locked(false) {}
+ explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
+
+ void operator=(unique_lock &&o) {
+ if (owns_lock())
+ M->unlock();
+ M = o.M;
+ locked = o.locked;
+ o.M = nullptr;
+ o.locked = false;
+ }
+
+ ~unique_lock() { if (owns_lock()) M->unlock(); }
+
+ void lock() {
+ assert(!locked && "mutex already locked!");
+ assert(M && "no associated mutex!");
+ M->lock();
+ locked = true;
+ }
+
+ void unlock() {
+ assert(locked && "unlocking a mutex that isn't locked!");
+ assert(M && "no associated mutex!");
+ M->unlock();
+ locked = false;
+ }
+
+ bool owns_lock() { return locked; }
+ };
+}
+
+#endif // LLVM_SUPPORT_UNIQUE_LOCK_H
Modified: llvm/trunk/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp?rev=216338&r1=216337&r2=216338&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Sat Aug 23 18:07:14 2014
@@ -28,6 +28,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/UniqueLock.h"
#include <cmath>
#include <csignal>
#include <cstdio>
@@ -248,14 +249,14 @@ GenericValue Interpreter::callExternalFu
const std::vector<GenericValue> &ArgVals) {
TheInterpreter = this;
- FunctionsLock->lock();
+ unique_lock<sys::Mutex> Guard(*FunctionsLock);
// Do a lookup to see if the function is in our cache... this should just be a
// deferred annotation!
std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
: FI->second) {
- FunctionsLock->unlock();
+ Guard.unlock();
return Fn(F->getFunctionType(), ArgVals);
}
@@ -273,7 +274,7 @@ GenericValue Interpreter::callExternalFu
RawFn = RF->second;
}
- FunctionsLock->unlock();
+ Guard.unlock();
GenericValue Result;
if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
Modified: llvm/trunk/lib/Support/Unix/Signals.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Signals.inc?rev=216338&r1=216337&r2=216338&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Signals.inc (original)
+++ llvm/trunk/lib/Support/Unix/Signals.inc Sat Aug 23 18:07:14 2014
@@ -15,6 +15,7 @@
#include "Unix.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/UniqueLock.h"
#include <algorithm>
#include <string>
#include <vector>
@@ -162,25 +163,25 @@ static RETSIGTYPE SignalHandler(int Sig)
sigfillset(&SigMask);
sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
- SignalsMutex.lock();
- RemoveFilesToRemove();
+ {
+ unique_lock<SmartMutex<true>> Guard(SignalsMutex);
+ RemoveFilesToRemove();
+
+ if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) {
+ if (InterruptFunction) {
+ void (*IF)() = InterruptFunction;
+ Guard.unlock();
+ InterruptFunction = nullptr;
+ IF(); // run the interrupt function.
+ return;
+ }
- if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) {
- if (InterruptFunction) {
- void (*IF)() = InterruptFunction;
- SignalsMutex.unlock();
- InterruptFunction = nullptr;
- IF(); // run the interrupt function.
+ Guard.unlock();
+ raise(Sig); // Execute the default handler.
return;
- }
-
- SignalsMutex.unlock();
- raise(Sig); // Execute the default handler.
- return;
+ }
}
- SignalsMutex.unlock();
-
// Otherwise if it is a fault (like SEGV) run any handler.
for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i)
CallBacksToRun[i].first(CallBacksToRun[i].second);
More information about the llvm-commits
mailing list