00001
00031 #ifndef GALOIS_RUNTIME_LL_SIMPLE_LOCK_H
00032 #define GALOIS_RUNTIME_LL_SIMPLE_LOCK_H
00033
00034 #include "Galois/config.h"
00035 #include "Galois/Runtime/ll/CompilerSpecific.h"
00036
00037 #include <cassert>
00038 #include GALOIS_CXX11_STD_HEADER(atomic)
00039
00040 namespace Galois {
00041 namespace Runtime {
00042 namespace LL {
00043
00047
00048 template<bool isALock>
00049 class SimpleLock;
00050
00051 template<>
00052 class SimpleLock<true> {
00053 mutable std::atomic<int> _lock;
00054 GALOIS_ATTRIBUTE_NOINLINE
00055 void slow_lock() const {
00056 int oldval = 0;
00057 do {
00058 while (_lock.load(std::memory_order_acquire) != 0) {
00059 asmPause();
00060 }
00061 oldval = 0;
00062 } while (!_lock.compare_exchange_weak(oldval, 1, std::memory_order_acq_rel, std::memory_order_relaxed));
00063 assert(is_locked());
00064 }
00065
00066 public:
00067 SimpleLock() : _lock(0) { }
00068
00069 SimpleLock(const SimpleLock& p) :_lock(p._lock.load(std::memory_order_relaxed)) {}
00070
00071 SimpleLock& operator= (const SimpleLock& p) {
00072 if (&p == this) return *this;
00073
00074 _lock.store(p._lock.load(std::memory_order_relaxed), std::memory_order_relaxed);
00075 return *this;
00076 }
00077
00078
00079 inline void lock() const {
00080 int oldval = 0;
00081 if (_lock.load(std::memory_order_relaxed))
00082 goto slow_path;
00083 if (!_lock.compare_exchange_weak(oldval, 1, std::memory_order_acq_rel, std::memory_order_relaxed))
00084 goto slow_path;
00085 assert(is_locked());
00086 return;
00087 slow_path:
00088 slow_lock();
00089 }
00090
00091 inline void unlock() const {
00092 assert(is_locked());
00093
00094 _lock.store(0, std::memory_order_release);
00095
00096 }
00097
00098 inline bool try_lock() const {
00099 int oldval = 0;
00100 if (_lock.load(std::memory_order_acquire))
00101 return false;
00102 if (!_lock.compare_exchange_weak(oldval, 1, std::memory_order_acq_rel))
00103 return false;
00104 assert(is_locked());
00105 return true;
00106 }
00107
00108 inline bool is_locked() const {
00109 return _lock.load(std::memory_order_acquire) & 1;
00110 }
00111 };
00112
00113 template<>
00114 class SimpleLock<false> {
00115 public:
00116 inline void lock() const {}
00117 inline void unlock() const {}
00118 inline bool try_lock() const { return true; }
00119 inline bool is_locked() const { return false; }
00120 };
00121
00122
00123 void LockPairOrdered(SimpleLock<true>& L1, SimpleLock<true>& L2);
00124 bool TryLockPairOrdered(SimpleLock<true>& L1, SimpleLock<true>& L2);
00125 void UnLockPairOrdered(SimpleLock<true>& L1, SimpleLock<true>& L2);
00126 void LockPairOrdered(SimpleLock<false>& L1, SimpleLock<false>& L2);
00127 bool TryLockPairOrdered(SimpleLock<false>& L1, SimpleLock<false>& L2);
00128 void UnLockPairOrdered(SimpleLock<false>& L1, SimpleLock<false>& L2);
00129
00130 }
00131 }
00132 }
00133
00134 #endif