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