153ca1f3190680f3e86aebe0f72f7918d63f71e0dCharles Davis//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// 2b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// 3b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// The LLVM Compiler Infrastructure 4b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// 57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source 67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details. 7b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// 8b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//===----------------------------------------------------------------------===// 9b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// 10b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// This file declares the llvm::sys::Mutex class. 11b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer// 12b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer//===----------------------------------------------------------------------===// 13b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 14674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_SUPPORT_MUTEX_H 15674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_SUPPORT_MUTEX_H 16b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 17f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper#include "llvm/Support/Compiler.h" 181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h" 19cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson#include <cassert> 20b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson 21b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencernamespace llvm 22b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer{ 23b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer namespace sys 24b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer { 25b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Platform agnostic Mutex class. 26b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson class MutexImpl 27b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer { 28b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @name Constructors 29b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @{ 30b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer public: 31b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 32b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// Initializes the lock but doesn't acquire it. if \p recursive is set 33b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// to false, the lock will not be recursive which makes it cheaper but 34b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// also more likely to deadlock (same thread can't acquire more than 35b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// once). 36b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Default Constructor. 37b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson explicit MutexImpl(bool recursive = true); 38b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 39b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// Releases and removes the lock 40b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Destructor 41b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson ~MutexImpl(); 42b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 43b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @} 44b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @name Methods 45b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @{ 46b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer public: 47b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 48b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// Attempts to unconditionally acquire the lock. If the lock is held by 49b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// another thread, this method will wait until it can acquire the lock. 50b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @returns false if any kind of error occurs, true otherwise. 51b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Unconditionally acquire the lock. 52b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer bool acquire(); 53b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 54b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// Attempts to release the lock. If the lock is held by the current 55b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// thread, the lock is released allowing other threads to acquire the 569eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen /// lock. 57b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @returns false if any kind of error occurs, true otherwise. 58b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Unconditionally release the lock. 59e98fc32b0d80663aff215e328bcd297b3141b565Dan Gohman bool release(); 60b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 61b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// Attempts to acquire the lock without blocking. If the lock is not 62b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// available, this function returns false quickly (without blocking). If 63b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// the lock is available, it is acquired. 64b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @returns false if any kind of error occurs or the lock is not 65b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// available, true otherwise. 66b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @brief Try to acquire the lock. 67b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer bool tryacquire(); 689eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen 69b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer //@} 70b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @name Platform Dependent Data 71b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @{ 72b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer private: 736d2352249af8853c8307a7cf679017b32d27958cJeff Cohen void* data_; ///< We don't know what the data will be 74b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 75b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @} 76b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @name Do Not Implement 77b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @{ 789eb59ec548b861d6ede05b4e6dc22aabf645e665Jeff Cohen private: 79f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; 80f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; 81b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer /// @} 82b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer }; 831f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 841f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 851f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer /// SmartMutex - A mutex with a compile time constant parameter that 86b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson /// indicates whether this mutex should become a no-op when we're not 87b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson /// running in multithreaded mode. 88b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson template<bool mt_only> 89f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson class SmartMutex : public MutexImpl { 90cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson unsigned acquired; 91cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson bool recursive; 92b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson public: 93cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson explicit SmartMutex(bool rec = true) : 94cc40f077b018e62e2e6f5dc279e3be84779569ceOwen Anderson MutexImpl(rec), acquired(0), recursive(rec) { } 951f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 96b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson bool acquire() { 97740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands if (!mt_only || llvm_is_multithreaded()) { 98f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson return MutexImpl::acquire(); 99740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else { 100740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // Single-threaded debugging code. This would be racy in 101740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // multithreaded mode, but provides not sanity checks in single 102740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // threaded mode. 103740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands assert((recursive || acquired == 0) && "Lock already acquired!!"); 104740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands ++acquired; 105740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands return true; 106740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } 107b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson } 108b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson 109b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson bool release() { 110740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands if (!mt_only || llvm_is_multithreaded()) { 111f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson return MutexImpl::release(); 112740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else { 113740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // Single-threaded debugging code. This would be racy in 114740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // multithreaded mode, but provides not sanity checks in single 115740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands // threaded mode. 116740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands assert(((recursive && acquired) || (acquired == 1)) && 117740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands "Lock not acquired before release!"); 118740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands --acquired; 119740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands return true; 120740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } 121b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson } 122b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson 123b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson bool tryacquire() { 124f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson if (!mt_only || llvm_is_multithreaded()) 125f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson return MutexImpl::tryacquire(); 126740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands else return true; 127b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson } 1281f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 129b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson private: 130f0eeb9b7f580a3e92c0a740893b7956801eafd52Owen Anderson SmartMutex(const SmartMutex<mt_only> & original); 131b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson void operator=(const SmartMutex<mt_only> &); 132b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson }; 1331f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 134b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson /// Mutex - A standard, always enforced mutex. 135b849a4dd4bee9ad17e295691087ce09e8d77d685Owen Anderson typedef SmartMutex<false> Mutex; 1361f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 1373c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson template<bool mt_only> 1383c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson class SmartScopedLock { 139a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson SmartMutex<mt_only>& mtx; 1401f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 1413c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson public: 142a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 143a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson mtx.acquire(); 1443c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson } 1451f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 1463c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson ~SmartScopedLock() { 147a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson mtx.release(); 1483c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson } 1493c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson }; 1501f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 1513c8031df6d555ab6dc6b629273fd8244b801e4d6Owen Anderson typedef SmartScopedLock<false> ScopedLock; 152b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer } 153b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer} 154b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer 155b2164e5cb5086f0595e96fdbb5ffc614dea9c441Reid Spencer#endif 156