source: CIVL/text/include/omp.cvl@ 3bb4189

1.23 2.0 main test-branch
Last change on this file since 3bb4189 was ac69c0f7, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

minor correction of open mp support function.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1412 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/* This header file defines standard types and provides
2 * function prototypes used in the OpenMP to CIVLC transformation.
3 */
4
5#ifdef __CIVLC_OMP__
6#else
7#define __CIVLC_OMP__
8
9#include<civlc.cvh>
10#include<pointer.cvh>
11#include<seq.cvh>
12#include<concurrency.cvh>
13
14/* *********************** Types *********************** */
15
16typedef enum __OMP_var_status_{
17 EMPTY, // local is empty
18 FULL, // local is occupied, no writes to it have been made
19 MODIFIED // local is occupied, writes have been made to it
20} $omp_var_status;
21
22/* global shared object, used to represent the state of
23 * a shared variable. A handle type.
24 * The type of the status variable is obtained from
25 * the type of the original variable by replacing
26 * all leaf nodes in the type tree with "int".
27 */
28typedef struct OMP_gshared {
29 _Bool init[]; // which threads have joined
30 void * original; // pointer to original variable
31} * $omp_gshared;
32
33/* local view of the shared object, belonging to a single
34 * thread, with reference to the global object.
35 * A handle type.
36 */
37 /*
38typedef struct OMP_shared {
39 $omp_gshared gshared;
40 // The thread id
41 int tid;
42 // Pointer to the local copy of the shared variable.
43 // This provides the thread's "private view" of the variable.
44 void * local;
45} * $omp_shared;*/
46
47typedef struct OMP_shared {
48 $omp_gshared gshared;
49 // The thread id
50 int tid;
51 // Pointer to the local copy of the shared variable.
52 // This provides the thread's "private view" of the variable.
53 void * local;
54 // Pointer to the local status variable
55 void * status;
56} * $omp_shared;
57
58typedef struct OMP_work_record {
59 int kind; // loop, barrier, sections, or single
60 int location; // location in model of construct
61 _Bool arrived; // has this thread arrived yet?
62 $domain loop_domain; // full loop domain; null if not loop
63 $domain subdomain; // tasks this thread must do
64 // reduction operation?
65} OMP_work_record;
66
67/* global team object, represents a team of threads executing
68 * in a parallel region. A handle type. This is where all the
69 * state needed to correctly execute a parallel region will
70 * be stored. This includes all the shared object data,
71 * and a worksharking queue for every thread.
72 */
73typedef struct OMP_gteam {
74 /* scope in which data is allocated in heap */
75 $scope scope;
76 /* number of threads in team */
77 int nthreads;
78 /* which threads have joined this gteam */
79 _Bool init[];
80 /* work queues. Length nthreads. For each thread,
81 * a FIFO queue of work records */
82 OMP_work_record work[][];
83 /* the shared object data. */
84 $omp_gshared shared[];
85 $gbarrier gbarrier;
86} * $omp_gteam;
87
88typedef struct OMP_team {
89 $omp_gteam gteam;
90 $scope scope;
91 int tid;
92 $omp_shared shared[];
93 $barrier barrier;
94} * $omp_team;
95
96
97
98/* *********************** Functions *********************** */
99
100/* called by a thread when it reaches an omp sections
101 * construct, this function returns the subset of the
102 * integers 0..numSections-1 specifying the indexes of
103 * the sections that this thread will execute. The sections
104 * are numbered from 0 in increasing order.
105 */
106$domain(1) $omp_arrive_sections($omp_team team, int numSections){
107 int low = team->tid, high = numSections - 1, step = team->gteam->nthreads;
108 $range range = low .. high # step;
109 $domain(1) dom = ($domain(1)) {range};
110
111 return dom;
112}
113
114/* creates new global team object, allocating object in heap
115 * in specified scope. Number of threads that will be in the
116 * team is nthreads.
117 */
118$omp_gteam $omp_gteam_create($scope scope, int nthreads) {
119 OMP_work_record empty[0];
120 $omp_gteam result = ($omp_gteam)$malloc(scope, sizeof(struct OMP_gteam));
121 _Bool f = $false;
122
123 result->scope = scope;
124 result->nthreads = nthreads;
125 $seq_init(&result->init, nthreads, &f);
126 $seq_init(&result->work, nthreads, &empty);
127 $seq_init(&result->shared, 0, NULL);
128 result->gbarrier = $gbarrier_create(scope, nthreads);
129 return result;
130}
131
132/* destroys the global team object. All shared objects
133 * associated to the team must have been destroyed before
134 * calling this function.
135 */
136void $omp_gteam_destroy($omp_gteam gteam) {
137 int nthreads = gteam->nthreads;
138
139 $assert($seq_length(&gteam->shared)==0,
140 "shared objects must be deallocated before freeing gteam");
141 for (int i=0; i<nthreads; i++) {
142 int numRecords = $seq_length(&gteam->work[i]);
143
144 $assert(numRecords == 0,
145 "Thread %d still has %d queued worksharing events",
146 i, numRecords);
147 }
148 $free(gteam->gbarrier);
149 $free(gteam);
150}
151
152
153/* creates new local team object for a specific thread. */
154$omp_team $omp_team_create($scope scope, $omp_gteam gteam, int tid) {
155 $omp_team result = ($omp_team)$malloc(scope, sizeof(struct OMP_team));
156
157 $assert(!gteam->init[tid],
158 "Thread %d has already joined gteam",
159 tid);
160 gteam->init[tid] = $true;
161 result->gteam = gteam;
162 result->scope = scope;
163 result->tid = tid;
164 $seq_init(result->shared, 0, NULL);
165 result->barrier = $barrier_create(scope, gteam->gbarrier, tid);
166 return result;
167}
168
169/* destroys the local team object */
170void $omp_team_destroy($omp_team team) {
171 int numShared = $seq_length(team->shared);
172
173 for(int i = 0; i < numShared; i++){
174 $free(team->shared[i]);
175 }
176 $free(team->barrier);
177 $free(team);
178}
179
180/* creates new global shared object, associated to the given
181 * global team. A pointer to the shared variable that this
182 * object corresponds to is given. The new object is initialized
183 * by copying the values from the original variable.
184 */
185$omp_gshared $omp_gshared_create($omp_gteam gteam,
186 void *original) {
187 $omp_gshared result =
188 ($omp_gshared)$malloc(gteam->scope, sizeof(struct OMP_gshared));
189 _Bool f = $false;
190
191 $seq_init(result->init, gteam->nthreads, &f);
192 result->original = original;
193 //result->status = status;
194 return result;
195}
196
197/* destroys the global shared object, copying the content
198 * to the original variable.
199 */
200void $omp_gshared_destroy($omp_gshared gshared) {
201 $free(gshared);
202}
203
204/* creates a local shared object, returning handle to it */
205$omp_shared $omp_shared_create($omp_team team,
206 $omp_gshared gshared, void *local, void *status) {
207 $omp_shared result =
208 ($omp_shared)$malloc(team->scope, sizeof(struct OMP_shared));
209
210 $assert(!gshared->init[team->tid], "Thread %d has already created its local copy for %p.\n", team->tid, gshared);
211 result->gshared = gshared;
212 result->tid = team->tid;
213 result->local = local;
214 result->status = status;
215 $seq_append(&team->shared, &result, 1);
216 return result;
217}
218
219/* destroys the local shared object */
220void $omp_shared_destroy($omp_shared shared) {
221 $free(shared);
222}
223
224/* called by a thread to read a shared object.
225 * ref is a pointer into the local copy of the shared variable.
226 * The result of the read is stored in the
227 * memory unit pointed to by result.
228 * assumes ref is a pointer to a scalar.
229 */
230void $omp_read($omp_shared shared, void *result, void *ref) {
231 int tid = shared->tid;
232 int *status_ref = (int*)$translate_ptr(ref, shared->status);
233 int status = *status_ref;
234
235 if(status == EMPTY){
236 void *local = $translate_ptr(ref, shared->local);
237
238 $copy(local, ref); // copy shared to local
239 *status_ref = FULL; // set status to FULL
240 }
241 // read local
242 $copy(result, ref);
243}
244
245/* called by a thread to write to the shared object.
246 * ref is a pointer into the local copy of the shared variable.
247 * The value to be written is taken
248 * from the memory unit pointed to by value.
249 */
250void $omp_write($omp_shared shared, void *ref, void *value) {
251 int tid = shared->tid;
252 void *local = $translate_ptr(ref, shared->local);
253 int *status_ref = (int*)$translate_ptr(ref, shared->status);
254
255 $copy(local, value);
256 *status_ref = MODIFIED;
257}
258
259/* Reads the reference, applies the associative operator
260 * specified by op to the read value and the value pointed
261 * to by value, and writes the result back to ref.
262 * This happens in one atomic step. Example: you can
263 * use this to add some value to a shared variable,
264 * using CIVL_SUM for op.
265 */
266void $omp_apply_assoc($omp_shared shared, void *local,
267 $operation op,
268 void *value){
269 $atomic{
270 void *shared_ref = $translate_ptr(local, shared->gshared->original);
271
272 $apply(shared_ref, op, local, shared_ref);
273 }
274}
275
276/* performs an OpenMP flush operation on the shared object
277 */
278void $omp_flush($omp_shared shared, void *ref) {
279 // need to drill down into all leaf nodes of the object
280 // being flushed...
281 // also, it should be ok to flush a memory unit if you are not
282 // the owner but you also have no reads or writes to that variable
283
284 $omp_gshared gshared = shared->gshared;
285 int tid = shared->tid;
286 void *refs[];
287 int numRefs;
288
289 // get all leaf node pointers
290 $leaf_node_ptrs(&refs, ref);
291 numRefs = $seq_length(&refs);
292 for(int i = 0; i < numRefs; i++){
293 void *leaf = refs[i];
294 int *leaf_status = (int *)$translate_ptr(leaf, shared->status);
295 void *leaf_local = (int *)$translate_ptr(leaf, shared->local);
296 void *leaf_shared = (int *)$translate_ptr(leaf, gshared->original);
297
298 switch(*leaf_status){
299 case EMPTY:
300 break;
301 case MODIFIED:
302 $copy(leaf_shared, leaf_local);
303 case FULL:
304 *leaf_status = EMPTY;
305 $set_default(leaf_local);
306 break;
307 }
308 }
309}
310
311/* performs an OpenMP flush operation on all shared
312 * objects. This is the default in OpenMP if no argument
313 * is specified for a flush construct.
314 */
315void $omp_flush_all($omp_team team) {
316 int num_shared = $seq_length(team->shared);
317
318 for (int i=0; i<num_shared; i++) {
319 $omp_shared shared = team->shared[i];
320
321 $omp_flush(shared, shared->local);
322 }
323}
324
325/* performs a barrier only. Note however that usually
326 * (always?) a barrier is accompanied by a flush-all,
327 * so $omp_barrier_and_flush should be used instead.
328 */
329void $omp_barrier($omp_team team){
330 $barrier_call(team->barrier);
331}
332
333/* combines a barrier and a flush on all shared objects
334 * owned by the team. Implicit in many OpenMP worksharing
335 * constructs.
336 */
337void $omp_barrier_and_flush($omp_team team) {
338 // this is a collective operation: all members of team call
339 $barrier_call(team->barrier);
340 $omp_flush_all(team);
341}
342
343/* called by a thread when it reaches an omp for loop,
344 * this function returns the subset of the loop domain
345 * specifying the iterations that this thread will execute.
346 * The dimension of the domain returned equals the
347 * dimension of the given domain loop_dom.
348 */
349$domain $omp_arrive_loop($omp_team, $domain loop_dom);
350
351/* called by a thread when it reaches on omp single
352 * construct, returns the thread ID of the thread that
353 * will execute the single construct.
354 */
355int $omp_arrive_single($omp_team team){
356 return 0;
357}
358
359#endif
Note: See TracBrowser for help on using the repository browser.