00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _SIMPLE_LOCK_H
00021 #define _SIMPLE_LOCK_H
00022
00023 #include <stdint.h>
00024 #include <cassert>
00025
00026 namespace GaloisRuntime {
00027
00028 template<typename T, bool isALock>
00029 class SimpleLock;
00030
00031 template<typename T>
00032 class SimpleLock<T, true> {
00033 volatile mutable T _lock;
00034 public:
00035 SimpleLock() : _lock(0) {
00036 }
00037
00038 inline void lock(T val) const {
00039 do {
00040 while (_lock != 0) {
00041 #if defined(__i386__) || defined(__amd64__)
00042 asm volatile ( "pause");
00043 #endif
00044 }
00045 if (try_lock(val))
00046 break;
00047 } while (true);
00048 }
00049
00050 inline void lock() const {
00051 do {
00052 while (_lock != 0) {
00053 #if defined(__i386__) || defined(__amd64__)
00054 asm volatile ( "pause");
00055 #endif
00056 }
00057 if (try_lock())
00058 break;
00059 } while (true);
00060 }
00061
00062 inline void unlock() const {
00063 assert(_lock);
00064 _lock = 0;
00065 }
00066
00067 inline bool try_lock(T val) const {
00068 if (_lock != 0)
00069 return false;
00070 return __sync_bool_compare_and_swap(&_lock, 0, val);
00071 }
00072
00073 inline bool try_lock() const {
00074 if (_lock != 0)
00075 return false;
00076 T oldval = __sync_fetch_and_or(&_lock, 1);
00077 return !(oldval & 1);
00078 }
00079
00080 inline T getValue() const {
00081 return _lock;
00082 }
00083 };
00084
00085 template<typename T>
00086 class SimpleLock<T, false> {
00087 public:
00088 inline void lock(T val = 0) const {}
00089 inline void unlock() const {}
00090 inline bool try_lock(T val = 1) const { return true; }
00091 inline T getValue() const { return 0; }
00092 };
00093
00094
00095
00096 template<typename T, bool isALock>
00097 class PtrLock;
00098
00099 template<typename T>
00100 class PtrLock<T, true> {
00101 volatile uintptr_t _lock;
00102 public:
00103 PtrLock() : _lock(0) {}
00104 explicit PtrLock(T val) : _lock(val) {}
00105
00106 inline void lock() {
00107 do {
00108 while ((_lock & 1) != 0) {
00109 #if defined(__i386__) || defined(__amd64__)
00110 asm volatile ( "pause");
00111 #endif
00112 }
00113 if (try_lock())
00114 break;
00115 } while (true);
00116 }
00117
00118 inline void unlock() {
00119 assert(_lock & 1);
00120 _lock = _lock & ~1;
00121 }
00122
00123 inline void unlock_and_clear() {
00124 assert(_lock & 1);
00125 _lock = 0;
00126 }
00127
00128 inline void unlock_and_set(T val) {
00129 assert(_lock & 1);
00130 assert(!((uintptr_t)val & 1));
00131 _lock = (uintptr_t)val;
00132 }
00133
00134 inline T getValue() const {
00135 return (T)(_lock & ~1);
00136 }
00137
00138 inline void setValue(T val) {
00139 _lock = ((uintptr_t)val) | (_lock & 1);
00140 }
00141
00142 inline bool try_lock() {
00143 uintptr_t oldval = _lock;
00144 if ((oldval & 1) != 0)
00145 return false;
00146 oldval = __sync_fetch_and_or(&_lock, 1);
00147 return !(oldval & 1);
00148 }
00149
00150
00151
00152 inline bool CAS(T oldval, T newval) {
00153 assert(!((uintptr_t)oldval & 1) && !((uintptr_t)newval & 1));
00154 return __sync_bool_compare_and_swap(&_lock, oldval, newval);
00155 }
00156 };
00157
00158 template<typename T>
00159 class PtrLock<T, false> {
00160 T _lock;
00161 public:
00162 PtrLock() : _lock(0) {}
00163 explicit PtrLock(T val) : _lock(val) {}
00164
00165 inline void lock() {}
00166 inline void unlock() {}
00167 inline void unlock_and_clear() { _lock = 0; }
00168 inline void unlock_and_set(T val) { _lock = val; }
00169 inline T getValue() const { return _lock; }
00170 inline void setValue(T val) { _lock = val; }
00171 inline bool try_lock() { return true; }
00172 inline bool CAS(T oldval, T newval) {
00173 if (_lock == oldval) {
00174 _lock = newval;
00175 return true;
00176 }
00177 return false;
00178 }
00179 };
00180
00181 }
00182
00183 #endif