Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libgalois/include/galois/runtime/Context.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_RUNTIME_CONTEXT_H
21 #define GALOIS_RUNTIME_CONTEXT_H
22 
23 #include <cassert>
24 #include <cstdlib>
25 
26 #include <boost/utility.hpp>
27 
28 #include "galois/config.h"
29 
30 #ifdef GALOIS_USE_LONGJMP_ABORT
31 #include <csetjmp>
32 #endif
33 
34 #include "galois/gIO.h"
35 #include "galois/MethodFlags.h"
37 
38 namespace galois {
39 namespace runtime {
40 
42  CONFLICT = -1,
45  BREAK = 2
46 };
47 
48 extern thread_local std::jmp_buf execFrame;
49 
50 class Lockable;
51 
52 [[noreturn]] inline void signalConflict(Lockable* = nullptr) {
53 #if defined(GALOIS_USE_LONGJMP_ABORT)
54  std::longjmp(execFrame, CONFLICT);
55  std::abort(); // shouldn't reach here after longjmp
56 #elif defined(GALOIS_USE_EXCEPTION_ABORT)
57  throw CONFLICT;
58 #endif
59 }
60 
61 #ifdef GALOIS_USE_EXP
62 bool owns(Lockable* lockable, MethodFlag m);
63 #endif
64 
65 [[noreturn]] inline void signalFailSafe(void) {
66 #if defined(GALOIS_USE_LONGJMP_ABORT)
68  std::abort(); // shouldn't reach here after longjmp
69 #elif defined(GALOIS_USE_EXCEPTION_ABORT)
70  throw REACHED_FAILSAFE;
71 #endif
72 }
73 
75 static inline void clearConflictLock() {}
76 
77 class LockManagerBase;
78 
83 class Lockable {
88  Lockable* next;
89  friend class LockManagerBase;
90  friend class SimpleRuntimeContext;
91 
92 public:
93  Lockable() : next(0) {}
94 };
95 
96 class LockManagerBase : private boost::noncopyable {
97 protected:
99 
100  AcquireStatus tryAcquire(Lockable* lockable);
101 
102  inline bool stealByCAS(Lockable* lockable, LockManagerBase* other) {
103  assert(lockable != nullptr);
104  return lockable->owner.stealing_CAS(other, this);
105  }
106 
107  inline bool CASowner(Lockable* lockable, LockManagerBase* other) {
108  assert(lockable != nullptr);
109  return lockable->owner.CAS(other, this);
110  }
111 
112  inline void setOwner(Lockable* lockable) {
113  assert(lockable != nullptr);
114  assert(!lockable->owner.getValue());
115  lockable->owner.setValue(this);
116  }
117 
118  inline void release(Lockable* lockable) {
119  assert(lockable != nullptr);
120  assert(getOwner(lockable) == this);
121  lockable->owner.unlock_and_clear();
122  }
123 
124  inline static bool tryLock(Lockable* lockable) {
125  assert(lockable != nullptr);
126  return lockable->owner.try_lock();
127  }
128 
129  inline static LockManagerBase* getOwner(Lockable* lockable) {
130  assert(lockable != nullptr);
131  return lockable->owner.getValue();
132  }
133 };
134 
137  Lockable* locks;
138  bool customAcquire;
139 
140 protected:
141  friend void doAcquire(Lockable*, galois::MethodFlag);
142 
144  LockManagerBase* owner = LockManagerBase::getOwner(lockable);
145  return static_cast<SimpleRuntimeContext*>(owner);
146  }
147 
148  virtual void subAcquire(Lockable* lockable, galois::MethodFlag m);
149 
150  void addToNhood(Lockable* lockable) {
151  assert(!lockable->next);
152  lockable->next = locks;
153  locks = lockable;
154  }
155 
156  void acquire(Lockable* lockable, galois::MethodFlag m) {
157  AcquireStatus i;
158  if (customAcquire) {
159  subAcquire(lockable, m);
160  } else if ((i = tryAcquire(lockable)) != AcquireStatus::FAIL) {
161  if (i == AcquireStatus::NEW_OWNER) {
162  addToNhood(lockable);
163  }
164  } else {
165  signalConflict(lockable);
166  }
167  }
168 
169  void release(Lockable* lockable);
170 
171 public:
172  SimpleRuntimeContext(bool child = false) : locks(0), customAcquire(child) {}
174 
175  void startIteration() { assert(!locks); }
176 
177  unsigned cancelIteration();
178  unsigned commitIteration();
179 };
180 
183 SimpleRuntimeContext* getThreadContext();
184 
186 void setThreadContext(SimpleRuntimeContext* n);
187 
189 inline bool shouldLock(const galois::MethodFlag g) {
190  // Mask out additional "optional" flags
191  switch (g & galois::MethodFlag::INTERNAL_MASK) {
194  return false;
195 
196  case MethodFlag::READ:
197  case MethodFlag::WRITE:
198  return true;
199 
200  default:
201  // XXX(ddn): Adding error checking code here either upsets the inlining
202  // heuristics or icache behavior. Avoid complex code if possible.
203  // GALOIS_DIE("shouldn't get here");
204  assert(false);
205  }
206  return false;
207 }
208 
210 inline void doAcquire(Lockable* lockable, galois::MethodFlag m) {
212  if (ctx)
213  ctx->acquire(lockable, m);
214 }
215 
218 inline void acquire(Lockable* lockable, galois::MethodFlag m) {
219  if (shouldLock(m))
220  doAcquire(lockable, m);
221 }
222 
224  void operator()(Lockable* lockable) const {
226  }
227 };
228 
232  void operator()(Lockable* lockable) const { acquire(lockable, m); }
233 };
234 
235 } // namespace runtime
236 } // end namespace galois
237 
238 #endif
Definition: libgalois/include/galois/runtime/Context.h:45
unsigned cancelIteration()
Definition: Context.cpp:92
static SimpleRuntimeContext * getOwner(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:143
void setOwner(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:112
PtrLock is a spinlock and a pointer.
Definition: PtrLock.h:42
void setThreadContext(SimpleRuntimeContext *n)
used by the parallel code to set up conflict detection per thread
Definition: Context.cpp:31
thread_local std::jmp_buf execFrame
Definition: Context.cpp:29
bool CASowner(Lockable *lockable, LockManagerBase *other)
Definition: libgalois/include/galois/runtime/Context.h:107
void release(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:118
void signalFailSafe(void)
Definition: libgalois/include/galois/runtime/Context.h:65
Definition: libgalois/include/galois/runtime/Context.h:98
Definition: libgalois/include/galois/runtime/Context.h:98
bool shouldLock(const galois::MethodFlag g)
Helper function to decide if the conflict detection lock should be taken.
Definition: libgalois/include/galois/runtime/Context.h:189
Definition: libgalois/include/galois/runtime/Context.h:229
Lockable()
Definition: libgalois/include/galois/runtime/Context.h:93
void addToNhood(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:150
void doAcquire(Lockable *lockable, galois::MethodFlag m)
actual locking function. Will always lock.
Definition: libgalois/include/galois/runtime/Context.h:210
All objects that may be locked (nodes primarily) must inherit from Lockable.
Definition: libgalois/include/galois/runtime/Context.h:83
Definition: libgalois/include/galois/runtime/Context.h:98
Definition: libgalois/include/galois/runtime/Context.h:223
virtual ~SimpleRuntimeContext()
Definition: libgalois/include/galois/runtime/Context.h:173
Definition: libgalois/include/galois/runtime/Context.h:96
SimpleRuntimeContext(bool child=false)
Definition: libgalois/include/galois/runtime/Context.h:172
virtual void subAcquire(Lockable *lockable, galois::MethodFlag m)
Definition: Context.cpp:96
static LockManagerBase * getOwner(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:129
bool stealByCAS(Lockable *lockable, LockManagerBase *other)
Definition: libgalois/include/galois/runtime/Context.h:102
galois::MethodFlag m
Definition: libgalois/include/galois/runtime/Context.h:230
void startIteration()
Definition: libgalois/include/galois/runtime/Context.h:175
void signalConflict(Lockable *=nullptr)
Definition: libgalois/include/galois/runtime/Context.h:52
void release(Lockable *lockable)
Definition: Context.cpp:67
ConflictFlag
Definition: libgalois/include/galois/runtime/Context.h:41
void acquire(Lockable *lockable, galois::MethodFlag m)
Master function which handles conflict detection used to acquire a lockable thing.
Definition: libgalois/include/galois/runtime/Context.h:218
AcquireStatus
Definition: libgalois/include/galois/runtime/Context.h:98
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
friend void doAcquire(Lockable *, galois::MethodFlag)
actual locking function. Will always lock.
Definition: libgalois/include/galois/runtime/Context.h:210
static bool tryLock(Lockable *lockable)
Definition: libgalois/include/galois/runtime/Context.h:124
Definition: libgalois/include/galois/runtime/Context.h:135
void operator()(Lockable *lockable) const
Definition: libgalois/include/galois/runtime/Context.h:224
AcquireStatus tryAcquire(Lockable *lockable)
Definition: Context.cpp:45
Definition: libgalois/include/galois/runtime/Context.h:42
Definition: libgalois/include/galois/runtime/Context.h:43
void acquire(Lockable *lockable, galois::MethodFlag m)
Definition: libgalois/include/galois/runtime/Context.h:156
CheckedLockObj(galois::MethodFlag _m)
Definition: libgalois/include/galois/runtime/Context.h:231
SimpleRuntimeContext * getThreadContext()
get the current conflict detection class, may be null if not in parallel region
Definition: Context.cpp:36
Definition: libgalois/include/galois/runtime/Context.h:44
unsigned commitIteration()
Definition: Context.cpp:77
void operator()(Lockable *lockable) const
Definition: libgalois/include/galois/runtime/Context.h:232