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

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

fixed the "translation" problem of the reduction example; added note to omp library about the legal access of local/share view and status variables of shared variables.

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

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