Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
runtime/Mem.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_MEM_H
21 #define GALOIS_RUNTIME_MEM_H
22 
23 #include <cstddef>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <list>
28 #include <map>
29 #include <memory>
30 
31 #include <boost/utility.hpp>
32 
33 #include "galois/config.h"
34 #include "galois/gIO.h"
41 
42 namespace galois {
43 namespace runtime {
44 
45 extern unsigned activeThreads;
46 
48 
49 void preAlloc_impl(unsigned num);
50 
51 // const size_t hugePageSize = 2*1024*1024;
52 
54 void pagePreAlloc(int numpages);
56 void pageIn(void* buf, size_t len, size_t stride);
58 void pageInReadOnly(void* buf, size_t len, size_t stride);
59 
61 int numNumaAllocForNode(unsigned nodeid);
62 
65 void printInterleavedStats(int minPages = 16 * 1024);
66 
68 class MallocHeap {
69 public:
72  enum { AllocSize = 0 };
73 
74  void* allocate(size_t size) { return malloc(size); }
75 
76  void deallocate(void* ptr) { free(ptr); }
77 };
79 
81 template <class SourceHeap>
84 
85 public:
86  enum { AllocSize = SourceHeap::AllocSize };
87 
90 
91  template <typename... Args>
92  inline void* allocate(size_t size, Args&&... args) {
93  return heaps.getLocal()->allocate(size, std::forward<Args>(args)...);
94  }
95 
96  inline void deallocate(void* ptr) { heaps.getLocal()->deallocate(ptr); }
97 
98  void clear() {
99  for (unsigned int i = 0; i < heaps.size(); i++)
100  heaps.getRemote(i)->clear();
101  }
102 };
103 
105 template <class SourceHeap>
106 class LockedHeap : public SourceHeap {
108 
109 public:
110  enum { AllocSize = SourceHeap::AllocSize };
111 
112  inline void* allocate(size_t size) {
113  lock.lock();
114  void* retval = SourceHeap::allocate(size);
115  lock.unlock();
116  return retval;
117  }
118 
119  inline void deallocate(void* ptr) {
120  lock.lock();
121  SourceHeap::deallocate(ptr);
122  lock.unlock();
123  }
124 };
125 
126 template <typename SourceHeap>
127 class ZeroOut : public SourceHeap {
128 public:
129  enum { AllocSize = SourceHeap::AllocSize };
130 
131  inline void* allocate(size_t size) {
132  void* retval = SourceHeap::allocate(size);
133  memset(retval, 0, size);
134  return retval;
135  }
136 
137  inline void deallocate(void* ptr) { SourceHeap::deallocate(ptr); }
138 };
139 
141 template <typename Header, typename SourceHeap>
142 class AddHeader : public SourceHeap {
143  enum {
144  offset = (sizeof(Header) + (sizeof(double) - 1)) & ~(sizeof(double) - 1)
145  };
146 
147 public:
148  inline void* allocate(size_t size) {
149  // First increase the size of the header to be aligned to a double
150  void* ptr = SourceHeap::allocate(size + offset);
151  // Now return the offseted pointer
152  return (char*)ptr + offset;
153  }
154 
155  inline void deallocate(void* ptr) { SourceHeap::deallocate(getHeader(ptr)); }
156 
157  inline static Header* getHeader(void* ptr) {
158  return (Header*)((char*)ptr - offset);
159  }
160 };
161 
163 template <class SourceHeap>
164 class OwnerTaggedHeap : public AddHeader<void*, SourceHeap> {
166 
167 public:
168  inline void* allocate(size_t size) {
169  void* retval = Src::allocate(size);
170  *(Src::getHeader(retval)) = this;
171  return retval;
172  }
173 
174  inline void deallocate(void* ptr) {
175  assert(*(Src::getHeader(ptr)) == this);
176  Src::deallocate(ptr);
177  }
178 
179  inline static OwnerTaggedHeap* owner(void* ptr) {
180  return *(OwnerTaggedHeap**)Src::getHeader(ptr);
181  }
182 };
183 
185 template <class SourceHeap>
186 class FreeListHeap : public SourceHeap {
187  struct FreeNode {
188  FreeNode* next;
189  };
190  FreeNode* head;
191 
192  using dbg = galois::debug<0>;
193 
194 public:
195  enum { AllocSize = SourceHeap::AllocSize };
196 
197  void clear() {
198  while (head) {
199  FreeNode* N = head;
200  head = N->next;
201  SourceHeap::deallocate(N);
202  }
203  }
204 
205  FreeListHeap() : head(0) {}
207 
208  inline void* allocate(size_t size) {
209  if (head) {
210  void* ptr = head;
211  head = head->next;
212  dbg::print(this, " picking from free list, ptr = ", ptr);
213  return ptr;
214  } else {
215  void* ptr = SourceHeap::allocate(size);
216  dbg::print(this, " allocating from SourceHeap, ptr = ", ptr);
217  return ptr;
218  }
219  }
220 
221  inline void deallocate(void* ptr) {
222  if (!ptr)
223  return;
224  assert((uintptr_t)ptr > 0x100);
225  FreeNode* NH = (FreeNode*)ptr;
226  NH->next = head;
227  head = NH;
228  dbg::print(this, " adding block to list, head = ", head);
229  }
230 };
231 
233 template <class SourceHeap>
234 class SelfLockFreeListHeap : public SourceHeap {
235  struct FreeNode {
236  FreeNode* next;
237  };
238  FreeNode* head;
239 
240 public:
241  enum { AllocSize = SourceHeap::AllocSize };
242 
243  void clear() {
244  FreeNode* h = 0;
245  do {
246  h = head;
247  } while (!__sync_bool_compare_and_swap(&head, h, 0));
248  while (h) {
249  FreeNode* N = h;
250  h = N->next;
251  SourceHeap::deallocate(N);
252  }
253  }
254 
255  SelfLockFreeListHeap() : head(0) {}
257 
258  inline void* allocate(size_t size) {
259  static substrate::SimpleLock lock;
260 
261  lock.lock();
262  FreeNode* OH = 0;
263  FreeNode* NH = 0;
264  do {
265  OH = head;
266  if (!OH) {
267  lock.unlock();
268  return SourceHeap::allocate(size);
269  }
270  NH = OH->next; // The lock protects this line
271  } while (!__sync_bool_compare_and_swap(&head, OH, NH));
272  lock.unlock();
273  assert(OH);
274  return (void*)OH;
275  }
276 
277  inline void deallocate(void* ptr) {
278  if (!ptr)
279  return;
280  FreeNode* OH;
281  FreeNode* NH;
282  do {
283  OH = head;
284  NH = (FreeNode*)ptr;
285  NH->next = OH;
286  } while (!__sync_bool_compare_and_swap(&head, OH, NH));
287  }
288 };
289 
290 template <unsigned ElemSize, typename SourceHeap>
291 class BlockHeap : public SourceHeap {
292  struct TyEq {
293  double data[((ElemSize + sizeof(double) - 1) & ~(sizeof(double) - 1)) /
294  sizeof(double)];
295  };
296 
297  struct Block_basic {
298  union {
299  Block_basic* next;
300  double dummy;
301  };
302  TyEq data[1];
303  };
304 
305  enum {
306  BytesLeft = (SourceHeap::AllocSize - sizeof(Block_basic)),
307  BytesLeftR = BytesLeft & ~(sizeof(double) - 1),
308  FitLeft = BytesLeftR / sizeof(TyEq[1]),
309  TotalFit = FitLeft + 1
310  };
311 
312  struct Block {
313  union {
314  Block* next;
315  double dummy;
316  };
317  TyEq data[TotalFit];
318  };
319 
320  Block* head;
321  int headIndex;
322 
323  void refill() {
324  void* P = SourceHeap::allocate(SourceHeap::AllocSize);
325  Block* BP = (Block*)P;
326  BP->next = head;
327  head = BP;
328  headIndex = 0;
329  }
330 
331 public:
332  enum { AllocSize = ElemSize };
333 
334  void clear() {
335  while (head) {
336  Block* B = head;
337  head = B->next;
338  SourceHeap::deallocate(B);
339  }
340  }
341 
342  BlockHeap() : SourceHeap(), head(0), headIndex(0) {
343  static_assert(sizeof(Block) <= SourceHeap::AllocSize, "");
344  }
345 
346  ~BlockHeap() { clear(); }
347 
348  inline void* allocate(size_t GALOIS_USED_ONLY_IN_DEBUG(size)) {
349  assert(size == ElemSize);
350  if (!head || headIndex == TotalFit)
351  refill();
352  return &head->data[headIndex++];
353  }
354 
355  inline void deallocate(void*) {}
356 };
357 
359 template <typename SourceHeap>
360 class BumpHeap : public SourceHeap {
361  struct Block {
362  union {
363  Block* next;
364  double dummy; // for alignment
365  };
366  };
367 
368  Block* head;
369  int offset;
370 
371  void refill() {
372  void* P = SourceHeap::allocate(SourceHeap::AllocSize);
373  Block* BP = (Block*)P;
374  BP->next = head;
375  head = BP;
376  offset = sizeof(Block);
377  }
378 
379 public:
380  enum { AllocSize = 0 };
381 
382  BumpHeap() : SourceHeap(), head(0), offset(0) {}
383 
384  ~BumpHeap() { clear(); }
385 
386  void clear() {
387  while (head) {
388  Block* B = head;
389  head = B->next;
390  SourceHeap::deallocate(B);
391  }
392  }
393 
394  inline void* allocate(size_t size) {
395  // Increase to alignment
396  size_t alignedSize = (size + sizeof(double) - 1) & ~(sizeof(double) - 1);
397  // Check current block
398  if (!head || offset + alignedSize > SourceHeap::AllocSize) {
399  refill();
400  }
401  if (offset + alignedSize > SourceHeap::AllocSize) {
402  std::abort(); // TODO: remove
403  throw std::bad_alloc();
404  }
405  char* retval = (char*)head;
406  retval += offset;
407  offset += alignedSize;
408  return retval;
409  }
410 
415  inline void* allocate(size_t size, size_t& allocated) {
416  // Increase to alignment
417  size_t alignedSize = (size + sizeof(double) - 1) & ~(sizeof(double) - 1);
418  if (alignedSize > SourceHeap::AllocSize) {
419  alignedSize = SourceHeap::AllocSize;
420  }
421  // Check current block
422  if (!head || offset + alignedSize > SourceHeap::AllocSize) {
423  size_t remaining = SourceHeap::AllocSize - offset;
424  assert((remaining & (sizeof(double) - 1)) ==
425  0); // should still be aligned
426  if (!remaining) {
427  refill();
428  } else {
429  alignedSize = remaining;
430  }
431  }
432  char* retval = (char*)head;
433  retval += offset;
434  offset += alignedSize;
435  allocated = (alignedSize > size) ? size : alignedSize;
436  return retval;
437  }
438 
439  inline void deallocate(void*) {}
440 };
441 
446 template <typename SourceHeap>
447 class BumpWithMallocHeap : public SourceHeap {
448  struct Block {
449  union {
450  Block* next;
451  double dummy; // for alignment
452  };
453  };
454 
455  Block* head;
456  Block* fallbackHead;
457  int offset;
458 
460  void refill(void* P, Block*& h, int* o) {
461  Block* BP = (Block*)P;
462  BP->next = h;
463  h = BP;
464  if (o)
465  *o = sizeof(Block);
466  }
467 
468 public:
469  enum { AllocSize = 0 };
470 
471  BumpWithMallocHeap() : SourceHeap(), head(0), fallbackHead(0), offset(0) {}
472 
474 
475  void clear() {
476  while (head) {
477  Block* B = head;
478  head = B->next;
479  SourceHeap::deallocate(B);
480  }
481  while (fallbackHead) {
482  Block* B = fallbackHead;
483  fallbackHead = B->next;
484  free(B);
485  }
486  }
487 
488  inline void* allocate(size_t size) {
489  // Increase to alignment
490  size_t alignedSize = (size + sizeof(double) - 1) & ~(sizeof(double) - 1);
491  if (sizeof(Block) + alignedSize > SourceHeap::AllocSize) {
492  void* p = malloc(alignedSize + sizeof(Block));
493  refill(p, fallbackHead, NULL);
494  return (char*)p + sizeof(Block);
495  }
496  // Check current block
497  if (!head || offset + alignedSize > SourceHeap::AllocSize)
498  refill(SourceHeap::allocate(SourceHeap::AllocSize), head, &offset);
499  char* retval = (char*)head;
500  retval += offset;
501  offset += alignedSize;
502  return retval;
503  }
504 
505  inline void deallocate(void*) {}
506 };
507 
510 class SystemHeap {
511 public:
512  // FIXME: actually check!
513  enum { AllocSize = 2 * 1024 * 1024 };
514 
515  SystemHeap();
516  ~SystemHeap();
517 
518  inline void* allocate(size_t) { return pagePoolAlloc(); }
519 
520  inline void deallocate(void* ptr) { pagePoolFree(ptr); }
521 };
522 
523 template <typename Derived>
524 class StaticSingleInstance : private boost::noncopyable {
525 
526  // static std::unique_ptr<Derived> instance;
527  static substrate::PtrLock<Derived> ptr;
528 
529 public:
530  static Derived* getInstance(void) {
531  Derived* f = ptr.getValue();
532  if (f) {
533  // assert (f == instance.get ());
534  return f;
535  }
536 
537  ptr.lock();
538  f = ptr.getValue();
539  if (f) {
540  ptr.unlock();
541  // assert (f == instance.get ());
542  } else {
543  // instance = std::unique_ptr<Derived> (new Derived());
544  // f = instance.get ();
545  f = new Derived;
546  ptr.unlock_and_set(f);
547  }
548  return f;
549  }
550 };
551 
552 // template <typename Derived>
553 // std::unique_ptr<Derived> StaticSingleInstance<Derived>::instance =
554 // std::unique_ptr<Derived>();
555 
556 template <typename Derived>
558  StaticSingleInstance<Derived>::ptr = substrate::PtrLock<Derived>();
559 
560 class PageHeap : public StaticSingleInstance<PageHeap> {
561 
563 
564  /* template <typename _U> */ friend class StaticSingleInstance<PageHeap>;
565 
567  // using InnerHeap = SystemHeap;
568 
569  InnerHeap innerHeap;
570 
571  using dbg = galois::debug<0>;
572 
573  PageHeap() : innerHeap() { dbg::print("New instance of PageHeap: ", this); }
574 
575 public:
576  enum { AllocSize = InnerHeap::AllocSize };
577 
578  inline void* allocate(size_t size) {
579  assert(size <= AllocSize);
580  void* ptr = innerHeap.allocate(size);
581  dbg::print(this, " PageHeap allocate, ptr = ", ptr);
582  return ptr;
583  }
584 
585  inline void deallocate(void* ptr) {
586  assert(ptr);
587  dbg::print(this, " PageHeap deallocate ptr = ", ptr);
588  innerHeap.deallocate(ptr);
589  }
590 };
591 
592 #ifdef GALOIS_FORCE_STANDALONE
593 class SizedHeapFactory : private boost::noncopyable {
594 public:
595  typedef MallocHeap SizedHeap;
596 
597  static SizedHeap* getHeapForSize(const size_t) { return &alloc; }
598 
599 private:
600  static SizedHeap alloc;
601 };
602 #else
603 class SizedHeapFactory : public StaticSingleInstance<SizedHeapFactory> {
605  /* template <typename> */ friend class StaticSingleInstance<SizedHeapFactory>;
606 
607 public:
611 
612  static SizedHeap* getHeapForSize(const size_t);
613 
614 private:
615  typedef std::map<size_t, SizedHeap*> HeapMap;
616  static thread_local HeapMap* localHeaps;
617  HeapMap heaps;
618  std::list<HeapMap*> allLocalHeaps;
620 
622 
623  SizedHeap* getHeap(size_t);
624 
625 public:
626  ~SizedHeapFactory();
627 };
628 #endif
629 
637 struct VariableSizeHeap : public ThreadPrivateHeap<BumpHeap<SystemHeap>> {
638  enum { AllocSize = 0 };
639 };
640 
644 
645 public:
646  FixedSizeHeap(size_t size) {
648  if (!heap && size != 0) {
649  fprintf(stderr, "ERROR: Cannot init a fixed sized heap from "
650  "SizedHeapFactory\n");
651  throw std::bad_alloc();
652  }
653  }
654 
655  inline void* allocate(size_t size) {
656  void* alloc = heap->allocate(size);
657  if (alloc == nullptr && size != 0) {
658  fprintf(stderr, "ERROR: Fixed sized heap allocate called failed\n");
659  throw std::bad_alloc();
660  }
661  return alloc;
662  }
663 
664  inline void deallocate(void* ptr) { heap->deallocate(ptr); }
665 
666  inline bool operator!=(const FixedSizeHeap& rhs) const {
667  return heap != rhs.heap;
668  }
669 
670  inline bool operator==(const FixedSizeHeap& rhs) const {
671  return heap == rhs.heap;
672  }
673 };
674 
676  enum {
677  offset = (sizeof(substrate::LAptr) + (sizeof(double) - 1)) &
678  ~(sizeof(double) - 1)
679  };
680 
681 public:
682  enum { AllocSize = 0 };
683 
684  void* allocate(size_t size) {
685  auto ptr = substrate::largeMallocInterleaved(size + offset, activeThreads);
686  substrate::LAptr* header =
687  new ((char*)ptr.get()) substrate::LAptr{std::move(ptr)};
688  return (char*)(header->get()) + offset;
689  }
690 
691  void deallocate(void* ptr) {
692  char* realPtr = ((char*)ptr - offset);
693  substrate::LAptr dptr{std::move(*(substrate::LAptr*)realPtr)};
694  }
695 };
696 
698 // Now adapt to standard std allocators
700 
702 template <typename Ty>
704 
705 template <>
706 class FixedSizeAllocator<void> {
707 public:
708  typedef size_t size_type;
709  typedef ptrdiff_t difference_type;
710  typedef void* pointer;
711  typedef const void* const_pointer;
712  typedef void value_type;
713 
714  template <typename Other>
715  struct rebind {
717  };
718 };
719 
720 template <typename Ty>
721 class FixedSizeAllocator {
722  inline void destruct(char*) const {}
723  inline void destruct(wchar_t*) const {}
724  template <typename T>
725  inline void destruct(T* t) const {
726  t->~T();
727  }
728 
729  FixedSizeHeap heap;
730 
731 public:
732  typedef size_t size_type;
733  typedef ptrdiff_t difference_type;
734  typedef Ty* pointer;
735  typedef const Ty* const_pointer;
736  typedef Ty& reference;
737  typedef const Ty& const_reference;
738  typedef Ty value_type;
739 
740  template <class Other>
741  struct rebind {
743  };
744 
745  FixedSizeAllocator() noexcept : heap(sizeof(Ty)) {}
746 
747  template <class U>
749  : heap(sizeof(Ty)) {}
750 
751  inline pointer address(reference val) const { return &val; }
752  inline const_pointer address(const_reference val) const { return &val; }
753 
755  if (size > max_size())
756  throw std::bad_alloc();
757  return static_cast<pointer>(heap.allocate(sizeof(Ty)));
758  }
759 
760  void deallocate(pointer ptr, size_type GALOIS_USED_ONLY_IN_DEBUG(len)) {
761  assert(len == 1);
762  heap.deallocate(ptr);
763  }
764 
765  template <class U, class... Args>
766  inline void construct(U* p, Args&&... args) const {
767  ::new ((void*)p) U(std::forward<Args>(args)...);
768  }
769 
770  inline void destroy(pointer ptr) const { destruct(ptr); }
771 
772  size_type max_size() const noexcept { return 1; }
773 
774  template <typename T1>
775  inline bool operator!=(const FixedSizeAllocator<T1>& rhs) const {
776  return heap != rhs.heap;
777  }
778 
779  template <typename T1>
780  inline bool operator==(const FixedSizeAllocator<T1>& rhs) const {
781  return heap == rhs.heap;
782  }
783 };
784 
785 class Pow_2_BlockHeap : public StaticSingleInstance<Pow_2_BlockHeap> {
786 
787 private:
789  /* template <typename> */ friend class StaticSingleInstance<Pow_2_BlockHeap>;
790 
791  static const bool USE_MALLOC_AS_BACKUP = true;
792 
793  static const size_t LOG2_MIN_SIZE = 3; // 2^3 == 8 bytes
794  static const size_t LOG2_MAX_SIZE = 16; // 64k
795 
796  typedef FixedSizeHeap Heap_ty;
797 
798  std::vector<Heap_ty> heapTable;
799 
800  static inline size_t pow2(unsigned i) { return (1U << i); }
801 
802  static unsigned nextLog2(const size_t allocSize) {
803 
804  unsigned i = LOG2_MIN_SIZE;
805 
806  while (pow2(i) < allocSize) {
807  ++i;
808  }
809 
810  // if (pow2 (i) > pow2 (LOG2_MAX_SIZE)) {
811  // std::fprintf (stderr, "ERROR: block bigger than huge page size
812  // requested\n"); throw std::bad_alloc();
813  // }
814 
815  return i;
816  }
817 
818  void populateTable(void) {
819  assert(heapTable.empty());
820 
821  heapTable.clear();
822  for (unsigned i = 0; i <= LOG2_MAX_SIZE; ++i) {
823  heapTable.push_back(Heap_ty(pow2(i)));
824  }
825  }
826 
827  Pow_2_BlockHeap() noexcept; // NOLINT(modernize-use-equals-delete)
828 
829 public:
830  void* allocateBlock(const size_t allocSize) {
831 
832  if (allocSize > pow2(LOG2_MAX_SIZE)) {
833  if (USE_MALLOC_AS_BACKUP) {
834  return malloc(allocSize);
835  } else {
836  fprintf(stderr, "ERROR: block bigger than huge page size requested\n");
837  throw std::bad_alloc();
838  }
839  } else {
840 
841  unsigned i = nextLog2(allocSize);
842  assert(i < heapTable.size());
843  return heapTable[i].allocate(pow2(i));
844  }
845  }
846 
847  void deallocateBlock(void* ptr, const size_t allocSize) {
848  if (allocSize > pow2(LOG2_MAX_SIZE)) {
849  if (USE_MALLOC_AS_BACKUP) {
850  free(ptr);
851  } else {
852  fprintf(stderr, "ERROR: block bigger than huge page size requested\n");
853  throw std::bad_alloc();
854  }
855  } else {
856  unsigned i = nextLog2(allocSize);
857  assert(i < heapTable.size());
858  heapTable[i].deallocate(ptr);
859  }
860  }
861 };
862 
863 template <typename Ty>
865 
866  template <typename T>
867  static inline void destruct(T* t) {
868  if (!std::is_scalar<T>::value) {
869  t->~T();
870  }
871  }
872 
873 public:
874  typedef size_t size_type;
875  typedef ptrdiff_t difference_type;
876  typedef Ty* pointer;
877  typedef const Ty* const_pointer;
878  typedef Ty& reference;
879  typedef const Ty& const_reference;
880  typedef Ty value_type;
881 
882  template <class Other>
883  struct rebind {
885  };
886 
888 
889  Pow_2_BlockAllocator() noexcept : heap(Pow_2_BlockHeap::getInstance()) {}
890 
891  // template <typename U>
892  // friend class Pow_2_BlockAllocator<U>;
893 
894  template <typename U>
896  : heap(that.heap) {}
897 
898  inline pointer address(reference val) const { return &val; }
899 
900  inline const_pointer address(const_reference val) const { return &val; }
901 
903  return static_cast<pointer>(heap->allocateBlock(size * sizeof(Ty)));
904  }
905 
906  void deallocate(pointer ptr, size_type len) {
907  heap->deallocateBlock(ptr, len * sizeof(Ty));
908  }
909 
910  template <class U, class... Args>
911  inline void construct(U* p, Args&&... args) const {
912  ::new ((void*)p) U(std::forward<Args>(args)...);
913  }
914 
915  inline void destroy(pointer ptr) const { destruct(ptr); }
916 
917  size_type max_size() const noexcept { return size_type(-1); }
918 
919  template <typename T1>
920  bool operator!=(const Pow_2_BlockAllocator<T1>& rhs) const {
921  return heap != rhs.heap;
922  }
923 
924  template <typename T1>
925  bool operator==(const Pow_2_BlockAllocator<T1>& rhs) const {
926  return heap == rhs.heap;
927  }
928 };
929 
930 template <>
931 class Pow_2_BlockAllocator<void> {
932 public:
933  typedef size_t size_type;
934  typedef ptrdiff_t difference_type;
935  typedef void* pointer;
936  typedef const void* const_pointer;
937  typedef void value_type;
938 
939  template <typename Other>
940  struct rebind {
942  };
943 };
944 
946 template <typename Ty, typename HeapTy>
948 
949 template <typename HeapTy>
950 class ExternalHeapAllocator<void, HeapTy> {
951 public:
952  typedef size_t size_type;
953  typedef ptrdiff_t difference_type;
954  typedef void* pointer;
955  typedef const void* const_pointer;
956  typedef void value_type;
957 
958  template <typename Other>
959  struct rebind {
961  };
962 };
963 
964 template <typename Ty, typename HeapTy>
965 class ExternalHeapAllocator {
966  inline void destruct(char*) const {}
967  inline void destruct(wchar_t*) const {}
968  template <typename T>
969  inline void destruct(T* t) const {
970  t->~T();
971  }
972 
973 public:
974  HeapTy* heap; // Should be private except that makes copy hard
975 
976  typedef size_t size_type;
977  typedef ptrdiff_t difference_type;
978  typedef Ty* pointer;
979  typedef const Ty* const_pointer;
980  typedef Ty& reference;
981  typedef const Ty& const_reference;
982  typedef Ty value_type;
983 
984  template <class Other>
985  struct rebind {
987  };
988 
989  explicit ExternalHeapAllocator(HeapTy* a) noexcept : heap(a) {}
990 
991  template <class T1>
993  heap = rhs.heap;
994  }
995 
996  inline pointer address(reference val) const { return &val; }
997 
998  inline const_pointer address(const_reference val) const { return &val; }
999 
1001  if (size > max_size())
1002  throw std::bad_alloc();
1003  return static_cast<pointer>(heap->allocate(size * sizeof(Ty)));
1004  }
1005 
1006  void deallocate(pointer ptr, size_type) { heap->deallocate(ptr); }
1007 
1008  inline void construct(pointer ptr, const_reference val) const {
1009  new (ptr) Ty(val);
1010  }
1011 
1012  template <class U, class... Args>
1013  inline void construct(U* p, Args&&... args) const {
1014  ::new ((void*)p) U(std::forward<Args>(args)...);
1015  }
1016 
1017  void destroy(pointer ptr) const { destruct(ptr); }
1018 
1019  size_type max_size() const noexcept {
1020  return (HeapTy::AllocSize == 0) ? size_t(-1) / sizeof(Ty)
1021  : HeapTy::AllocSize / sizeof(Ty);
1022  }
1023 
1024  template <typename T1, typename A1>
1026  return heap != rhs.heap;
1027  }
1028 
1029  template <typename T1, typename A1>
1031  return heap == rhs.heap;
1032  }
1033 };
1034 
1035 template <typename T>
1036 class SerialNumaAllocator : public ExternalHeapAllocator<T, SerialNumaHeap> {
1038  SerialNumaHeap heap;
1039 
1040 public:
1041  template <class Other>
1042  struct rebind {
1044  };
1045 
1047 };
1048 
1049 } // end namespace runtime
1050 } // end namespace galois
1051 
1052 #endif
void * allocate(size_t size, Args &&...args)
Definition: runtime/Mem.h:92
pointer allocate(size_type size)
Definition: runtime/Mem.h:1000
BlockHeap()
Definition: runtime/Mem.h:342
void * allocate(size_t size)
Definition: runtime/Mem.h:168
void printInterleavedStats(int minPages=16 *1024)
Print lines from /proc/pid/numa_maps that contain at least n (non-huge) pages.
void destroy(pointer ptr) const
Definition: runtime/Mem.h:915
FreeListHeap()
Definition: runtime/Mem.h:205
This is the base source of memory for all allocators.
Definition: runtime/Mem.h:510
void deallocate(pointer ptr, size_type)
Definition: runtime/Mem.h:1006
HeapTy * heap
Definition: runtime/Mem.h:974
ExternalHeapAllocator< Other, HeapTy > other
Definition: runtime/Mem.h:986
static void print(const Args &...)
Definition: gIO.h:123
Definition: runtime/Mem.h:1042
Definition: runtime/Mem.h:524
Add a header to objects.
Definition: runtime/Mem.h:142
Maintain a freelist using a lock which doesn&#39;t cover SourceHeap.
Definition: runtime/Mem.h:234
void deallocate(void *ptr)
Definition: runtime/Mem.h:96
~SelfLockFreeListHeap()
Definition: runtime/Mem.h:256
const void * const_pointer
Definition: runtime/Mem.h:955
void deallocate(pointer ptr, size_type len)
Definition: runtime/Mem.h:906
Definition: runtime/Mem.h:675
Ty * pointer
Definition: runtime/Mem.h:876
const_pointer address(const_reference val) const
Definition: runtime/Mem.h:752
ptrdiff_t difference_type
Definition: runtime/Mem.h:709
void deallocate(void *)
Definition: runtime/Mem.h:439
SelfLockFreeListHeap()
Definition: runtime/Mem.h:255
void value_type
Definition: runtime/Mem.h:712
Pow_2_BlockAllocator< Other > other
Definition: runtime/Mem.h:884
static SizedHeap * getHeapForSize(const size_t)
[FixedSizeAllocator example]
Definition: Mem.cpp:36
void * pointer
Definition: runtime/Mem.h:935
ptrdiff_t difference_type
Definition: runtime/Mem.h:733
void clear()
Definition: runtime/Mem.h:334
size_type max_size() const noexcept
Definition: runtime/Mem.h:1019
void deallocate(void *ptr)
Definition: runtime/Mem.h:691
Pow_2_BlockAllocator(const Pow_2_BlockAllocator< U > &that) noexcept
Definition: runtime/Mem.h:895
const Ty * const_pointer
Definition: runtime/Mem.h:877
Definition: runtime/Mem.h:291
Definition: runtime/Mem.h:1036
void clear()
Definition: runtime/Mem.h:386
pointer allocate(size_type size)
Definition: runtime/Mem.h:902
void * allocate(size_t size)
Definition: runtime/Mem.h:131
[Example Third Party Allocator]
Definition: runtime/Mem.h:68
T * getLocal()
Definition: PerThreadStorage.h:128
const_pointer address(const_reference val) const
Definition: runtime/Mem.h:998
const Ty & const_reference
Definition: runtime/Mem.h:981
Keep a reference to an external allocator.
Definition: runtime/Mem.h:947
void * allocate(size_t size)
Definition: runtime/Mem.h:684
pointer address(reference val) const
Definition: runtime/Mem.h:898
void * allocate(size_t size)
Definition: runtime/Mem.h:74
const void * const_pointer
Definition: runtime/Mem.h:936
void deallocate(void *ptr)
Definition: runtime/Mem.h:277
bool operator!=(const Pow_2_BlockAllocator< T1 > &rhs) const
Definition: runtime/Mem.h:920
void construct(U *p, Args &&...args) const
Definition: runtime/Mem.h:1013
SerialNumaAllocator()
Definition: runtime/Mem.h:1046
void value_type
Definition: runtime/Mem.h:956
pointer address(reference val) const
Definition: runtime/Mem.h:751
void * allocate(size_t size)
Definition: runtime/Mem.h:258
SerialNumaAllocator< Other > other
Definition: runtime/Mem.h:1043
void pageIn(void *buf, size_t len, size_t stride)
Forces the given block to be paged into physical memory.
BumpHeap()
Definition: runtime/Mem.h:382
Ty & reference
Definition: runtime/Mem.h:980
bool operator==(const ExternalHeapAllocator< T1, A1 > &rhs) const
Definition: runtime/Mem.h:1030
size_type max_size() const noexcept
Definition: runtime/Mem.h:917
Definition: runtime/Mem.h:195
pointer address(reference val) const
Definition: runtime/Mem.h:996
Apply a lock to a heap.
Definition: runtime/Mem.h:106
Ty value_type
Definition: runtime/Mem.h:738
void * allocate(size_t size)
Definition: runtime/Mem.h:112
Definition: runtime/Mem.h:603
static Derived * getInstance(void)
Definition: runtime/Mem.h:530
void * allocate(size_t size)
Definition: runtime/Mem.h:578
void deallocate(void *ptr)
Definition: runtime/Mem.h:155
void unlock() const
Definition: SimpleLock.h:68
size_t allocSize()
Definition: PageAlloc.cpp:69
Definition: runtime/Mem.h:72
void deallocate(void *)
Definition: runtime/Mem.h:355
void construct(U *p, Args &&...args) const
Definition: runtime/Mem.h:911
size_t size_type
Definition: runtime/Mem.h:874
size_t size_type
Definition: runtime/Mem.h:952
void construct(U *p, Args &&...args) const
Definition: runtime/Mem.h:766
Ty & reference
Definition: runtime/Mem.h:878
Definition: runtime/Mem.h:785
void deallocateBlock(void *ptr, const size_t allocSize)
Definition: runtime/Mem.h:847
ptrdiff_t difference_type
Definition: runtime/Mem.h:875
bool operator!=(const ExternalHeapAllocator< T1, A1 > &rhs) const
Definition: runtime/Mem.h:1025
ExternalHeapAllocator(HeapTy *a) noexcept
Definition: runtime/Mem.h:989
BumpWithMallocHeap()
Definition: runtime/Mem.h:471
pointer allocate(size_type size)
Definition: runtime/Mem.h:754
ptrdiff_t difference_type
Definition: runtime/Mem.h:977
void pagePoolFree(void *)
Definition: PagePool.cpp:48
void pagePreAlloc(int numpages)
Preallocate numpages large pages for each thread.
void * allocate(size_t size)
Definition: runtime/Mem.h:208
size_t size_type
Definition: runtime/Mem.h:732
Definition: runtime/Mem.h:864
~FreeListHeap()
Definition: runtime/Mem.h:206
void deallocate(void *ptr)
Definition: runtime/Mem.h:221
unsigned int activeThreads
Definition: Threads.cpp:26
This implements a bump pointer though chunks of memory.
Definition: runtime/Mem.h:360
Definition: runtime/Mem.h:560
void preAlloc_impl(unsigned num)
Memory management functionality.
Definition: PreAlloc.cpp:24
void clear()
Definition: runtime/Mem.h:243
const_pointer address(const_reference val) const
Definition: runtime/Mem.h:900
ptrdiff_t difference_type
Definition: runtime/Mem.h:934
~BlockHeap()
Definition: runtime/Mem.h:346
static OwnerTaggedHeap * owner(void *ptr)
Definition: runtime/Mem.h:179
FixedSizeHeap(size_t size)
Definition: runtime/Mem.h:646
const Ty * const_pointer
Definition: runtime/Mem.h:735
void destroy(pointer ptr) const
Definition: runtime/Mem.h:770
Definition: runtime/Mem.h:332
Definition: runtime/Mem.h:110
ptrdiff_t difference_type
Definition: runtime/Mem.h:953
Main scalable allocator in Galois.
Definition: runtime/Mem.h:642
void deallocate(void *ptr)
Definition: runtime/Mem.h:520
This implements a bump pointer though chunks of memory that falls back to malloc if the source heap c...
Definition: runtime/Mem.h:447
Allow looking up parent heap pointers.
Definition: runtime/Mem.h:164
void * alloc()
Definition: PerThreadStorage.cpp:42
void * allocate(size_t GALOIS_USED_ONLY_IN_DEBUG(size))
Definition: runtime/Mem.h:348
void deallocate(void *ptr)
Definition: runtime/Mem.h:119
void * pointer
Definition: runtime/Mem.h:954
void * pointer
Definition: runtime/Mem.h:710
void destroy(pointer ptr) const
Definition: runtime/Mem.h:1017
Scalable variable-size allocations.
Definition: runtime/Mem.h:637
Maintain a freelist.
Definition: runtime/Mem.h:186
void clear()
Definition: runtime/Mem.h:197
Definition: runtime/Mem.h:127
void * allocate(size_t)
Definition: runtime/Mem.h:518
Ty & reference
Definition: runtime/Mem.h:736
ExternalHeapAllocator(const ExternalHeapAllocator< T1, HeapTy > &rhs) noexcept
Definition: runtime/Mem.h:992
void * allocate(size_t size)
Definition: runtime/Mem.h:394
size_type max_size() const noexcept
Definition: runtime/Mem.h:772
Definition: runtime/Mem.h:129
Ty value_type
Definition: runtime/Mem.h:982
LAptr largeMallocInterleaved(size_t bytes, unsigned numThreads)
Definition: NumaMem.cpp:150
ThreadPrivateHeap< FreeListHeap< BumpHeap< SystemHeap > > > SizedHeap
[FixedSizeAllocator example]
Definition: runtime/Mem.h:609
bool operator!=(const FixedSizeAllocator< T1 > &rhs) const
Definition: runtime/Mem.h:775
ThreadPrivateHeap()
Definition: runtime/Mem.h:88
bool operator==(const Pow_2_BlockAllocator< T1 > &rhs) const
Definition: runtime/Mem.h:925
void lock() const
Definition: SimpleLock.h:55
Pow_2_BlockAllocator< Other > other
Definition: runtime/Mem.h:941
unsigned size() const
Definition: PerThreadStorage.h:159
void deallocate(void *ptr)
Definition: runtime/Mem.h:174
void * pagePoolAlloc()
Low level page pool (individual pages, use largeMalloc for large blocks)
Definition: PagePool.cpp:41
const Ty & const_reference
Definition: runtime/Mem.h:879
void deallocate(void *ptr)
Definition: runtime/Mem.h:76
static Header * getHeader(void *ptr)
Definition: runtime/Mem.h:157
size_t size_type
Definition: runtime/Mem.h:976
Definition: gIO.h:121
SimpleLock is a spinlock.
Definition: SimpleLock.h:36
size_t size_type
Definition: runtime/Mem.h:933
[Example Third Party Allocator]
Definition: runtime/Mem.h:82
~BumpWithMallocHeap()
Definition: runtime/Mem.h:473
Ty value_type
Definition: runtime/Mem.h:880
void deallocate(pointer ptr, size_type GALOIS_USED_ONLY_IN_DEBUG(len))
Definition: runtime/Mem.h:760
bool operator==(const FixedSizeHeap &rhs) const
Definition: runtime/Mem.h:670
Definition: runtime/Mem.h:741
void * allocate(size_t size)
Definition: runtime/Mem.h:148
std::unique_ptr< void, internal::largeFreer > LAptr
Definition: NumaMem.h:39
void clear()
Definition: runtime/Mem.h:98
bool operator!=(const FixedSizeHeap &rhs) const
Definition: runtime/Mem.h:666
void * allocate(size_t size)
Definition: runtime/Mem.h:655
~ThreadPrivateHeap()
Definition: runtime/Mem.h:89
void value_type
Definition: runtime/Mem.h:937
FixedSizeAllocator< Other > other
Definition: runtime/Mem.h:742
static void print(const Args &...args)
Definition: gIO.h:115
const Ty & const_reference
Definition: runtime/Mem.h:737
void * allocate(size_t size, size_t &allocated)
Allocates size bytes but may fail.
Definition: runtime/Mem.h:415
size_t size_type
Definition: runtime/Mem.h:708
FixedSizeAllocator< Other > other
Definition: runtime/Mem.h:716
Ty * pointer
Definition: runtime/Mem.h:734
const Ty * const_pointer
Definition: runtime/Mem.h:979
void pageInReadOnly(void *buf, size_t len, size_t stride)
Forces the given readonly block to be paged into physical memory.
T * getRemote(unsigned int thread)
Definition: PerThreadStorage.h:149
const void * const_pointer
Definition: runtime/Mem.h:711
void deallocate(void *ptr)
Definition: runtime/Mem.h:137
void * allocate(size_t size)
Definition: runtime/Mem.h:488
int numNumaAllocForNode(unsigned nodeid)
Returns total small pages allocated by OS on a NUMA node.
void deallocate(void *)
Definition: runtime/Mem.h:505
Ty * pointer
Definition: runtime/Mem.h:978
void deallocate(void *ptr)
Definition: runtime/Mem.h:585
A fixed size block allocator.
Definition: runtime/Mem.h:703
bool operator==(const FixedSizeAllocator< T1 > &rhs) const
Definition: runtime/Mem.h:780
FixedSizeAllocator() noexcept
Definition: runtime/Mem.h:745
FixedSizeAllocator(const FixedSizeAllocator< U > &) noexcept
Definition: runtime/Mem.h:748
~BumpHeap()
Definition: runtime/Mem.h:384
void construct(pointer ptr, const_reference val) const
Definition: runtime/Mem.h:1008
Pow_2_BlockAllocator() noexcept
Definition: runtime/Mem.h:889
Pow_2_BlockHeap * heap
Definition: runtime/Mem.h:887
ExternalHeapAllocator< Other, HeapTy > other
Definition: runtime/Mem.h:960
void clear()
Definition: runtime/Mem.h:475
void deallocate(void *ptr)
Definition: runtime/Mem.h:664