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

1.23 2.0 main test-branch
Last change on this file since 7d23067 was 2f8145f, checked in by Stephen Siegel <siegel@…>, 12 years ago

Reorganizing omp library structure in more rational way.

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

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