Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PerThreadStorage.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_SUBSTRATE_PERTHREADSTORAGE_H
21 #define GALOIS_SUBSTRATE_PERTHREADSTORAGE_H
22 
23 #include <cassert>
24 #include <cstddef>
25 #include <utility>
26 #include <vector>
27 
28 #include "galois/config.h"
32 
33 namespace galois {
34 namespace substrate {
35 
36 class PerBackend {
38 
39  std::atomic<unsigned int> nextLoc{0};
40  std::atomic<char*>* heads{nullptr};
41  Lock freeOffsetsLock;
42  std::vector<std::vector<unsigned>> freeOffsets;
50  bool invalid{false};
51 
52  void initCommon(unsigned maxT);
53  static unsigned nextLog2(unsigned size);
54 
55 public:
56  PerBackend();
57 
58  PerBackend(const PerBackend&) = delete;
59  PerBackend& operator=(const PerBackend&) = delete;
60 
62  // Intentionally leak heads so that other PerThread operations are
63  // still valid after we are gone
64  invalid = true;
65  }
66 
67  char* initPerThread(unsigned maxT);
68  char* initPerSocket(unsigned maxT);
69 
70  unsigned allocOffset(const unsigned size);
71  void deallocOffset(const unsigned offset, const unsigned size);
72  void* getRemote(unsigned thread, unsigned offset);
73  void* getLocal(unsigned offset, char* base) { return &base[offset]; }
74  // faster when (1) you already know the id and (2) shared access to heads is
75  // not to expensive; otherwise use getLocal(unsigned,char*)
76  void* getLocal(unsigned offset, unsigned id) { return &heads[id][offset]; }
77 };
78 
79 extern thread_local char* ptsBase;
80 PerBackend& getPTSBackend();
81 
82 extern thread_local char* pssBase;
83 PerBackend& getPPSBackend();
84 
85 void initPTS(unsigned maxT);
86 
87 template <typename T>
89 protected:
91  unsigned offset;
92 
93  void destruct() {
94  if (offset == ~0U)
95  return;
96 
97  for (unsigned n = 0; n < getThreadPool().getMaxThreads(); ++n)
98  reinterpret_cast<T*>(b->getRemote(n, offset))->~T();
99  b->deallocOffset(offset, sizeof(T));
100  offset = ~0U;
101  }
102 
103 public:
104  // construct on each thread
105  template <typename... Args>
106  PerThreadStorage(Args&&... args) : b(&getPTSBackend()) {
107  // in case we make one of these before initializing the thread pool
108  // This will call initPTS for each thread if it hasn't already
109  auto& tp = getThreadPool();
110 
111  offset = b->allocOffset(sizeof(T));
112  for (unsigned n = 0; n < tp.getMaxThreads(); ++n)
113  new (b->getRemote(n, offset)) T(std::forward<Args>(args)...);
114  }
115 
117  rhs.offset = ~0;
118  }
119 
121 
123  std::swap(offset, rhs.offset);
124  std::swap(b, rhs.b);
125  return *this;
126  }
127 
128  T* getLocal() {
129  void* ditem = b->getLocal(offset, ptsBase);
130  return reinterpret_cast<T*>(ditem);
131  }
132 
133  const T* getLocal() const {
134  void* ditem = b->getLocal(offset, ptsBase);
135  return reinterpret_cast<T*>(ditem);
136  }
137 
139  T* getLocal(unsigned int thread) {
140  void* ditem = b->getLocal(offset, thread);
141  return reinterpret_cast<T*>(ditem);
142  }
143 
144  const T* getLocal(unsigned int thread) const {
145  void* ditem = b->getLocal(offset, thread);
146  return reinterpret_cast<T*>(ditem);
147  }
148 
149  T* getRemote(unsigned int thread) {
150  void* ditem = b->getRemote(thread, offset);
151  return reinterpret_cast<T*>(ditem);
152  }
153 
154  const T* getRemote(unsigned int thread) const {
155  void* ditem = b->getRemote(thread, offset);
156  return reinterpret_cast<T*>(ditem);
157  }
158 
159  unsigned size() const { return getThreadPool().getMaxThreads(); }
160 };
161 
162 template <typename T>
164 protected:
165  unsigned offset;
167 
168  void destruct() {
169  auto& tp = getThreadPool();
170  for (unsigned n = 0; n < tp.getMaxSockets(); ++n)
171  reinterpret_cast<T*>(b.getRemote(tp.getLeaderForSocket(n), offset))->~T();
172  b.deallocOffset(offset, sizeof(T));
173  }
174 
175 public:
176  template <typename... Args>
177  PerSocketStorage(Args&&... args) : b(getPPSBackend()) {
178  // in case we make one of these before initializing the thread pool
179  // This will call initPTS for each thread if it hasn't already
180  getThreadPool();
181 
182  offset = b.allocOffset(sizeof(T));
183  auto& tp = getThreadPool();
184  for (unsigned n = 0; n < tp.getMaxSockets(); ++n)
185  new (b.getRemote(tp.getLeaderForSocket(n), offset))
186  T(std::forward<Args>(args)...);
187  }
188 
190  : offset(std::move(o.offset)), b(getPPSBackend()) {}
192  destruct();
193  offset = std::move(o.offset);
194  return *this;
195  }
196 
197  PerSocketStorage(const PerSocketStorage&) = delete;
198  PerSocketStorage& operator=(const PerSocketStorage&) = delete;
199 
201 
202  T* getLocal() {
203  void* ditem = b.getLocal(offset, pssBase);
204  return reinterpret_cast<T*>(ditem);
205  }
206 
207  const T* getLocal() const {
208  void* ditem = b.getLocal(offset, pssBase);
209  return reinterpret_cast<T*>(ditem);
210  }
211 
213  T* getLocal(unsigned int thread) {
214  void* ditem = b.getLocal(offset, thread);
215  return reinterpret_cast<T*>(ditem);
216  }
217 
218  const T* getLocal(unsigned int thread) const {
219  void* ditem = b.getLocal(offset, thread);
220  return reinterpret_cast<T*>(ditem);
221  }
222 
223  T* getRemote(unsigned int thread) {
224  void* ditem = b.getRemote(thread, offset);
225  return reinterpret_cast<T*>(ditem);
226  }
227 
228  const T* getRemote(unsigned int thread) const {
229  void* ditem = b.getRemote(thread, offset);
230  return reinterpret_cast<T*>(ditem);
231  }
232 
233  T* getRemoteByPkg(unsigned int pkg) {
234  void* ditem = b.getRemote(getThreadPool().getLeaderForSocket(pkg), offset);
235  return reinterpret_cast<T*>(ditem);
236  }
237 
238  const T* getRemoteByPkg(unsigned int pkg) const {
239  void* ditem = b.getRemote(getThreadPool().getLeaderForSocket(pkg), offset);
240  return reinterpret_cast<T*>(ditem);
241  }
242 
243  unsigned size() const { return getThreadPool().getMaxThreads(); }
244 };
245 
246 } // namespace substrate
247 } // end namespace galois
248 #endif
PerSocketStorage & operator=(PerSocketStorage &&o)
Definition: PerThreadStorage.h:191
T * getLocal(unsigned int thread)
Like getLocal() but optimized for when you already know the thread id.
Definition: PerThreadStorage.h:139
PerThreadStorage(PerThreadStorage &&rhs)
Definition: PerThreadStorage.h:116
PerBackend & b
Definition: PerThreadStorage.h:166
~PerSocketStorage()
Definition: PerThreadStorage.h:200
ThreadPool & getThreadPool(void)
return a reference to system thread pool
Definition: ThreadPool.cpp:259
PerBackend & getPPSBackend()
Definition: PerThreadStorage.cpp:36
PerThreadStorage & operator=(PerThreadStorage &&rhs)
Definition: PerThreadStorage.h:122
unsigned offset
Definition: PerThreadStorage.h:91
unsigned getMaxThreads() const
return the number of threads supported by the thread pool on the current machine
Definition: ThreadPool.h:178
void destruct()
Definition: PerThreadStorage.h:168
PerSocketStorage(Args &&...args)
Definition: PerThreadStorage.h:177
void * getLocal(unsigned offset, unsigned id)
Definition: PerThreadStorage.h:76
~PerBackend()
Definition: PerThreadStorage.h:61
T * getLocal()
Definition: PerThreadStorage.h:128
void deallocOffset(const unsigned offset, const unsigned size)
Definition: PerThreadStorage.cpp:126
PerThreadStorage(Args &&...args)
Definition: PerThreadStorage.h:106
const T * getLocal() const
Definition: PerThreadStorage.h:133
Definition: PerThreadStorage.h:36
unsigned size() const
Definition: PerThreadStorage.h:243
PerBackend * b
Definition: PerThreadStorage.h:90
T * getRemoteByPkg(unsigned int pkg)
Definition: PerThreadStorage.h:233
PerBackend & operator=(const PerBackend &)=delete
unsigned offset
Definition: PerThreadStorage.h:165
const T * getLocal() const
Definition: PerThreadStorage.h:207
Definition: PerThreadStorage.h:88
Definition: PerThreadStorage.h:163
void initPTS(unsigned)
Definition: PerThreadStorage.cpp:186
const T * getRemote(unsigned int thread) const
Definition: PerThreadStorage.h:228
T * getLocal()
Definition: PerThreadStorage.h:202
PerBackend & getPTSBackend()
Definition: PerThreadStorage.cpp:29
PerSocketStorage(PerSocketStorage &&o)
Definition: PerThreadStorage.h:189
const T * getLocal(unsigned int thread) const
Definition: PerThreadStorage.h:144
thread_local char * pssBase
Definition: PerThreadStorage.cpp:34
unsigned allocOffset(const unsigned size)
Definition: PerThreadStorage.cpp:71
unsigned size() const
Definition: PerThreadStorage.h:159
const T * getRemote(unsigned int thread) const
Definition: PerThreadStorage.h:154
SimpleLock is a spinlock.
Definition: SimpleLock.h:36
PerBackend()
Definition: PerThreadStorage.cpp:58
T * getRemote(unsigned int thread)
Definition: PerThreadStorage.h:223
const T * getLocal(unsigned int thread) const
Definition: PerThreadStorage.h:218
void * getLocal(unsigned offset, char *base)
Definition: PerThreadStorage.h:73
thread_local char * ptsBase
Definition: PerThreadStorage.cpp:27
void * getRemote(unsigned thread, unsigned offset)
Definition: PerThreadStorage.cpp:147
T * getRemote(unsigned int thread)
Definition: PerThreadStorage.h:149
char * initPerThread(unsigned maxT)
Definition: PerThreadStorage.cpp:161
void destruct()
Definition: PerThreadStorage.h:93
char * initPerSocket(unsigned maxT)
Definition: PerThreadStorage.cpp:168
T * getLocal(unsigned int thread)
Like getLocal() but optimized for when you already know the thread id.
Definition: PerThreadStorage.h:213
~PerThreadStorage()
Definition: PerThreadStorage.h:120
const T * getRemoteByPkg(unsigned int pkg) const
Definition: PerThreadStorage.h:238