Atlas Runtime
pregion_mgr.hpp
Go to the documentation of this file.
1 /*
2  * (c) Copyright 2016 Hewlett Packard Enterprise Development LP
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation, either version 3 of the
7  * License, or (at your option) any later version. This program is
8  * distributed in the hope that it will be useful, but WITHOUT ANY
9  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11  * for more details. You should have received a copy of the GNU Lesser
12  * General Public License along with this program. If not, see
13  * <http://www.gnu.org/licenses/>.
14  */
15 
16 
17 #ifndef PREGION_MGR_HPP
18 #define PREGION_MGR_HPP
19 
20 #include <cstdlib>
21 #include <cassert>
22 #include <utility>
23 #include <atomic>
24 
25 #include <stdint.h>
26 #include <pthread.h>
27 #include <sys/file.h>
28 
29 #include "pregion_configs.hpp"
30 #include "pregion_mgr_util.hpp"
31 #include "pregion.hpp"
32 
33 namespace Atlas {
34 
35 class PRegionMgr {
36  static PRegionMgr *Instance_;
37 public:
38  // serial mode only
40  assert(!Instance_);
41  Instance_ = new PRegionMgr();
42  Instance_->initPRegionTable();
43  Instance_->setCacheParams();
44  return *Instance_;
45  }
46 
47  // serial mode only
48  static void deleteInstance() {
49  if (Instance_) {
50  Instance_->shutPRegionTable();
51  delete Instance_;
52  Instance_ = nullptr;
53  }
54  }
55 
56  static PRegionMgr& getInstance() {
57  assert(Instance_);
58  return *Instance_;
59  }
60 
61  static bool hasInstance() { return Instance_ != nullptr; }
62 
63  region_id_t getOpenPRegionId(const void *addr, size_t sz) const;
64 
65  bool isInOpenPRegion(const void *addr, size_t sz) const
66  { return getOpenPRegionId(addr, sz) != kInvalidPRegion_; }
67 
69  assert(rid < getNumPRegions() && "Region index out of range!");
70  return instantiateNewPRegion(rid);
71  }
72 
73  void *allocMem(
74  size_t sz, region_id_t rid,
75  bool does_need_cache_line_alignment, bool does_need_logging) const;
76  void *callocMem(size_t nmemb, size_t sz, region_id_t) const;
77  void *reallocMem(void*, size_t, region_id_t) const;
78  void freeMem(void *ptr, bool should_log = true) const;
79  void deleteMem(void *ptr, bool should_log = true) const;
80  void freeMemImpl(region_id_t rgn_id, void *ptr, bool should_log) const;
81 
82  void *allocMemWithoutLogging(size_t sz, region_id_t rid) const;
84  size_t sz, region_id_t rid, bool should_log) const;
85 
86  region_id_t findOrCreatePRegion(const char *name, int flags,
87  int *is_created = nullptr);
88  region_id_t findPRegion(const char *name, int flags,
89  bool is_in_recovery = false);
90  region_id_t createPRegion(const char *name, int flags);
91  void closePRegion(region_id_t, bool is_deleting = false);
92  void deletePRegion(const char *name);
93  void deleteForcefullyPRegion(const char *name);
95 
96  void *getPRegionRoot(region_id_t) const;
97  void setPRegionRoot(region_id_t, void *new_root) const;
98 
99  PRegion* searchPRegion(const char *name) const;
100 
101  // TODO the following should take the size into consideration
102  std::pair<void* /* base address */,region_id_t>
103  ensurePRegionMapped(void *addr);
104 
105  void dumpDebugInfo() const;
106 private:
107  // PRegionMgr is logically transient
108  void *PRegionTable_; // pointer to regions metadata
109  int PRegionTableFD_; // file holding the metadata
110  pthread_mutex_t PRegionTableLock_; // mediator across threads
111  std::atomic<PRegionExtentMap*> ExtentMap_; // region extent tracker
112 
113  enum OpType { kCreate_, kFind_, kClose_, kDelete_ };
114 
115  PRegionMgr() : PRegionTable_{nullptr}, PRegionTableFD_{-1},
116  ExtentMap_{new PRegionExtentMap()}
117  { pthread_mutex_init(&PRegionTableLock_, NULL); }
118 
119  ~PRegionMgr() { delete ExtentMap_.load(std::memory_order_relaxed); }
120 
121  PRegionMgr(const PRegionMgr&) = delete;
122  PRegionMgr(PRegionMgr&&) = delete;
123  PRegionMgr& operator=(const PRegionMgr&) = delete;
124  PRegionMgr& operator=(PRegionMgr&&) = delete;
125 
126  void acquireTableLock()
127  { pthread_mutex_lock(&PRegionTableLock_); }
128  void releaseTableLock()
129  { pthread_mutex_unlock(&PRegionTableLock_); }
130 
131  // Mediates metadata management across processes (advisory locking)
132  void acquireExclusiveFLock()
133  { flock(PRegionTableFD_, LOCK_EX); }
134  void releaseFLock()
135  { flock(PRegionTableFD_, LOCK_UN); }
136 
137  uint32_t getNumPRegions() const
138  { return *(static_cast<uint32_t*>(PRegionTable_)); }
139 
140  void setNumPRegions(uint32_t);
141 
142  void *computePRegionBaseAddr(void *addr) const;
143 
144  PRegion *instantiateNewPRegion(region_id_t rid) const {
145  return reinterpret_cast<PRegion*>(
146  static_cast<char*>(PRegionTable_) +
147  sizeof(uint32_t) + rid * sizeof(PRegion));
148  }
149 
150  void *computeNewPRegionBaseAddr() const;
151 
152  PRegion *getPRegionArrayPtr() const;
153 
154  void initPRegionTable();
155  void shutPRegionTable();
156 
157  void setCacheParams();
158  int getCacheLineSize() const;
159 
160  void initPRegionRoot(PRegion*);
161 
162  region_id_t initNewPRegionImpl(const char *name, int flags);
163  region_id_t mapNewPRegion(const char *name, int flags, void *base_addr);
164  void mapNewPRegionImpl(
165  PRegion *rgn, const char *name, region_id_t rid,
166  int flags, void *base_addr);
167  void initExistingPRegionImpl(PRegion *preg, const char *name, int flags);
168  void mapExistingPRegion(PRegion *preg, const char *name, int flags);
169  int mapFile(const char *name, int flags, void *base_addr, bool does_exist);
170 
172 
173  void insertExtent(void *first_addr, void *last_addr, region_id_t rid);
174  void deleteExtent(void *first_addr, void *last_addr, region_id_t rid);
175 
176  void tracePRegion(region_id_t, OpType) const;
177  void statsPRegion(region_id_t) const;
178 };
179 
180 inline void *PRegionMgr::allocMem(
181  size_t sz, region_id_t rid, bool does_need_cache_line_alignment,
182  bool does_need_logging) const
183 {
184  return getPRegion(rid)->allocMem(
185  sz, does_need_cache_line_alignment, does_need_logging);
186 }
187 
189  size_t nmemb, size_t sz, region_id_t rid) const
190 {
191  return getPRegion(rid)->callocMem(nmemb, sz);
192 }
193 
195  void *ptr, size_t sz, region_id_t rid) const
196 {
197  return getPRegion(rid)->reallocMem(ptr, sz);
198 }
199 
201  size_t sz, region_id_t rid) const
202 {
203  bool does_need_cache_line_alignment = false;
204  bool does_need_logging = false;
205  return allocMem(
206  sz, rid, does_need_cache_line_alignment, does_need_logging);
207 }
208 
210  size_t sz, region_id_t rid, bool should_log) const
211 {
212  bool does_need_cache_line_alignment = true;
213  return allocMem(
214  sz, rid, does_need_cache_line_alignment, should_log);
215 }
216 
217 inline PRegion *PRegionMgr::getPRegionArrayPtr() const
218 {
219  return reinterpret_cast<PRegion*>(
220  static_cast<char*>(PRegionTable_) + sizeof(uint32_t));
221 }
222 
224 {
225  return getPRegion(rid)->getRoot();
226 }
227 
232 inline void *PRegionMgr::computePRegionBaseAddr(void *addr) const
233 {
234  assert(addr >= (static_cast<char*>(PRegionTable_) + kPRegionSize_) &&
235  addr < (static_cast<char*>(PRegionTable_) +
236  kPRegionSize_ * (kMaxNumPRegions_ + 1)) &&
237  "Location not in any persistent region!");
238  return static_cast<char*>(PRegionTable_) + kPRegionSize_ *
239  ((reinterpret_cast<uint64_t>(addr) -
240  reinterpret_cast<uint64_t>(PRegionTable_))/kPRegionSize_);
241 }
242 
246 inline void *PRegionMgr::computeNewPRegionBaseAddr() const
247 {
248  uint32_t num_regions = getNumPRegions();
249  if (!num_regions) return (char*)kPRegionsBase_ + kPRegionSize_;
250  else return static_cast<char*>(
251  reinterpret_cast<PRegion*>(
252  reinterpret_cast<char*>(getPRegionArrayPtr()) +
253  (num_regions - 1) * sizeof(PRegion))->
254  get_base_addr()) + kPRegionSize_;
255 }
256 
262 inline void PRegionMgr::dumpDebugInfo() const
263 {
264 #if defined(ATLAS_ALLOC_DUMP)
265  assert(Instance_ && "Region manager does not exist!");
266  std::cout << "------- Start of region information -------" << std::endl;
267  std::cout << "Region table base: " << PRegionTable_ << std::endl;
268  PRegion *pregion_arr_ptr = getPRegionArrayPtr();
269  uint32_t curr = 0;
270  for (; curr < getNumPRegions(); ++curr, ++pregion_arr_ptr)
271  pregion_arr_ptr->dumpDebugInfo();
272  std::cout << "------- End of region information -------" << std::endl;
273 #endif
274 }
275 
281 inline void PRegionMgr::tracePRegion(region_id_t rid, OpType op) const
282 {
283 #if defined(ATLAS_ALLOC_TRACE)
284  PRegion *rgn = getPRegion(rid);
285  std::cout << "[Atlas] " <<
286  (op == kCreate_ ? "Created " :
287  op == kFind_ ? "Found " :
288  op == kClose_ ? "Closed " :
289  op == kDelete_ ? "Deleted " :
290  "Unknown")
291  << "region with name=" << rgn->get_name()
292  << " id " << rgn->get_id() << " address " << rgn->get_base_addr()
293  << std::endl;
294 #endif
295 }
296 
302 inline void PRegionMgr::statsPRegion(region_id_t rid) const
303 {
304 #if defined(ATLAS_ALLOC_STATS)
305  getPRegion(rid)->printStats();
306 #endif
307 }
308 
309 
310 } // namespace Atlas
311 
312 #endif
static void deleteInstance()
Definition: pregion_mgr.hpp:48
static bool hasInstance()
Definition: pregion_mgr.hpp:61
Definition: pregion_mgr_util.hpp:27
static PRegionMgr & createInstance()
Definition: pregion_mgr.hpp:39
Definition: pregion_mgr.hpp:35
Definition: pregion.hpp:31
region_id_t get_id() const
Definition: pregion.hpp:52
const uint32_t kInvalidPRegion_
Definition: pregion_configs.hpp:33
void deleteForcefullyPRegion(const char *name)
Definition: pregion_mgr.cpp:310
const char * get_name() const
Definition: pregion.hpp:57
const uint32_t kMaxNumPRegions_
Definition: pregion_configs.hpp:29
void * reallocMem(void *, size_t)
Definition: pregion.cpp:156
uint32_t region_id_t
Definition: pregion_configs.hpp:22
void * allocMem(size_t sz, bool does_need_cache_line_alignment, bool does_need_logging)
Definition: pregion.cpp:26
const uint64_t kPRegionSize_
Definition: pregion_configs.hpp:28
const uint64_t kPRegionsBase_
Definition: pregion_configs.hpp:35
region_id_t findOrCreatePRegion(const char *name, int flags, int *is_created=nullptr)
Definition: pregion_mgr.cpp:96
void * callocMem(size_t nmemb, size_t sz, region_id_t) const
Definition: pregion_mgr.hpp:188
void closePRegion(region_id_t, bool is_deleting=false)
Definition: pregion_mgr.cpp:236
bool isInOpenPRegion(const void *addr, size_t sz) const
Definition: pregion_mgr.hpp:65
void freeMemImpl(region_id_t rgn_id, void *ptr, bool should_log) const
Definition: pregion_mgr.cpp:76
void * allocMemWithoutLogging(size_t sz, region_id_t rid) const
Definition: pregion_mgr.hpp:200
void deleteMem(void *ptr, bool should_log=true) const
Definition: pregion_mgr.cpp:65
void * allocMem(size_t sz, region_id_t rid, bool does_need_cache_line_alignment, bool does_need_logging) const
Definition: pregion_mgr.hpp:180
void deleteForcefullyAllPRegions()
Definition: pregion_mgr.cpp:347
uint32_t rgn_id
Definition: malloc_free_test.c:22
std::pair< void *,region_id_t > ensurePRegionMapped(void *addr)
Definition: pregion_mgr.cpp:636
void * allocMemCacheLineAligned(size_t sz, region_id_t rid, bool should_log) const
Definition: pregion_mgr.hpp:209
void * get_base_addr() const
Definition: pregion.hpp:53
void deletePRegion(const char *name)
Definition: pregion_mgr.cpp:275
void setPRegionRoot(region_id_t, void *new_root) const
Definition: pregion_mgr.cpp:370
region_id_t findPRegion(const char *name, int flags, bool is_in_recovery=false)
Definition: pregion_mgr.cpp:155
PRegion * searchPRegion(const char *name) const
Definition: pregion_mgr.cpp:608
void dumpDebugInfo() const
Definition: pregion.hpp:151
void * callocMem(size_t nmemb, size_t sz)
Definition: pregion.cpp:143
region_id_t getOpenPRegionId(const void *addr, size_t sz) const
Definition: pregion_mgr.cpp:625
region_id_t createPRegion(const char *name, int flags)
Definition: pregion_mgr.cpp:200
void * getRoot() const
Definition: pregion.hpp:91
Definition: atlas_alloc_cpp.hpp:21
void * reallocMem(void *, size_t, region_id_t) const
Definition: pregion_mgr.hpp:194
static PRegionMgr & getInstance()
Definition: pregion_mgr.hpp:56
void printStats()
Definition: pregion.hpp:163
PRegion * getPRegion(region_id_t rid) const
Definition: pregion_mgr.hpp:68
void * getPRegionRoot(region_id_t) const
Definition: pregion_mgr.hpp:223
void dumpDebugInfo() const
Definition: pregion_mgr.hpp:262
void freeMem(void *ptr, bool should_log=true) const
Definition: pregion_mgr.cpp:48