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