HClib  0.3
Documentation for Habanero-C Library API
 All Data Structures Functions Typedefs Enumerations Groups
runtime-ocr.c
1 /* Copyright (c) 2013, Rice University
2 
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6 
7 1. Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9 2. Redistributions in binary form must reproduce the above
10  copyright notice, this list of conditions and the following
11  disclaimer in the documentation and/or other materials provided
12  with the distribution.
13 3. Neither the name of Rice University
14  nor the names of its contributors may be used to endorse or
15  promote products derived from this software without specific
16  prior written permission.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30  */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 
35 // Note: OCR must have been built with ELS support
36 #include "ocr.h"
37 #include "ocr-lib.h"
38 #include "ocr-runtime-itf.h"
39 
40 #include "runtime-callback.h"
41 #include "rt-ddf.h"
42 
43 #ifdef HAVE_PHASER
44 #include "phaser-api.h"
45 #endif
46 
47 // Store async task in ELS @ offset 0
48 #define ELS_OFFSET_ASYNC 0
49 
54 // Set when initializing hclib
55 static async_task_t * root_async_task = NULL;
56 
57 // guid template for async-edt
58 static ocrGuid_t asyncTemplateGuid;
59 
60 typedef struct ocr_finish_t_ {
61  finish_t finish;
62  volatile ocrGuid_t done_event;
63 } ocr_finish_t;
64 
65 // Fwd declaration
66 ocrGuid_t asyncEdt(u32 paramc, u64* paramv, u32 depc, ocrEdtDep_t depv[]);
67 
68 #ifdef HAVE_PHASER
69 phaser_context_t * get_phaser_context_from_els();
70 #endif
71 
72 void runtime_init(int * argc, char ** argv) {
73  ocrConfig_t ocrConfig;
74  ocrParseArgs(*argc, (const char**) argv, &ocrConfig);
75  ocrInit(&ocrConfig);
76  ocrEdtTemplateCreate(&asyncTemplateGuid, asyncEdt, 1, 0);
77  #ifdef HAVE_PHASER
78  // setup phaser library
79  phaser_lib_setup(get_phaser_context_from_els);
80  #endif
81 }
82 
83 void runtime_finalize() {
84  // This is called only when the main implicit finish is done.
85  // At this point it's safe to call ocrFinish and turn the ocr runtime off.
86  ocrShutdown();
87  ocrFinalize();
88 }
89 
90 typedef struct {
91  async_task_t task; // the actual task
92  ddt_t ddt; // ddt meta-information from hclib
93 } ocr_ddt_t;
94 
95 static ocrGuid_t guidify_async(async_task_t * async_task) {
96  // The right way to do that would be to use a datablock
97  // This should work and save the alloc
98  return (ocrGuid_t) async_task;
99 }
100 
101 static async_task_t * deguidify_async(ocrGuid_t guid) {
102  // The right way to do that would be to use a datablock
103  // This should work and save the alloc
104  return (async_task_t *) guid;
105 }
106 
107 /*
108  * @brief Retrieve the async task currently executed from the ELS
109  */
110 async_task_t * get_current_async() {
111  ocrGuid_t edtGuid = currentEdtUserGet();
112  //If currentEDT is NULL_GUID
113  if (edtGuid == NULL_GUID) {
114  // This must be the main activity
115  return root_async_task;
116  }
117  ocrGuid_t guid = ocrElsUserGet(ELS_OFFSET_ASYNC);
118  return deguidify_async(guid);
119 }
120 
121 void set_current_async(async_task_t * async_task) {
122  ocrGuid_t edtGuid = currentEdtUserGet ();
123  if (edtGuid == NULL_GUID) {
124  root_async_task = async_task;
125  } else {
126  ocrGuid_t guid = guidify_async(async_task);
127  ocrElsUserSet(ELS_OFFSET_ASYNC, guid);
128  }
129 }
130 
131 // Defines the function the phaser library should use to
132 // get the phaser context of the currently executing async
133 #ifdef HAVE_PHASER
134 phaser_context_t * get_phaser_context_from_els() {
135  async_task_t * current_async = get_current_async();
136  // Lazily create phaser contexts
137  if (current_async->phaser_context == NULL) {
138  current_async->phaser_context = phaser_context_construct();
139  }
140  return current_async->phaser_context;
141 }
142 #endif
143 
147 ocrGuid_t asyncEdt(u32 paramc, u64* paramv, u32 depc, ocrEdtDep_t depv[]) {
148  // The async_task_t data-structure is the single argument.
149  async_task_t * async_task = (async_task_t *) paramv[0];
150 
151  // Stores a pointer to the async task in the ELS
152  ocrGuid_t guid = guidify_async(async_task);
153  ocrElsUserSet(ELS_OFFSET_ASYNC, guid);
154 
155  // Call back in the hclib runtime
156  rtcb_async_run(async_task);
157  return NULL_GUID;
158 }
164 async_task_t * rt_ddt_to_async_task(ddt_t * ddt) {
165  return (async_task_t *) ((void *)ddt-(void*)sizeof(async_task_t));
166 }
167 
168 ddt_t * rt_async_task_to_ddt(async_task_t * async_task) {
169  return &(((ocr_ddt_t*) async_task)->ddt);
170 }
171 
172 async_task_t * rt_allocate_ddt(struct ddf_st ** ddf_list) {
173  ocr_ddt_t * dd_task = (ocr_ddt_t *) calloc(1, sizeof(ocr_ddt_t));
174  ddt_init((ddt_t *)&(dd_task->ddt), ddf_list);
175  assert(dd_task && "calloc failed");
176  return (async_task_t *) dd_task;
177 }
178 
179 async_task_t * rt_allocate_async_task() {
180  async_task_t * async_task = (async_task_t *) calloc(1, sizeof(async_task_t));
181  assert(async_task && "calloc failed");
182  return async_task;
183 }
184 
185 void rt_deallocate_async_task(async_task_t * async_task) {
186  free(async_task);
187 }
188 
189 forasync1D_task_t * rt_allocate_forasync1D_task() {
190  //TODO malloc or calloc ?
191  forasync1D_task_t * forasync_task = (forasync1D_task_t *) calloc(1, sizeof(forasync1D_task_t));
192  assert(forasync_task && "calloc failed");
193  return forasync_task;
194 }
195 
196 forasync2D_task_t * rt_allocate_forasync2D_task() {
197  //TODO malloc or calloc ?
198  forasync2D_task_t * forasync_task = (forasync2D_task_t *) calloc(1, sizeof(forasync2D_task_t));
199  assert(forasync_task && "calloc failed");
200  return forasync_task;
201 }
202 
203 forasync3D_task_t * rt_allocate_forasync3D_task() {
204  //TODO malloc or calloc ?
205  forasync3D_task_t * forasync_task = (forasync3D_task_t *) calloc(1, sizeof(forasync3D_task_t));
206  assert(forasync_task && "calloc failed");
207  return forasync_task;
208 }
209 
210 void rt_schedule_async(async_task_t * async_task) {
211  ocrGuid_t edtGuid;
212  u64 paramv[1];
213  paramv[0] = (u64) async_task;
214  u8 retCode = ocrEdtCreate(&edtGuid, asyncTemplateGuid,
215  EDT_PARAM_DEF, paramv, EDT_PARAM_DEF, NULL, 0, NULL_GUID, NULL);
216  assert(!retCode);
217  // No dependences, the EDT gets scheduled right-away
218 }
219 
220 finish_t * rt_allocate_finish() {
221  ocr_finish_t * ocr_finish = (ocr_finish_t *) malloc(sizeof(ocr_finish_t));
222  assert(ocr_finish && "malloc failed");
223  ocr_finish->done_event = NULL_GUID;
224  return (finish_t *) ocr_finish;
225 }
226 
227 void rt_deallocate_finish(finish_t * finish) {
228  ocr_finish_t * ocr_finish = (ocr_finish_t *) finish;
229  if (ocr_finish->done_event != NULL_GUID) {
230  //TODO handle ocrWait bug
231  //ocrEventDestroy(ocr_finish->done_event);
232  }
233  free(ocr_finish);
234 }
235 
236 void rt_finish_reached_zero(finish_t * finish) {
237  ocr_finish_t * ocr_finish = (ocr_finish_t *) finish;
238  if (ocr_finish->done_event != NULL_GUID) {
239  ocrEventSatisfy(ocr_finish->done_event, NULL_GUID);
240  }
241 }
242 
243 void rt_help_finish(finish_t * finish) {
244  ocr_finish_t * ocr_finish = (ocr_finish_t *) finish;
245 
246  // The event is only required to be able to use ocrWait
247  u8 retCode = ocrEventCreate((ocrGuid_t *) &(ocr_finish->done_event), OCR_EVENT_STICKY_T, false);
248  assert(!retCode);
249 
250  // Here we're racing with other asyncs checking out of the same finish scope
251  rtcb_check_out_finish(finish);
252 
253  // OCR will try to make progress by executing other EDTs until
254  // the event is satisfied (i.e. finish-scope completed)
255  ocrWait(ocr_finish->done_event);
256  assert(finish->counter == 0);
257 }
258 
259 int rt_get_nb_workers() {
260  return nbWorkers();
261 }
262 
263 int rt_get_worker_id() {
264  int wid = currentWorkerId();
265  return wid;
266 }
267