source: CIVL/text/include/civlc-omp.cvl@ 09d949f

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

fixed the bug in $omp_read which yielded an uninitialization error.

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

  • Property mode set to 100644
File size: 8.2 KB
RevLine 
[2f8145f]1// civlc-omp.cvl: implementations of functions and types in civlc-omp.cvh
[d442136]2
[2f8145f]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>
[d442136]9
[68f2754]10/* Completes the definition of struct OMP_gshared given in civlc-omp.cvh.
11 */
[2f8145f]12struct OMP_gshared {
13 _Bool init[]; // which threads have joined
[7459af4]14 void * original; // pointer to original variable
15};
16
[68f2754]17/* Completes the definition of struct OMP_shared given in civlc-omp.cvh.
18 */
[2f8145f]19struct OMP_shared {
20 $omp_gshared gshared;
[68f2754]21 /* The thread id */
[2f8145f]22 int tid;
[68f2754]23 /* Pointer to the local copy of the shared variable.
24 * This provides the thread's "private view" of the variable. */
[2f8145f]25 void * local;
[68f2754]26 /* Pointer to the local status variable */
[2f8145f]27 void * status;
28};
[7459af4]29
[68f2754]30/* Completes the definition of struct OMP_work_record
31 * given in civlc-omp.cvh. */
[2f8145f]32struct OMP_work_record {
33 int kind; // loop, barrier, sections, or single
[7459af4]34 int location; // location in model of construct
35 _Bool arrived; // has this thread arrived yet?
[2f8145f]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;
[7459af4]44 /* number of threads in team */
[118a7b7]45 int nthreads;
[2f8145f]46 /* which threads have joined this gteam */
47 _Bool init[];
[7459af4]48 /* work queues. Length nthreads. For each thread,
49 * a FIFO queue of work records */
[2f8145f]50 $omp_work_record work[][];
51 /* the shared object data. */
[7459af4]52 $omp_gshared shared[];
[2f8145f]53 $gbarrier gbarrier;
54};
[f6ce0eb]55
[2f8145f]56struct OMP_team {
[7459af4]57 $omp_gteam gteam;
[2f8145f]58 $scope scope;
[f6ce0eb]59 int tid;
[2f8145f]60 $omp_shared shared[];
61 $barrier barrier;
62};
[7459af4]63
64
65/* *********************** Functions *********************** */
66
[2f8145f]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}
[7459af4]97
98/* creates new local team object for a specific thread. */
[2f8145f]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}
[7459af4]113
114/* destroys the local team object */
[2f8145f]115void $omp_team_destroy($omp_team team) {
[6389e34]116 int numShared = $seq_length(&team->shared);
[2f8145f]117
118 for(int i = 0; i < numShared; i++){
119 $free(team->shared[i]);
120 }
121 $free(team->barrier);
122 $free(team);
123}
[7459af4]124
125/* creates new global shared object, associated to the given
126 * global team. A pointer to the shared variable that this
[2f8145f]127 * object corresponds to is given.
[7459af4]128 */
[2f8145f]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
[31c5a80]135 $seq_init(&result->init, gteam->nthreads, &f);
[2f8145f]136 result->original = original;
137 //result->status = status;
138 return result;
139}
[7459af4]140
141/* destroys the global shared object, copying the content
142 * to the original variable.
143 */
[2f8145f]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
153 $assert !gshared->init[team->tid] :
154 "Thread %d has already created its local copy for %p.\n",
155 team->tid, gshared;
156 result->gshared = gshared;
157 result->tid = team->tid;
158 result->local = local;
159 result->status = status;
160 $seq_append(&team->shared, &result, 1);
161 return result;
162}
163
164void $omp_shared_destroy($omp_shared shared) {
165 $free(shared);
166}
167
168void $omp_read($omp_shared shared, void *result, void *ref) {
169 int tid = shared->tid;
170 int *status_ref = (int*)$translate_ptr(ref, shared->status);
171 int status = *status_ref;
172
173 if(status == EMPTY){
[09d949f]174 void *global = $translate_ptr(ref, shared->gshared->original);
[2f8145f]175
[09d949f]176 $copy(ref, global); // copy shared to local
[2f8145f]177 *status_ref = FULL; // set status to FULL
178 }
179 // read local
180 $copy(result, ref);
181}
182
183void $omp_write($omp_shared shared, void *ref, void *value) {
184 int tid = shared->tid;
185 int *status_ref = (int*)$translate_ptr(ref, shared->status);
186
187 $copy(ref, value);
188 *status_ref = MODIFIED;
189}
190
191void $omp_apply_assoc($omp_shared shared,
192 $operation op,
193 void *local){
194 $atomic {
195 void *shared_ref = $translate_ptr(local, shared->gshared->original);
196
197 $apply(shared_ref, op, local, shared_ref);
198 }
199}
200
201void $omp_flush($omp_shared shared, void *ref) {
202 // need to drill down into all leaf nodes of the object
203 // being flushed...
204 // also, it should be ok to flush a memory unit if you are not
205 // the owner but you also have no reads or writes to that variable
206 $omp_gshared gshared = shared->gshared;
207 int tid = shared->tid;
208 void *refs[];
209 int numRefs;
210
211 // get all leaf node pointers
212 $leaf_node_ptrs(&refs, ref);
213 numRefs = $seq_length(&refs);
214 for(int i = 0; i < numRefs; i++){
215 void *leaf = refs[i];
216 int *leaf_status = (int *)$translate_ptr(leaf, shared->status);
217 void *leaf_local = (int *)$translate_ptr(leaf, shared->local);
218 void *leaf_shared = (int *)$translate_ptr(leaf, gshared->original);
219
220 switch(*leaf_status){
221 case EMPTY:
222 break;
223 case MODIFIED:
224 $copy(leaf_shared, leaf_local);
225 case FULL:
226 *leaf_status = EMPTY;
227 $set_default(leaf_local);
228 break;
229 }
230 }
231}
232
233void $omp_flush_all($omp_team team) {
[84932eb]234 int num_shared = $seq_length(&team->shared);
[2f8145f]235
236 for (int i=0; i<num_shared; i++) {
237 $omp_shared shared = team->shared[i];
238
239 $omp_flush(shared, shared->local);
240 }
241}
242
243void $omp_barrier($omp_team team){
244 $barrier_call(team->barrier);
245}
246
247void $omp_barrier_and_flush($omp_team team) {
248 // this is a collective operation: all members of team call
249 $barrier_call(team->barrier);
250 $omp_flush_all(team);
251 $barrier_call(team->barrier);
252}
253
254$domain $omp_arrive_loop($omp_team team, $domain loop_dom,
[887a6423]255 $domain_strategy strategy){
[2f8145f]256 $omp_gteam gteam = team->gteam;
257 int tid = team->tid;
258 int numWorkrecords, nthreads = gteam->nthreads;
259 $domain_decomposition decomposition;
260 $domain result;
261
262 $assert gteam->init[tid] : "The current thread %d has not joined the gteam!", tid;
263 numWorkrecords = $seq_length(&gteam->work[tid]);
264 for(int i = 0; i < numWorkrecords; i++){
265 $omp_work_record workrecord = gteam->work[tid][i];
266
267 if(!workrecord.arrived)
268 return workrecord.subdomain;
269 }
270 decomposition = $domain_partition(loop_dom, strategy, nthreads);
271 for(int i = 0; i< nthreads; i++){
272 $omp_work_record workrecord;
273
274 workrecord.kind = LOOP;
275 workrecord.location = 0; // TODO: how to specify the location?
276 if(i != tid){
277 workrecord.arrived = $false;
278 }else{
279 workrecord.arrived = $true;
280 result = decomposition.subdomains[i];
281 }
282 workrecord.subdomain = decomposition.subdomains[i];
283 $seq_append(&gteam->work[i], &workrecord, 1);
284 }
285 return result;
286}
287
288$domain(1) $omp_arrive_sections($omp_team team, int numSections){
289 int low = team->tid, high = numSections - 1, step = team->gteam->nthreads;
290 $range range = low .. high # step;
291 $domain(1) dom = ($domain(1)) {range};
292
293 return dom;
294}
295
296int $omp_arrive_single($omp_team team){
297 return 0;
298}
Note: See TracBrowser for help on using the repository browser.