HClib  0.3
Documentation for Habanero-C Library API
 All Data Structures Functions Typedefs Enumerations Groups
runtime-hclib.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 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <assert.h>
38 
39 #include "hc_sysdep.h"
40 #include "runtime-support.h"
41 #include "rt-accumulator.h"
42 #include "rt-ddf.h"
43 #ifdef HAVE_PHASER
44 #include "phased.h"
45 #endif
46 
47 
51 void check_in_finish(finish_t * finish) {
52  hc_atomic_inc(&(finish->counter));
53 }
54 
59 void check_out_finish(finish_t * finish) {
60  if (hc_atomic_dec(&(finish->counter))) {
61  // If counter reached zero notify runtime
62  rt_finish_reached_zero(finish);
63  }
64 }
65 
69 void async_check_in_finish(async_task_t * async_task) {
70  check_in_finish(async_task->current_finish);
71 }
72 
76 void async_check_out_finish(async_task_t * async_task) {
77  check_out_finish(async_task->current_finish);
78 }
79 
83 void async_drop_phasers(async_task_t * async_task) {
84 #ifdef HAVE_PHASER
85  if (async_task->phaser_context != NULL) {
86  // This call drop all phasers and deallocate the context
87  destruct_phaser_context();
88  async_task->phaser_context = NULL;
89  }
90 #endif
91 }
92 
99 async_task_t * allocate_async_task(async_t * async_def) {
100  async_task_t * async_task;
101  if ((async_def != NULL) && async_def->ddf_list != NULL) {
102  // When the async has ddfs, we allocate a ddt instead
103  // of a regular async. The ddt has extra data-structures.
104  async_task = rt_allocate_ddt(async_def->ddf_list);
105  } else {
106  // Initializes and zeroes
107  async_task = rt_allocate_async_task();
108  }
109  // Copy the definition
110  if (async_def != NULL) {
111  async_task->def = *async_def;
112  }
113  #ifdef HAVE_PHASER
114  async_task->phaser_context = NULL;
115  #endif
116  return async_task;
117 }
118 
122 forasync1D_task_t * allocate_forasync1D_task() {
123  return rt_allocate_forasync1D_task();
124 }
125 
129 forasync2D_task_t * allocate_forasync2D_task() {
130  return rt_allocate_forasync2D_task();
131 }
132 
136 forasync3D_task_t * allocate_forasync3D_task() {
137  return rt_allocate_forasync3D_task();
138 }
139 
143 void deallocate_async_task(async_task_t * async) {
144  rt_deallocate_async_task(async);
145 }
146 
150 finish_t * allocate_finish() {
151  return rt_allocate_finish();
152 }
153 
157 void deallocate_finish(finish_t * finish) {
158  rt_deallocate_finish(finish);
159 }
160 
164 finish_t * get_current_finish() {
165  // Calling get_current_async is always legal because there's
166  // a fake async to represent the main activity.
167  return get_current_async()->current_finish;
168 }
169 
170 void end_finish_notify(finish_t * current_finish) {
171  accum_t ** accumulators = current_finish->accumulators;
172  if(accumulators != NULL) {
173  int i = 0;
174  while (accumulators[i] != NULL) {
175  accum_impl_t * accum_impl = (accum_impl_t *) accumulators[i];
176  accum_impl->close(accum_impl);
177  i++;
178  }
179  }
180 }
181 
182 static int is_eligible_to_schedule(async_task_t * async_task) {
183  if (async_task->def.ddf_list != NULL) {
184  ddt_t * ddt = (ddt_t *) rt_async_task_to_ddt(async_task);
185  return iterate_ddt_frontier(ddt);
186  } else {
187  return 1;
188  }
189 }
190 
191 int get_nb_workers() {
192  return rt_get_nb_workers();
193 }
194 
195 int get_worker_id_hc() {
196  return rt_get_worker_id();
197 }
198 
199 void try_schedule_async(async_task_t * async_task) {
200  if (is_eligible_to_schedule(async_task)) {
201  rt_schedule_async(async_task);
202  }
203 }
204 
205 void schedule_async(async_task_t * async_task, finish_t * finish_scope, int property) {
206  // Set the async finish scope to be the currently executing async's one.
207  async_task->current_finish = finish_scope;
208  // The newly created async must check in the current finish scope
209  async_check_in_finish(async_task);
210 
211  #ifdef HAVE_PHASER
212  phased_t * phased_clause = async_task->def.phased_clause;
213  assert(!(phased_clause && (property & PHASER_TRANSMIT_ALL)));
214  if (phased_clause != NULL) {
215  phaser_context_t * currentCtx = get_phaser_context();
216  phaser_context_t * ctx = phaser_context_construct();
217  async_task->phaser_context = ctx;
218  transmit_specific_phasers(currentCtx, ctx,
219  phased_clause->count,
220  phased_clause->phasers,
221  phased_clause->phasers_mode);
222  }
223  if (property & PHASER_TRANSMIT_ALL) {
224  phaser_context_t * currentCtx = get_phaser_context();
225  phaser_context_t * ctx = phaser_context_construct();
226  async_task->phaser_context = ctx;
227  transmit_all_phasers(currentCtx, ctx);
228  }
229  #endif
230 
231  // delegate scheduling to the underlying runtime
232  try_schedule_async(async_task);
233 
234  // Note: here the async has been scheduled and may or may not
235  // have been executed yet. Careful when adding code here.
236 }
237 
238 void help_finish(finish_t * finish) {
239  rt_help_finish(finish);
240 }