ROSS
tw-eventq.h
Go to the documentation of this file.
1 #ifndef INC_tw_eventq_h
2 #define INC_tw_eventq_h
3 
4 #define ROSS_DEBUG 0
5 
6 #include <ross.h>
7 
8 /**
9  * debug assitant fuction
10  */
11 static inline void
13 {
14 #if ROSS_DEBUG
15  tw_event *next;
16  tw_event *last;
17 
18  unsigned int cnt;
19 
20  cnt = 0;
21  next = q->head;
22  last = NULL;
23 
24  while(next)
25  {
26  cnt++;
27 
28  if(next->prev != last)
29  tw_error(TW_LOC, "Prev pointer not correct!");
30 
31  last = next;
32  next = next->next;
33  }
34 
35  if(q->tail != last)
36  tw_error(TW_LOC, "Tail pointer not correct!");
37 
38  if(cnt != q->size)
39  tw_error(TW_LOC, "Size not correct!");
40 #else
41  (void)q; // avoid "unused parameter" warning
42 #endif
43 }
44 
45 /**
46  * push the contents of one list onto another??
47  */
48 static inline void
50 {
51  tw_pe *pe;
52  tw_event *e;
53  tw_event *cev;
54  tw_event *next;
55 
56  tw_eventq_debug(q);
57 
58  t->next = q->head;
59 
60  if(q->head)
61  q->head->prev = t;
62 
63  q->head = h;
64  q->head->prev = NULL;
65 
66  if(!q->tail)
67  q->tail = t;
68 
69  q->size += cnt;
70 
71  // iterate through list to collect sent events
72  // go in reverse to ensure correct commit order
73  e = t;
74  t = t->next;
75  while(1)
76  {
77  if (g_st_ev_trace == COMMIT_TRACE) // doesn't rely on commit function existing, so should be outside of commit function check
79  tw_lp * clp = e->dest_lp;
80  if (*clp->type->commit) {
81  (*clp->type->commit)(clp->cur_state, &e->cv, tw_event_data(e), clp);
82  }
84 
85  if (e->delta_buddy) {
86  tw_clock start = tw_clock_read();
88  g_tw_pe->stats.s_buddy += (tw_clock_read() - start);
89  e->delta_buddy = 0;
90  }
91 
92  pe = e->dest_lp->pe;
93  // have to reclaim non-cancelled remote events from hash table
94  if(e->event_id && e->state.remote)
95  tw_hash_remove(pe->hash_t, e, e->send_pe);
96 
97  if(e->caused_by_me)
98  {
99  cev = next = e->caused_by_me;
100 
101  while(cev)
102  {
103  next = cev->cause_next;
104  cev->cause_next = NULL;
105 
106  if(cev->state.owner == TW_pe_sevent_q)
107  tw_event_free(cev->src_lp->pe, cev);
108 
109  cev = next;
110  }
111 
112  e->caused_by_me = NULL;
113  e->state.owner = TW_pe_free_q;
114  }
115  if (e == h) {
116  break;
117  }
118  e = e->prev;
119  }
120 
121  tw_eventq_debug(q);
122 }
123 
124 /**
125  * Given a list, move the portion of its contents that is older than GVT to
126  * the free list.
127  *
128  * Assumptions:
129  * - The provided q is not the free_q
130  * - The head of the list has the maximum time stamp in the list. Therefore,
131  * if the head is older than GVT, everything in the list is as well.
132  */
133 static inline void
135 {
136  tw_stime gvt = pe->GVT;
137 
138  tw_event *h = q->head;
139  tw_event *t = q->tail;
140 
141  int cnt;
142 
143  /* Nothing to collect from this event list? */
144  if (!t || (TW_STIME_CMP(t->recv_ts, gvt) >= 0))
145  return;
146 
147  if (TW_STIME_CMP(h->recv_ts, gvt) < 0)
148  {
149  /* Everything in the queue can be collected */
150  tw_eventq_push_list(&pe->free_q, h, t, q->size);
151  q->head = q->tail = NULL;
152  q->size = 0;
153  } else {
154  /* Only some of the list can be collected. We'll wind up
155  * with at least one event being collected and at least
156  * another event staying behind in the eventq structure so
157  * we can really optimize this list splicing operation for
158  * these conditions.
159  */
160  tw_event *n;
161 
162  /* Search the leading part of the list... */
163  for (h = t->prev, cnt = 1; h && (TW_STIME_CMP(h->recv_ts, gvt) < 0); cnt++)
164  h = h->prev;
165 
166  /* t isn't eligible for collection; its the new head */
167  n = h;
168 
169  /* Back up one cell, we overshot where to cut the list */
170  h = h->next;
171 
172  /* Cut h..t out of the event queue */
173  q->tail = n;
174  n->next = NULL;
175  q->size -= cnt;
176 
177  /* Free h..t (inclusive) */
178  tw_eventq_push_list(&pe->free_q, h, t, cnt);
179  }
180 }
181 
182 /**
183  * allocate a events into a given tw_eventq
184  */
185 static inline void
186 tw_eventq_alloc(tw_eventq * q, unsigned int cnt)
187 {
188  tw_event *event;
189  size_t event_len;
190  size_t align;
191 #ifdef ROSS_ALLOC_DEBUG
192  tw_event *event_prev = NULL;
193 #endif
194 
195  /* Construct a linked list of free events. We allocate
196  * the events such that they look like this in memory:
197  *
198  * ------------------
199  * | tw_event |
200  * | user_data |
201  * ------------------
202  * | tw_event |
203  * | user_data |
204  * ------------------
205  * ......
206  * ------------------
207  */
208 
209  align = ROSS_MAX(sizeof(double), sizeof(void*));
210  event_len = sizeof(tw_event) + g_tw_msg_sz;
211  if (event_len & (align - 1))
212  {
213  event_len += align - (event_len & (align - 1));
214  //tw_error(TW_LOC, "REALIGNING EVENT MEMORY!\n");
215  }
216  g_tw_event_msg_sz = event_len;
217 
218  // compute number of events needed for the network.
221  cnt += g_tw_gvt_threshold;
222 
223  q->size = cnt;
224  /* allocate one at a time so tools like valgrind can detect buffer
225  * overflows */
226 #ifdef ROSS_ALLOC_DEBUG
227  q->head = event = (tw_event *)tw_calloc(TW_LOC, "events", event_len, 1);
228  while (--cnt) {
229  event->state.owner = TW_pe_free_q;
230  event->prev = event_prev;
231  event_prev = event;
232  event->next = (tw_event *) tw_calloc(TW_LOC, "events", event_len, 1);
233  event = event->next;
234  }
235  event->prev = event_prev;
236 #else
237  /* alloc in one large block for performance/locality */
238  q->head = event = (tw_event *)tw_calloc(TW_LOC, "events", event_len, cnt);
239  while (--cnt) {
240  event->state.owner = TW_pe_free_q;
241  event->prev = (tw_event *) (((char *)event) - event_len);
242  event->next = (tw_event *) (((char *)event) + event_len);
243  event = event->next;
244  }
245  event->prev = (tw_event *) (((char *)event) - event_len);
246 #endif
247 
248  event->state.owner = TW_pe_free_q;
249  q->head->prev = event->next = NULL;
250  q->tail = event;
251 }
252 
253 /**
254  * push to tail of list
255  */
256 static inline void
258 {
259  tw_event *t = q->tail;
260 
261  tw_eventq_debug(q);
262 
263  e->next = NULL;
264  e->prev = t;
265  if (t)
266  t->next = e;
267  else
268  q->head = e;
269 
270  q->tail = e;
271  q->size++;
272 
273  tw_eventq_debug(q);
274 }
275 
276 /**
277  * peek to tail of list
278  */
279 static inline tw_event *
281 {
282  return q->tail;
283 }
284 
285 /**
286  * pop to tail of list
287  */
288 static inline tw_event *
290 {
291  tw_event *t = q->tail;
292  tw_event *p;
293 
294  tw_eventq_debug(q);
295 
296  if(!t)
297  return NULL;
298 
299  p = t->prev;
300 
301  if (p)
302  p->next = NULL;
303  else
304  q->head = NULL;
305 
306  q->tail = p;
307  q->size--;
308 
309  t->next = t->prev = NULL;
310 
311  tw_eventq_debug(q);
312 
313  return t;
314 }
315 
316 /**
317  * push to head of list
318  */
319 static inline void
321 {
322  tw_event *h = q->head;
323 
324  tw_eventq_debug(q);
325 
326  e->prev = NULL;
327  e->next = h;
328 
329  if (h)
330  h->prev = e;
331  else
332  q->tail = e;
333 
334  q->head = e;
335  q->size++;
336 
337  tw_eventq_debug(q);
338 }
339 
340 /**
341  * peek at head of list
342  */
343 static inline tw_event *
345 {
346  return q->head;
347 }
348 
349 /**
350  * pop from head of list
351  */
352 static inline tw_event *
354 {
355  tw_event *h = q->head;
356  tw_event *n;
357 
358  tw_eventq_debug(q);
359 
360  if(!h)
361  return NULL;
362 
363  n = h->next;
364 
365  if (n)
366  n->prev = NULL;
367  else
368  q->tail = NULL;
369 
370  q->head = n;
371  q->size--;
372 
373  h->next = h->prev = NULL;
374 
375  tw_eventq_debug(q);
376 
377  return h;
378 }
379 
380 /**
381  * delete an event from anywhere in the list
382  */
383 static inline void
385 {
386  tw_event *p = e->prev;
387  tw_event *n = e->next;
388 
389  tw_eventq_debug(q);
390 
391  if (p)
392  p->next = n;
393  else
394  q->head = n;
395 
396  if (n)
397  n->prev = p;
398  else
399  q->tail = p;
400 
401  e->next = e->prev = NULL;
402  q->size--;
403 
404  tw_eventq_debug(q);
405 }
406 
407 /**
408  * pop the entire list.
409  * After this operation, the size of the provided q is 0.
410  */
411 static inline tw_event *
413 {
414  tw_event *h = q->head;
415 
416  q->size = 0;
417  q->head = q->tail = NULL;
418 
419  return h;
420 }
421 
422 /**
423  * The purpose of this function is to be able to remove some
424  * part of a list.. could be all of list, from head to some inner
425  * buffer, or from some inner buffer to tail. I only care about the
426  * last case..
427  */
428 static inline void
430 {
431  tw_eventq_debug(q);
432 
433  if(h == q->head && t == q->tail)
434  {
435  q->size = 0;
436  q->head = q->tail = NULL;
437  return;
438  }
439 
440  if(h == q->head)
441  q->head = t->next;
442  else
443  h->prev->next = t->next;
444 
445  if(t == q->tail)
446  q->tail = h->prev;
447  else
448  t->next->prev = h->prev;
449 
450  q->size -= cnt;
451 
452  tw_eventq_debug(q);
453 }
454 
455 #endif
struct tw_event tw_event
Definition: ross-types.h:17
#define TW_LOC
Definition: ross-extern.h:164
void * delta_buddy
Delta memory from buddy allocator.
Definition: ross-types.h:275
unsigned long long g_tw_clock_rate
Definition: ross-global.c:98
tw_lp * dest_lp
Destination LP ID.
Definition: ross-types.h:280
double tw_stime
Definition: ross.h:150
tw_eventid event_id
Unique id assigned by src_lp->pe if remote.
Definition: ross-types.h:264
tw_event * head
Definition: ross-types.h:167
void tw_error(const char *file, int line, const char *fmt,...) NORETURN
Definition: tw-util.c:74
size_t g_tw_msg_sz
Definition: ross-global.c:33
tw_lptype * type
Type of this LP, including service callbacks.
Definition: ross-types.h:316
tw_statistics stats
per PE counters
Definition: ross-types.h:415
static tw_event * tw_eventq_peek(tw_eventq *q)
Definition: tw-eventq.h:280
unsigned int g_tw_gvt_threshold
Definition: ross-global.c:80
tw_stime recv_ts
Actual time to be received.
Definition: ross-types.h:282
static void tw_eventq_alloc(tw_eventq *q, unsigned int cnt)
Definition: tw-eventq.h:186
static void tw_eventq_delete_any(tw_eventq *q, tw_event *e)
Definition: tw-eventq.h:384
static tw_clock tw_clock_read(void)
Definition: aarch64.h:6
static void tw_event_free(tw_pe *, tw_event *)
void st_collect_event_data(tw_event *cev, double recv_rt)
Definition: st-event-trace.c:9
Holds the entire PE state.
Definition: ross-types.h:375
static tw_event * tw_eventq_shift(tw_eventq *q)
Definition: tw-eventq.h:353
tw_bf cv
Used by app during reverse computation.
Definition: ross-types.h:274
tw_event * prev
Definition: ross-types.h:252
tw_eventq free_q
Linked list of free tw_events.
Definition: ross-types.h:383
static void tw_eventq_push_list(tw_eventq *q, tw_event *h, tw_event *t, long cnt)
Definition: tw-eventq.h:49
unsigned int g_tw_net_device_size
Definition: ross-global.c:87
Event Stucture.
Definition: ross-types.h:250
#define TW_STIME_CMP(x, y)
Definition: ross.h:154
tw_clock s_buddy
Definition: ross-types.h:149
tw_event * next
Definition: ross-types.h:251
static tw_event * tw_eventq_pop_list(tw_eventq *q)
Definition: tw-eventq.h:412
void * hash_t
Array of incoming events from remote pes, Note: only necessary for distributed DSR.
Definition: ross-types.h:418
static void * tw_event_data(tw_event *event)
tw_event * cause_next
Next in parent's caused_by_me chain.
Definition: ross-types.h:262
static tw_event * tw_eventq_peek_head(tw_eventq *q)
Definition: tw-eventq.h:344
static void tw_eventq_fossil_collect(tw_eventq *q, tw_pe *pe)
Definition: tw-eventq.h:134
tw_event * caused_by_me
Start of event list caused by this event.
Definition: ross-types.h:261
In tw_pe.free_q.
Definition: ross-types.h:222
static tw_event * tw_eventq_pop(tw_eventq *q)
Definition: tw-eventq.h:289
commit_f commit
LP Commit event routine.
Definition: ross-types.h:92
static void tw_eventq_push(tw_eventq *q, tw_event *e)
Definition: tw-eventq.h:257
void buddy_free(void *ptr)
Definition: buddy.c:137
tw_peid send_pe
Definition: ross-types.h:284
static void tw_free_output_messages(tw_event *e, int print_message)
In tw_pe.sevent_q.
Definition: ross-types.h:221
tw_event * tail
Definition: ross-types.h:168
tw_pe * g_tw_pe
Definition: ross-global.c:75
struct tw_event::@0 state
static void tw_eventq_unshift(tw_eventq *q, tw_event *e)
Definition: tw-eventq.h:320
tw_pe * pe
Definition: ross-types.h:308
unsigned char remote
Indicates union addr is in 'remote' storage.
Definition: ross-types.h:271
tw_stime GVT
Global Virtual Time.
Definition: ross-types.h:403
tw_pe * pe
Definition: avl_tree.c:11
uint64_t tw_clock
Definition: aarch64.h:4
size_t g_tw_event_msg_sz
Definition: ross-global.c:43
tw_lp * src_lp
Sending LP ID.
Definition: ross-types.h:281
#define ROSS_MAX(a, b)
void * cur_state
Current application LP data.
Definition: ross-types.h:315
size_t size
Definition: ross-types.h:166
int g_st_ev_trace
Definition: st-event-trace.c:3
tw_event * tw_hash_remove(void *h, tw_event *event, long pe)
static void tw_eventq_debug(tw_eventq *q)
Definition: tw-eventq.h:12
void * tw_calloc(const char *file, int line, const char *for_who, size_t e_sz, size_t n)
Definition: tw-util.c:203
unsigned int g_tw_events_per_pe
Definition: ross-global.c:76
LP State Structure.
Definition: ross-types.h:304
static void tw_eventq_splice(tw_eventq *q, tw_event *h, tw_event *t, int cnt)
Definition: tw-eventq.h:429
unsigned char owner
Owner of the next/prev pointers; see tw_event_owner.
Definition: ross-types.h:268