00001
00025 #ifndef GALOIS_RUNTIME_CONTEXT_H
00026 #define GALOIS_RUNTIME_CONTEXT_H
00027
00028 #include "Galois/config.h"
00029 #include "Galois/MethodFlags.h"
00030 #include "Galois/Runtime/ll/PtrLock.h"
00031 #include "Galois/Runtime/ll/gio.h"
00032
00033 #include <boost/utility.hpp>
00034
00035 #include <cassert>
00036 #include <cstdlib>
00037
00038 #ifdef GALOIS_USE_LONGJMP
00039 #include <setjmp.h>
00040 #endif
00041
00042 namespace Galois {
00043 namespace Runtime {
00044
00045 enum ConflictFlag {
00046 CONFLICT = -1,
00047 NO_CONFLICT = 0,
00048 REACHED_FAILSAFE = 1,
00049 BREAK = 2
00050 };
00051
00052 enum PendingFlag {
00053 NON_DET,
00054 PENDING,
00055 COMMITTING
00056 };
00057
00059 void setPending(PendingFlag value);
00060 PendingFlag getPending ();
00061
00063 static inline void clearConflictLock() { }
00064
00065 #ifdef GALOIS_USE_LONGJMP
00066 extern __thread jmp_buf hackjmp;
00067
00072 class Releasable {
00073 Releasable* next;
00074 public:
00075 Releasable();
00076 virtual ~Releasable() { }
00077 virtual void release() = 0;
00078 void releaseAll();
00079 };
00080 void clearReleasable();
00081 #else
00082 class Releasable {
00083 public:
00084 virtual ~Releasable() { }
00085 virtual void release() = 0;
00086 };
00087 static inline void clearReleasable() { }
00088 #endif
00089
00090 class LockManagerBase;
00091
00092 #if defined(GALOIS_USE_SEQ_ONLY)
00093 class Lockable { };
00094
00095 class LockManagerBase: private boost::noncopyable {
00096 protected:
00097 enum AcquireStatus {
00098 FAIL, NEW_OWNER, ALREADY_OWNER
00099 };
00100
00101 AcquireStatus tryAcquire(Lockable* lockable) { return FAIL; }
00102 bool stealByCAS(Lockable* lockable, LockManagerBase* other) { return false; }
00103 void ownByForce(Lockable* lockable) { }
00104 void release (Lockable* lockable) {}
00105 static bool tryLock(Lockable* lockable) { return false; }
00106 static LockManagerBase* getOwner(Lockable* lockable) { return 0; }
00107
00108 };
00109
00110 class SimpleRuntimeContext: public LockManagerBase {
00111 protected:
00112 void acquire(Lockable* lockable) { }
00113 void release (Lockable* lockable) {}
00114 virtual void subAcquire(Lockable* lockable);
00115 void addToNhood(Lockable* lockable) { }
00116 static SimpleRuntimeContext* getOwner(Lockable* lockable) { return 0; }
00117
00118 public:
00119 SimpleRuntimeContext(bool child = false): LockManagerBase () { }
00120 virtual ~SimpleRuntimeContext() { }
00121 void startIteration() { }
00122
00123 unsigned cancelIteration() { return 0; }
00124 unsigned commitIteration() { return 0; }
00125 };
00126 #else
00127
00131 class Lockable {
00132 LL::PtrLock<LockManagerBase, true> owner;
00135 Lockable* next;
00136 friend class LockManagerBase;
00137 friend class SimpleRuntimeContext;
00138 public:
00139 Lockable() :next(0) {}
00140 };
00141
00142 class LockManagerBase: private boost::noncopyable {
00143 protected:
00144 enum AcquireStatus {
00145 FAIL, NEW_OWNER, ALREADY_OWNER
00146 };
00147
00148 AcquireStatus tryAcquire(Lockable* lockable);
00149
00150 inline bool stealByCAS(Lockable* lockable, LockManagerBase* other) {
00151 assert(lockable != nullptr);
00152 return lockable->owner.stealing_CAS(other, this);
00153 }
00154
00155 inline void ownByForce(Lockable* lockable) {
00156 assert(lockable != nullptr);
00157 assert(!lockable->owner.getValue());
00158 lockable->owner.setValue(this);
00159 }
00160
00161 inline void release(Lockable* lockable) {
00162 assert(lockable != nullptr);
00163 assert(getOwner(lockable) == this);
00164 lockable->owner.unlock_and_clear();
00165 }
00166
00167 inline static bool tryLock(Lockable* lockable) {
00168 assert(lockable != nullptr);
00169 return lockable->owner.try_lock();
00170 }
00171
00172 inline static LockManagerBase* getOwner(Lockable* lockable) {
00173 assert(lockable != nullptr);
00174 return lockable->owner.getValue();
00175 }
00176 };
00177
00178 class SimpleRuntimeContext: public LockManagerBase {
00180 Lockable* locks;
00181 bool customAcquire;
00182
00183 protected:
00184 friend void doAcquire(Lockable*);
00185
00186 static SimpleRuntimeContext* getOwner(Lockable* lockable) {
00187 LockManagerBase* owner = LockManagerBase::getOwner (lockable);
00188 return static_cast<SimpleRuntimeContext*>(owner);
00189 }
00190
00191 virtual void subAcquire(Lockable* lockable);
00192
00193 void addToNhood(Lockable* lockable) {
00194 assert(!lockable->next);
00195 lockable->next = locks;
00196 locks = lockable;
00197 }
00198
00199 void acquire(Lockable* lockable);
00200 void release(Lockable* lockable);
00201
00202 public:
00203 SimpleRuntimeContext(bool child = false): locks(0), customAcquire(child) { }
00204 virtual ~SimpleRuntimeContext() { }
00205
00206 void startIteration() {
00207 assert(!locks);
00208 }
00209
00210 unsigned cancelIteration();
00211 unsigned commitIteration();
00212 };
00213 #endif
00214
00216 SimpleRuntimeContext* getThreadContext();
00217
00219 void setThreadContext(SimpleRuntimeContext* n);
00220
00222 inline bool shouldLock(const Galois::MethodFlag g) {
00223 #ifdef GALOIS_USE_SEQ_ONLY
00224 return false;
00225 #else
00226
00227 switch (g & ALL) {
00228 case NONE:
00229 case SAVE_UNDO:
00230 return false;
00231 case ALL:
00232 case CHECK_CONFLICT:
00233 return true;
00234 default:
00235
00236
00237
00238 assert(false);
00239 }
00240 return false;
00241 #endif
00242 }
00243
00245 inline void doAcquire(Lockable* lockable) {
00246 SimpleRuntimeContext* ctx = getThreadContext();
00247 if (ctx)
00248 ctx->acquire(lockable);
00249 }
00250
00253 inline void acquire(Lockable* lockable, Galois::MethodFlag m) {
00254 if (shouldLock(m)) {
00255 doAcquire(lockable);
00256 }
00257 }
00258
00259 struct AlwaysLockObj {
00260 void operator()(Lockable* lockable) const {
00261 doAcquire(lockable);
00262 }
00263 };
00264
00265 struct CheckedLockObj {
00266 Galois::MethodFlag m;
00267 CheckedLockObj(Galois::MethodFlag _m) :m(_m) {}
00268 void operator()(Lockable* lockable) const {
00269 acquire(lockable, m);
00270 }
00271 };
00272
00273 void signalConflict(Lockable*);
00274
00275 void forceAbort();
00276
00277 }
00278 }
00279
00280 #endif