source: CIVL/text/include/civlc-omp.cvl@ 6d0ea02

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 6d0ea02 was f7b95e5, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

added tests for omp for/single support functions.

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

  • Property mode set to 100644
File size: 8.9 KB
Line 
1// civlc-omp.cvl: implementations of functions and types in civlc-omp.cvh
2
3#include<civlc-omp.cvh>
4#include<civlc.cvh>
5#include<pointer.cvh>
6#include<seq.cvh>
7#include<concurrency.cvh>
8#include<domain.cvh>
9
10/* Completes the definition of struct OMP_gshared given in civlc-omp.cvh.
11 */
12struct OMP_gshared {
13 _Bool init[]; // which threads have joined
14 void * original; // pointer to original variable
15};
16
17/* Completes the definition of struct OMP_shared given in civlc-omp.cvh.
18 */
19struct OMP_shared {
20 $omp_gshared gshared;
21 /* The thread id */
22 int tid;
23 /* Pointer to the local copy of the shared variable.
24 * This provides the thread's "private view" of the variable. */
25 void * local;
26 /* Pointer to the local status variable */
27 void * status;
28};
29
30/* Completes the definition of struct OMP_work_record
31 * given in civlc-omp.cvh. */
32struct OMP_work_record {
33 int kind; // loop, barrier, sections, or single
34 int location; // location in model of construct
35 _Bool arrived; // has this thread arrived yet?
36 //$domain loop_domain; // full loop domain; null if not loop
37 $domain subdomain; // tasks this thread must do
38 // reduction operation?
39};
40
41struct OMP_gteam {
42 /* scope in which data is allocated in heap */
43 $scope scope;
44 /* number of threads in team */
45 int nthreads;
46 /* which threads have joined this gteam */
47 _Bool init[];
48 /* work queues. Length nthreads. For each thread,
49 * a FIFO queue of work records */
50 $omp_work_record work[][];
51 /* the shared object data. */
52 $omp_gshared shared[];
53 $gbarrier gbarrier;
54};
55
56struct OMP_team {
57 $omp_gteam gteam;
58 $scope scope;
59 int tid;
60 $omp_shared shared[];
61 $barrier barrier;
62};
63
64
65/* *********************** Functions *********************** */
66
67$omp_gteam $omp_gteam_create($scope scope, int nthreads) {
68 $omp_work_record empty[];
69 $omp_gteam result = ($omp_gteam)$malloc(scope, sizeof(struct OMP_gteam));
70 _Bool f = $false;
71
72 $seq_init(&empty, 0, NULL);
73 result->scope = scope;
74 result->nthreads = nthreads;
75 $seq_init(&result->init, nthreads, &f);
76 $seq_init(&result->work, nthreads, &empty);
77 $seq_init(&result->shared, 0, NULL);
78 result->gbarrier = $gbarrier_create(scope, nthreads);
79 return result;
80}
81
82void $omp_gteam_destroy($omp_gteam gteam) {
83 int nthreads = gteam->nthreads;
84
85 //$assert $seq_length(&gteam->shared)==0 :
86 //"shared objects must be deallocated before freeing gteam";
87 for (int i=0; i<nthreads; i++) {
88 int numRecords = $seq_length(&gteam->work[i]);
89
90 $assert numRecords == 0 :
91 "Thread %d still has %d queued worksharing events",
92 i, numRecords;
93 }
94 $free(gteam->gbarrier);
95 $free(gteam);
96}
97
98/* creates new local team object for a specific thread. */
99$omp_team $omp_team_create($scope scope, $omp_gteam gteam, int tid) {
100 $omp_team result = ($omp_team)$malloc(scope, sizeof(struct OMP_team));
101
102 $assert !gteam->init[tid] :
103 "Thread %d has already joined gteam",
104 tid;
105 gteam->init[tid] = $true;
106 result->gteam = gteam;
107 result->scope = scope;
108 result->tid = tid;
109 $seq_init(&result->shared, 0, NULL);
110 result->barrier = $barrier_create(scope, gteam->gbarrier, tid);
111 return result;
112}
113
114/* destroys the local team object */
115void $omp_team_destroy($omp_team team) {
116 /*int numShared = $seq_length(&team->shared);
117
118 for(int i = 0; i < numShared; i++){
119 $free(team->shared[i]);
120 }*/
121 $free(team->barrier);
122 $free(team);
123}
124
125/* creates new global shared object, associated to the given
126 * global team. A pointer to the shared variable that this
127 * object corresponds to is given.
128 */
129$omp_gshared $omp_gshared_create($omp_gteam gteam,
130 void *original) {
131 $omp_gshared result =
132 ($omp_gshared)$malloc(gteam->scope, sizeof(struct OMP_gshared));
133 _Bool f = $false;
134
135 $seq_init(&result->init, gteam->nthreads, &f);
136 result->original = original;
137 //result->status = status;
138 return result;
139}
140
141/* destroys the global shared object, copying the content
142 * to the original variable.
143 */
144void $omp_gshared_destroy($omp_gshared gshared) {
145 $free(gshared);
146}
147
148$omp_shared $omp_shared_create($omp_team team,
149 $omp_gshared gshared, void *local, void *status) {
150 $omp_shared result =
151 ($omp_shared)$malloc(team->scope, sizeof(struct OMP_shared));
152 void *statusRefs[];
153 int numStatusRefs;
154 int sharedLength;
155
156 $assert !gshared->init[team->tid] :
157 "Thread %d has already created its local copy for %p.\n",
158 team->tid, gshared;
159 result->gshared = gshared;
160 result->tid = team->tid;
161 result->local = local;
162 // copies the shared data to the local copy
163 $copy(local, gshared->original);
164 result->status = status;
165 // set all leaf nodes of status to FULL
166 $leaf_node_ptrs(&statusRefs, status);
167 numStatusRefs = $seq_length(&statusRefs);
168 for(int i = 0; i < numStatusRefs; i++)
169 *((int*)(statusRefs[i])) = FULL;
170 sharedLength = $seq_length(&team->shared);
171 $seq_insert(&team->shared, sharedLength, &result, 1);
172 //$seq_append(&team->shared, &result, 1);
173 return result;
174}
175
176void $omp_shared_destroy($omp_shared shared) {
177 $free(shared);
178}
179
180void $omp_read($omp_shared shared, void *result, void *ref) {
181 int tid = shared->tid;
182 int *status_ref = (int*)$translate_ptr(ref, shared->status);
183 int status = *status_ref;
184
185 if(status == EMPTY){
186 void *global = $translate_ptr(ref, shared->gshared->original);
187
188 $copy(ref, global); // copy shared to local
189 *status_ref = FULL; // set status to FULL
190 }
191 // read local
192 $copy(result, ref);
193}
194
195void $omp_write($omp_shared shared, void *ref, void *value) {
196 int tid = shared->tid;
197 int *status_ref = (int*)$translate_ptr(ref, shared->status);
198
199 $copy(ref, value);
200 *status_ref = MODIFIED;
201}
202
203/* Only applicable to scalar type? */
204void $omp_apply_assoc($omp_shared shared,
205 $operation op,
206 void *local){
207 $atomic {
208 void *shared_ref = $translate_ptr(local, shared->gshared->original);
209
210 $apply(shared_ref, op, local, shared_ref);
211 }
212}
213
214void $omp_flush($omp_shared shared, void *ref) {
215 // need to drill down into all leaf nodes of the object
216 // being flushed...
217 // also, it should be ok to flush a memory unit if you are not
218 // the owner but you also have no reads or writes to that variable
219 // TODO: assert there is at most one thread for which this memory unit has status MODIFIED;
220 $omp_gshared gshared = shared->gshared;
221 int tid = shared->tid;
222 void *refs[];
223 int numRefs;
224
225 // get all leaf node pointers
226 $leaf_node_ptrs(&refs, ref);
227 numRefs = $seq_length(&refs);
228 for(int i = 0; i < numRefs; i++){
229 void *leaf = refs[i];
230 int *leaf_status = (int *)$translate_ptr(leaf, shared->status);
231 //void *leaf_local = (int *)$translate_ptr(leaf, shared->local);
232 void *leaf_shared = (int *)$translate_ptr(leaf, gshared->original);
233
234 switch(*leaf_status){
235 case EMPTY:
236 break;
237 case MODIFIED:
238 $copy(leaf_shared, leaf);
239 case FULL:
240 *leaf_status = EMPTY;
241 $set_default(leaf);
242 break;
243 }
244 }
245}
246
247void $omp_flush_all($omp_team team) {
248 int num_shared = $seq_length(&team->shared);
249
250 for (int i=0; i<num_shared; i++) {
251 $omp_shared shared = team->shared[i];
252
253 $omp_flush(shared, shared->local);
254 }
255}
256
257void $omp_barrier($omp_team team){
258 $barrier_call(team->barrier);
259}
260
261void $omp_barrier_and_flush($omp_team team) {
262 // this is a collective operation: all members of team call
263 $barrier_call(team->barrier);
264 $omp_flush_all(team);
265 $barrier_call(team->barrier);
266}
267
268$domain $omp_arrive_loop($omp_team team, $domain loop_dom,
269 $domain_strategy strategy){
270 $omp_gteam gteam = team->gteam;
271 int tid = team->tid;
272 int numWorkrecords, nthreads = gteam->nthreads;
273 $domain_decomposition decomposition;
274 $domain result;
275
276 $assert gteam->init[tid] : "The current thread %d has not joined the gteam!", tid;
277 numWorkrecords = $seq_length(&gteam->work[tid]);
278 for(int i = 0; i < numWorkrecords; i++){
279 $omp_work_record workrecord = gteam->work[tid][i];
280
281 if(!workrecord.arrived)
282 return workrecord.subdomain;
283 }
284 decomposition = $domain_partition(loop_dom, strategy, nthreads);
285 for(int i = 0; i< nthreads; i++){
286 $omp_work_record workrecord;
287 int workLength;
288
289 workrecord.kind = LOOP;
290 workrecord.location = 0; // TODO: how to specify the location?
291 if(i != tid){
292 workrecord.arrived = $false;
293 }else{
294 workrecord.arrived = $true;
295 result = decomposition.subdomains[i];
296 }
297 workrecord.subdomain = decomposition.subdomains[i];
298 workLength = $seq_length(&gteam->work[i]);
299 $seq_insert(&(gteam->work[i]), workLength, &workrecord, 1);
300 }
301 return result;
302}
303
304/* TODO: need strategies? */
305$domain(1) $omp_arrive_sections($omp_team team, int numSections){
306 int low = team->tid, high = numSections - 1, step = team->gteam->nthreads;
307 $range range = low .. high # step;
308 $domain(1) dom = ($domain(1)) {range};
309
310 return dom;
311}
312
313/* TODO: need strategies? */
314int $omp_arrive_single($omp_team team){
315 return 0;
316}
Note: See TracBrowser for help on using the repository browser.