SST  11.0.0
StructuralSimulationToolkit
activity.h
1 // Copyright 2009-2021 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2021, NTESS
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 
13 #ifndef SST_CORE_ACTIVITY_H
14 #define SST_CORE_ACTIVITY_H
15 
16 #include "sst/core/sst_types.h"
17 #include "sst/core/warnmacros.h"
18 
19 #include "sst/core/serialization/serializable.h"
20 
21 #include "sst/core/output.h"
22 #include "sst/core/mempool.h"
23 
24 #include <unordered_map>
25 #include <cinttypes>
26 #include <cstring>
27 
28 #include <errno.h>
29 
30 // Default Priority Settings
31 #define STOPACTIONPRIORITY 01
32 #define THREADSYNCPRIORITY 20
33 #define SYNCPRIORITY 25
34 #define INTROSPECTPRIORITY 30
35 #define CLOCKPRIORITY 40
36 #define EVENTPRIORITY 50
37 #define MEMEVENTPRIORITY 50
38 #define BARRIERPRIORITY 75
39 #define ONESHOTPRIORITY 80
40 #define STATISTICCLOCKPRIORITY 85
41 #define FINALEVENTPRIORITY 98
42 #define EXITPRIORITY 99
43 
44 #define SST_ENFORCE_EVENT_ORDERING
45 
46 extern int main(int argc, char **argv);
47 
48 
49 namespace SST {
50 
51 /** Base class for all Activities in the SST Event Queue */
53 public:
54  Activity() {}
55  virtual ~Activity() {}
56 
57  /** Function which will be called when the time for this Activity comes to pass. */
58  virtual void execute(void) = 0;
59 
60 #ifdef SST_ENFORCE_EVENT_ORDERING
61 
62  /** To use with STL container classes. */
64  public:
65  /** Compare based off pointers */
66  inline bool operator()(const Activity* lhs, const Activity* rhs) const {
67  if ( lhs->delivery_time == rhs->delivery_time ) {
68  if ( lhs->priority == rhs->priority ) {
69  /* TODO: Handle 64-bit wrap-around */
70  return lhs->enforce_link_order > rhs->enforce_link_order;
71  } else {
72  return lhs->priority > rhs->priority;
73  }
74  } else {
75  return lhs->delivery_time > rhs->delivery_time;
76  }
77  }
78 
79  /** Compare based off references */
80  inline bool operator()(const Activity& lhs, const Activity& rhs) const {
81  if ( lhs.delivery_time == rhs.delivery_time ) {
82  if ( lhs.priority == rhs.priority ) {
83  /* TODO: Handle 64-bit wrap-around */
84  return lhs.enforce_link_order > rhs.enforce_link_order;
85  } else {
86  return lhs.priority > rhs.priority;
87  }
88  } else {
89  return lhs.delivery_time > rhs.delivery_time;
90  }
91  }
92  };
93 
94  /** To use with STL priority queues, that order in reverse. */
96  public:
97  /** Compare based off pointers */
98  inline bool operator()(const Activity* lhs, const Activity* rhs) const {
99  if ( lhs->delivery_time == rhs->delivery_time ) {
100  if ( lhs->priority == rhs->priority ) {
101  if ( lhs->enforce_link_order == rhs->enforce_link_order ) {
102  /* TODO: Handle 64-bit wrap-around */
103  return lhs->queue_order > rhs->queue_order;
104  }
105  else {
106  return lhs->enforce_link_order > rhs->enforce_link_order;
107  }
108  } else {
109  return lhs->priority > rhs->priority;
110  }
111  } else {
112  return lhs->delivery_time > rhs->delivery_time;
113  }
114  }
115 
116  /** Compare based off references */
117  inline bool operator()(const Activity& lhs, const Activity& rhs) const {
118  if ( lhs.delivery_time == rhs.delivery_time ) {
119  if ( lhs.priority == rhs.priority ) {
120  if ( lhs.enforce_link_order == rhs.enforce_link_order ) {
121  return lhs.queue_order > rhs.queue_order;
122  }
123  else {
124  return lhs.enforce_link_order > rhs.enforce_link_order;
125  }
126  } else {
127  return lhs.priority > rhs.priority;
128  }
129  } else {
130  return lhs.delivery_time > rhs.delivery_time;
131  }
132  }
133  };
134 
135 #endif
136 
137  /** Comparator class to use with STL container classes. */
139  public:
140  /** Compare based off pointers */
141  inline bool operator()(const Activity* lhs, const Activity* rhs) {
142  if (lhs->delivery_time == rhs->delivery_time ) return lhs->priority < rhs->priority;
143  else return lhs->delivery_time < rhs->delivery_time;
144  }
145 
146  /** Compare based off references */
147  inline bool operator()(const Activity& lhs, const Activity& rhs) {
148  if (lhs.delivery_time == rhs.delivery_time ) return lhs.priority < rhs.priority;
149  else return lhs.delivery_time < rhs.delivery_time;
150  }
151  };
152 
153  /** To use with STL priority queues, that order in reverse. */
155  public:
156  /** Compare based off pointers */
157  inline bool operator()(const Activity* lhs, const Activity* rhs) const {
158  if ( lhs->delivery_time == rhs->delivery_time ) {
159  if ( lhs->priority == rhs->priority ) {
160  /* TODO: Handle 64-bit wrap-around */
161  return lhs->queue_order > rhs->queue_order;
162  } else {
163  return lhs->priority > rhs->priority;
164  }
165  } else {
166  return lhs->delivery_time > rhs->delivery_time;
167  }
168  }
169 
170  /** Compare based off references */
171  inline bool operator()(const Activity& lhs, const Activity& rhs) const {
172  if ( lhs.delivery_time == rhs.delivery_time ) {
173  if ( lhs.priority == rhs.priority ) {
174  /* TODO: Handle 64-bit wrap-around */
175  return lhs.queue_order > rhs.queue_order;
176  } else {
177  return lhs.priority > rhs.priority;
178  }
179  } else {
180  return lhs.delivery_time > rhs.delivery_time;
181  }
182  }
183  };
184 
185  /** Comparator class to use with STL container classes. */
186  class less_time {
187  public:
188  /** Compare pointers */
189  inline bool operator()(const Activity* lhs, const Activity* rhs) const {
190  return lhs->delivery_time < rhs->delivery_time;
191  }
192 
193  /** Compare references */
194  inline bool operator()(const Activity& lhs, const Activity& rhs) const {
195  return lhs.delivery_time < rhs.delivery_time;
196  }
197  };
198 
199  /** Set the time for which this Activity should be delivered */
200  void setDeliveryTime(SimTime_t time) {
201  delivery_time = time;
202  }
203 
204  /** Return the time at which this Activity will be delivered */
205  inline SimTime_t getDeliveryTime() const {
206  return delivery_time;
207  }
208 
209  /** Return the Priority of this Activity */
210  inline int getPriority() const {
211  return priority;
212  }
213 
214  /** Generic print-print function for this Activity.
215  * Subclasses should override this function.
216  */
217  virtual void print(const std::string& header, Output &out) const {
218  out.output("%s Generic Activity to be delivered at %" PRIu64 " with priority %d\n",
219  header.c_str(), delivery_time, priority);
220  }
221 
222 #ifdef __SST_DEBUG_EVENT_TRACKING__
223  virtual void printTrackingInfo(const std::string& header, Output &out) const {
224  }
225 #endif
226 
227  /** Set a new Queue order */
228  void setQueueOrder(uint64_t order) {
229  queue_order = order;
230  }
231 
232 #ifdef USE_MEMPOOL
233  /** Allocates memory from a memory pool for a new Activity */
234  void* operator new(std::size_t size) noexcept
235  {
236  /* 1) Find memory pool
237  * 1.5) If not found, create new
238  * 2) Alloc item from pool
239  * 3) Append PoolID to item, increment pointer
240  */
241  Core::MemPool *pool = nullptr;
242  size_t nPools = memPools.size();
243  std::thread::id tid = std::this_thread::get_id();
244  for ( size_t i = 0 ; i < nPools ; i++ ) {
245  PoolInfo_t &p = memPools[i];
246  if ( p.tid == tid && p.size == size ) {
247  pool = p.pool;
248  break;
249  }
250  }
251  if ( nullptr == pool ) {
252  /* Still can't find it, alloc a new one */
253  pool = new Core::MemPool(size+sizeof(PoolData_t));
254 
255  std::lock_guard<std::mutex> lock(poolMutex);
256  memPools.emplace_back(tid, size, pool);
257  }
258 
259  PoolData_t *ptr = (PoolData_t*)pool->malloc();
260  if ( !ptr ) {
261  fprintf(stderr, "Memory Pool failed to allocate a new object. Error: %s\n", strerror(errno));
262  return nullptr;
263  }
264  *ptr = pool;
265  return (void*)(ptr+1);
266  }
267 
268 
269  /** Returns memory for this Activity to the appropriate memory pool */
270  void operator delete(void* ptr)
271  {
272  /* 1) Decrement pointer
273  * 2) Determine Pool Pointer
274  * 2b) Set Pointer field to nullptr to allow tracking
275  * 3) Return to pool
276  */
277  PoolData_t *ptr8 = ((PoolData_t*)ptr) - 1;
278  Core::MemPool* pool = *ptr8;
279  *ptr8 = nullptr;
280 
281  pool->free(ptr8);
282  }
283  void operator delete(void* ptr, std::size_t UNUSED(sz)){
284  /* 1) Decrement pointer
285  * 2) Determine Pool Pointer
286  * 2b) Set Pointer field to nullptr to allow tracking
287  * 3) Return to pool
288  */
289  PoolData_t *ptr8 = ((PoolData_t*)ptr) - 1;
290  Core::MemPool* pool = *ptr8;
291  *ptr8 = nullptr;
292 
293  pool->free(ptr8);
294  };
295 
296  static void getMemPoolUsage(uint64_t& bytes, uint64_t& active_activities) {
297  bytes = 0;
298  active_activities = 0;
299  for ( auto && entry : Activity::memPools ) {
300  bytes += entry.pool->getBytesMemUsed();
301  active_activities += entry.pool->getUndeletedEntries();
302  }
303  }
304 
305  static void printUndeletedActivities(const std::string& header, Output &out, SimTime_t before = MAX_SIMTIME_T) {
306  for ( auto && entry : Activity::memPools ) {
307  const std::list<uint8_t*>& arenas = entry.pool->getArenas();
308  size_t arenaSize = entry.pool->getArenaSize();
309  size_t elemSize = entry.pool->getElementSize();
310  size_t nelem = arenaSize / elemSize;
311  for ( auto iter = arenas.begin(); iter != arenas.end(); ++iter ) {
312  for ( size_t j = 0; j < nelem; j++ ) {
313  PoolData_t* ptr = (PoolData_t*)((*iter) + (elemSize*j));
314  if ( *ptr != nullptr ) {
315  Activity* act = (Activity*)(ptr + 1);
316  if ( act->delivery_time <= before ) {
317  act->print(header, out);
318 #ifdef __SST_DEBUG_EVENT_TRACKING__
319  act->printTrackingInfo(header + " ", out);
320 #endif
321  }
322  }
323  }
324  }
325  }
326  }
327 
328 #endif
329 
330  // /* Serializable interface methods */
331  // void serialize_order(serializer &ser);
332 
333 
334 
335 
336 protected:
337  /** Set the priority of the Activity */
338  void setPriority(int priority) {
339  this->priority = priority;
340  }
341 
342  // Function used by derived classes to serialize data members.
343  // This class is not serializable, because not all class that
344  // inherit from it need to be serializable.
345  void serialize_order(SST::Core::Serialization::serializer &ser) override {
346  ser & queue_order;
347  ser & delivery_time;
348  ser & priority;
349 #ifdef SST_ENFORCE_EVENT_ORDERING
350  ser & enforce_link_order;
351 #endif
352  }
353 
354 #ifdef SST_ENFORCE_EVENT_ORDERING
355  int32_t enforce_link_order;
356 #endif
357 
358 private:
359  uint64_t queue_order;
360  SimTime_t delivery_time;
361  int priority;
362 #ifdef USE_MEMPOOL
363  friend int ::main(int argc, char **argv);
364  /* Defined in event.cc */
365  typedef Core::MemPool* PoolData_t;
366  struct PoolInfo_t {
367  std::thread::id tid;
368  size_t size;
369  Core::MemPool *pool;
370  PoolInfo_t(std::thread::id tid, size_t size, Core::MemPool *pool) : tid(tid), size(size), pool(pool)
371  { }
372  };
373  static std::mutex poolMutex;
374  static std::vector<PoolInfo_t> memPools;
375 #endif
376 };
377 
378 
379 } //namespace SST
380 
381 
382 #endif // SST_CORE_ACTIVITY_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:54
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:35
Comparator class to use with STL container classes.
Definition: activity.h:138
void setDeliveryTime(SimTime_t time)
Set the time for which this Activity should be delivered.
Definition: activity.h:200
void setQueueOrder(uint64_t order)
Set a new Queue order.
Definition: activity.h:228
bool operator()(const Activity *lhs, const Activity *rhs) const
Compare pointers.
Definition: activity.h:189
Base class for all Activities in the SST Event Queue.
Definition: activity.h:52
To use with STL container classes.
Definition: activity.h:63
bool operator()(const Activity &lhs, const Activity &rhs) const
Compare based off references.
Definition: activity.h:171
virtual void execute(void)=0
Function which will be called when the time for this Activity comes to pass.
bool operator()(const Activity *lhs, const Activity *rhs) const
Compare based off pointers.
Definition: activity.h:98
void free(void *ptr)
Return an element to the memory pool.
Definition: mempool.h:91
bool operator()(const Activity *lhs, const Activity *rhs) const
Compare based off pointers.
Definition: activity.h:66
Definition: serializable.h:109
bool operator()(const Activity &lhs, const Activity &rhs)
Compare based off references.
Definition: activity.h:147
void * malloc()
Allocate a new element from the memory pool.
Definition: mempool.h:77
bool operator()(const Activity &lhs, const Activity &rhs) const
Compare references.
Definition: activity.h:194
void setPriority(int priority)
Set the priority of the Activity.
Definition: activity.h:338
SimTime_t getDeliveryTime() const
Return the time at which this Activity will be delivered.
Definition: activity.h:205
bool operator()(const Activity *lhs, const Activity *rhs) const
Compare based off pointers.
Definition: activity.h:157
void output(uint32_t line, const char *file, const char *func, const char *format,...) const
Output the message with formatting as specified by the format parameter.
Definition: output.h:186
To use with STL priority queues, that order in reverse.
Definition: activity.h:95
bool operator()(const Activity *lhs, const Activity *rhs)
Compare based off pointers.
Definition: activity.h:141
virtual void print(const std::string &header, Output &out) const
Generic print-print function for this Activity.
Definition: activity.h:217
int getPriority() const
Return the Priority of this Activity.
Definition: activity.h:210
bool operator()(const Activity &lhs, const Activity &rhs) const
Compare based off references.
Definition: activity.h:80
Simple Memory Pool class.
Definition: mempool.h:32
To use with STL priority queues, that order in reverse.
Definition: activity.h:154
Comparator class to use with STL container classes.
Definition: activity.h:186
bool operator()(const Activity &lhs, const Activity &rhs) const
Compare based off references.
Definition: activity.h:117