HClib  0.3
Documentation for Habanero-C Library API
 All Data Structures Functions Typedefs Enumerations Groups
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 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <assert.h>
35 
36 #include "hclib.h"
37 #include "rt-hclib-def.h"
38 #include "runtime-support.h"
39 #include "runtime-hclib.h"
40 #ifdef HAVE_PHASER
41 #include "phased.h"
42 #endif
43 
48 static int runtime_on = 0;
49 static async_task_t * root_async_task = NULL;
50 
51 void hclib_init(int * argc, char ** argv) {
52  if (runtime_on) {
53  assert(0 && "hc_init called twice in a row");
54  }
55 
56  // Start the underlying runtime
57  runtime_init(argc, argv);
58  runtime_on = 1;
59 
60  // Create the root activity: abstraction to make code more uniform
61  root_async_task = allocate_async_task(NULL);
62  set_current_async(root_async_task);
63 
64  // Create and check in the implicit finish scope.
65  start_finish();
66 
67  // Go back to user code
68 }
69 
71  // Checkout of the implicit finish scope
72  if (runtime_on) {
73  // Current worker is executing the async root task
74  // Check out of the implicit finish scope
75  end_finish();
76  // Deallocate the root activity
77  free(root_async_task);
78  // Shutdown the underlying runtime
79  runtime_finalize();
80  runtime_on = 0;
81  } else {
82  assert(0 && "hc_finalize called without any matching hc_init");
83  }
84 }
85 
93 void start_finish() {
94  finish_t * finish = allocate_finish();
95  assert(finish && "malloc failed");
96  async_task_t * async_task = get_current_async();
97  finish->counter = 1;
98  finish->accumulators = NULL;
99 #if CHECKED_EXECUTION
100  // The owner of this finish scope is the worker executing this code.
101  finish->owner = get_worker_id_hc();
102 #endif
103  // The parent of this finish scope is the finish scope the
104  // async is currently executing in.
105  finish->parent = async_task->current_finish;
106  // The async task has now entered a new finish scope
107  async_task->current_finish = finish;
108 }
109 
110 void end_finish() {
111  //Note: Important to store the current async in a local as the
112  // help-protocol may execute a new async and change the
113  // worker's currently executed async.
114  async_task_t * async = get_current_async();
115  finish_t * current_finish = async->current_finish;
116  // If we still have children executing
117  if (current_finish->counter > 1) {
118  // Notify the runtime we are waiting for them
119  // Note: there's a race on counter. help_finish may
120  // start and realize the finish scope is done.
121  help_finish(current_finish);
122  }
123  //TODO careful with that, async has not been restored
124  // Notify this finish listeners, accumulators may be registered on this
125  end_finish_notify(current_finish);
126 
127  // Pop current finish to its parent
128  async->current_finish = current_finish->parent;
129  // Restore worker's currently executing async
130  //TODO not need that I think
131  set_current_async(async);
132  // Don't need this finish scope anymore
133  deallocate_finish(current_finish);
134 }
135 
136 void async(asyncFct_t fct_ptr, void * arg,
137  struct ddf_st ** ddf_list, struct _phased_t * phased_clause, int property) {
138 #if CHECKED_EXECUTION
139  assert(runtime_on);
140 #endif
141  // Populate the async definition
142  async_t async_def;
143  async_def.fct_ptr = fct_ptr;
144  async_def.arg = arg;
145  async_def.ddf_list = ddf_list;
146  #ifdef HAVE_PHASER
147  async_def.phased_clause = phased_clause;
148  #endif
149 
150  // Build the new async task and associate with the definition
151  async_task_t * async_task = allocate_async_task(&async_def);
152  schedule_async(async_task, get_current_finish(), property);
153 }