source: CIVL/text/include/omp.cvl@ e1b32beb

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

started to work on OpenMP support function.

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

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