PULSAR  2.0.0
Parallel Ultra-Light Systolic Array Runtime
 All Data Structures Files Functions Typedefs Enumerations Macros Groups
prt_thread.c
Go to the documentation of this file.
1 
11 #include "prt_thread.h"
12 
14 
23 prt_thread_t* prt_thread_new(int rank, int core, int agent_rank)
24 {
25  // Allocate the thread.
26  prt_thread_t *thread = (prt_thread_t*)malloc(sizeof(prt_thread_t));
27  prt_assert(thread != NULL, "malloc failed");
28 
29  // Initialize the thread.
30  thread->rank = rank;
31  thread->core = core;
32  thread->agent_rank = agent_rank;
33  thread->finished = 0;
34 
35  // Create the list of VDPs.
36  thread->vdps = icl_list_new();
37  prt_assert(thread->vdps != NULL, "icl_list_new failed");
38 
39  // Return the thread.
40  return thread;
41 }
42 
44 
50 {
51  // Destroy the list of VDPs.
52  int size = icl_list_size(thread->vdps);
53  prt_assert(size == 0, "destroying non-empty list");
54  int status = icl_list_destroy(thread->vdps, NULL);
55  prt_assert(status == 0, "icl_list_destroy failed");
56 
57  // Free the thread.
58  free(thread);
59 }
60 
62 
75 void* prt_thread_run(void *thrd)
76 {
77  prt_thread_t *thread = (prt_thread_t*)thrd;
78  // Set the trace rank, depending on the existence of the proxy.
79  int trace_rank = thread->vsa->proxy == NULL ? thread->rank : thread->rank+1;
80 
81  // Call the thread warmup function if set.
82  if (thread->vsa->thread_warmup_func != NULL)
83  thread->vsa->thread_warmup_func();
84 
85  // Barrier the threads.
86  svg_trace_start_cpu(trace_rank);
87  pthread_barrier_wait(&thread->vsa->barrier);
88  svg_trace_stop_cpu(trace_rank, -Azure);
89  double start = get_time_of_day();
90 
91  icl_list_t *node;
92  // WHILE the list of VDPs is not empty.
93  while ((node = icl_list_first(thread->vdps)) != NULL) {
94  // REPEAT.
95  do {
96  prt_vdp_t *vdp = (prt_vdp_t*)node->data;
97  // IF aggressive scheduling.
98  if (thread->vsa->config->vdp_scheduling
99  == PRT_VDP_SCHEDULING_AGGRESSIVE) {
100  // WHILE the inputs are ready AND the counter is NOT zero.
101  while (vdp->counter > 0 && prt_vdp_ready(vdp)) {
102  // Fire the VDP and decrement the counter.
103  svg_trace_start_cpu(trace_rank);
104  vdp->function(vdp);
105  svg_trace_stop_cpu(trace_rank, vdp->color);
106  vdp->counter--;
107  }
108  }
109  else if (thread->vsa->config->vdp_scheduling
110  == PRT_VDP_SCHEDULING_LAZY) {
111  // IF the inputs are ready AND the counter is NOT zero.
112  if (vdp->counter > 0 && prt_vdp_ready(vdp)) {
113  // Fire the VDP and decrement the counter.
114  svg_trace_start_cpu(trace_rank);
115  vdp->function(vdp);
116  svg_trace_stop_cpu(trace_rank, vdp->color);
117  vdp->counter--;
118  }
119  }
120  icl_list_t *prev = node;
121  node = icl_list_next(thread->vdps, node);
122  // IF the counter is zeroed.
123  if (vdp->counter == 0)
124  // Remove the VDP from the list
125  // Do not destroy the VDP itself.
126  icl_list_delete(thread->vdps, prev, NULL);
127  }
128  while (node != NULL);
129  // UNTIL the end of the list is reached.
130  }
131  // Signal completion.
132  thread->finished = 1;
133 
134  // Barrier the threads.
135  svg_trace_start_cpu(trace_rank);
136  pthread_barrier_wait(&thread->vsa->barrier);
137  svg_trace_stop_cpu(trace_rank, -Azure);
138 
139  // Return the time between the end of the first thread barrier
140  // and the end of the second thread barrier.
141  double stop = get_time_of_day();
142  thread->time = stop-start;
143  return NULL;
144 }