SST  6.1.0
StructuralSimulationToolkit
mempool.h
1 // Copyright 2009-2016 Sandia Corporation. Under the terms
2 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2016, Sandia Corporation
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_MEMPOOL_H
13 #define SST_CORE_MEMPOOL_H
14 
15 #include <list>
16 #include <deque>
17 
18 #include <cstddef>
19 #include <cstdlib>
20 #include <cstring>
21 #include <cinttypes>
22 #include <cstdint>
23 #include <sys/mman.h>
24 
25 #include "sst/core/threadsafe.h"
26 
27 namespace SST {
28 namespace Core {
29 
30 /**
31  * Simple Memory Pool class
32  */
33 class MemPool
34 {
35  template <typename LOCK_t>
36  class FreeList {
37  LOCK_t mtx;
38  std::vector<void*> list;
39  public:
40  inline void insert(void *ptr) {
41  std::lock_guard<LOCK_t> lock(mtx);
42  list.push_back(ptr);
43  }
44 
45  inline void* try_remove() {
46  std::lock_guard<LOCK_t> lock(mtx);
47  if ( list.empty() ) return NULL;
48  void *p = list.back();
49  list.pop_back();
50  return p;
51  }
52 
53  size_t size() const { return list.size(); }
54  };
55 
56 
57 public:
58  /** Create a new Memory Pool.
59  * @param elementSize - Size of each Element
60  * @param initialSize - Size of the memory pool (in bytes)
61  */
62  MemPool(size_t elementSize, size_t initialSize=(2<<20)) :
63  numAlloc(0), numFree(0),
64  elemSize(elementSize), arenaSize(initialSize),
65  allocating(false)
66  {
67  allocPool();
68  }
69 
70  ~MemPool()
71  {
72  for ( std::list<uint8_t*>::iterator i = arenas.begin() ; i != arenas.end() ; ++i ) {
73  ::free(*i);
74  }
75  }
76 
77  /** Allocate a new element from the memory pool */
78  inline void* malloc()
79  {
80  void *ret = freeList.try_remove();
81  while ( !ret ) {
82  bool ok = allocPool();
83  if ( !ok ) return NULL;
84  _mm_pause();
85  ret = freeList.try_remove();
86  }
87  ++numAlloc;
88  return ret;
89  }
90 
91  /** Return an element to the memory pool */
92  inline void free(void *ptr)
93  {
94  // TODO: Make sure this is in one of our arenas
95  freeList.insert(ptr);
96 // #ifdef __SST_DEBUG_EVENT_TRACKING__
97 // *((uint64_t*)ptr) = 0xFFFFFFFFFFFFFFFF;
98 // #endif
99  ++numFree;
100  }
101 
102  /**
103  Approximates the current memory usage of the mempool. Some
104  overheads are not taken into account.
105  */
106  uint64_t getBytesMemUsed() {
107  uint64_t bytes_in_arenas = arenas.size() * arenaSize;
108  uint64_t bytes_in_free_list = freeList.size() * sizeof(void*);
109  return bytes_in_arenas + bytes_in_free_list;
110  }
111 
112  uint64_t getUndeletedEntries() {
113  return numAlloc - numFree;
114  }
115 
116  /** Counter: Number of times elements have been allocated */
117  std::atomic<uint64_t> numAlloc;
118  /** Counter: Number times elements have been freed */
119  std::atomic<uint64_t> numFree;
120 
121  size_t getArenaSize() const { return arenaSize; }
122  size_t getElementSize() const { return elemSize; }
123 
124  const std::list<uint8_t*>& getArenas() { return arenas; }
125 
126 private:
127 
128  bool allocPool()
129  {
130  /* If already in progress, return */
131  if ( allocating.exchange(1, std::memory_order_acquire) ) {
132  return true;
133  }
134 
135  uint8_t *newPool = (uint8_t*)mmap(0, arenaSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
136  if ( MAP_FAILED == newPool ) {
137  allocating.store(0, std::memory_order_release);
138  return false;
139  }
140  std::memset(newPool, 0xFF, arenaSize);
141  arenas.push_back(newPool);
142  size_t nelem = arenaSize / elemSize;
143  for ( size_t i = 0 ; i < nelem ; i++ ) {
144  uint64_t* ptr = (uint64_t*)(newPool + (elemSize*i));
145 // #ifdef __SST_DEBUG_EVENT_TRACKING__
146 // *ptr = 0xFFFFFFFFFFFFFFFF;
147 // #endif
148  freeList.insert(ptr);
149  // freeList.push_back(newPool + (elemSize*i));
150  }
151  allocating.store(0, std::memory_order_release);
152  return true;
153  }
154 
155  size_t elemSize;
156  size_t arenaSize;
157 
158  std::atomic<unsigned int> allocating;
159  FreeList<ThreadSafe::Spinlock> freeList;
160  std::list<uint8_t*> arenas;
161 
162 };
163 
164 }
165 }
166 
167 #endif
Definition: action.cc:17
MemPool(size_t elementSize, size_t initialSize=(2<< 20))
Create a new Memory Pool.
Definition: mempool.h:62
void free(void *ptr)
Return an element to the memory pool.
Definition: mempool.h:92
void * malloc()
Allocate a new element from the memory pool.
Definition: mempool.h:78
std::atomic< uint64_t > numAlloc
Counter: Number of times elements have been allocated.
Definition: mempool.h:117
uint64_t getBytesMemUsed()
Approximates the current memory usage of the mempool.
Definition: mempool.h:106
std::atomic< uint64_t > numFree
Counter: Number times elements have been freed.
Definition: mempool.h:119
Simple Memory Pool class.
Definition: mempool.h:33