source: CIVL/src/include/civl/collate.cvl@ a289c43

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since a289c43 was 762b93c, checked in by Ziqing Luo <ziqing@…>, 10 years ago

fix collate_departs bug

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

  • Property mode set to 100644
File size: 7.6 KB
Line 
1#ifndef _CIVL_COLLATE_
2#define _CIVL_COLLATE_
3
4#include<collate.cvh>
5#include<civlc.cvh>
6#include<seq.cvh>
7
8// Status of a collate state for a process
9#define NONARRIVED 0
10#define ARRIVED 1
11#define DEPARTED 2
12#define UNCHECKED 3
13#define CHECKED 4
14// The $gcollate_state whose state field is significant:
15#define _STATE_USED(gstate, place) ((gstate)->status[(place)] >= NONARRIVED && (gstate)->status[(place)] <= DEPARTED)
16#define _ARRIVED(gstate, place) ((gstate)->status[(place)] == ARRIVED || (gstate)->status[(place)] == DEPARTED)
17#define _DEPARTED(gstate, place) ((gstate)->status[(place)] == DEPARTED)
18// The $gcollate_state whose attribute field is significant:
19#define _ATTR_USED(gstate, place) ((gstate)->status[(place)] >= UNCHECKED && (gstate)->status[(place)] <= CHECKED)
20#define _CHECKED(gstate, place) ((gstate)->status[(place)] == CHECKED)
21
22/******************* Definition of datatypes: *******************/
23struct _gcollator {
24 // The number of participants of a _gcollator object:
25 int nprocs;
26 // $proc array:
27 $proc procs[];
28 // The length of the queue of collation states:
29 int queue_length;
30 // The queue of collation states. Note that elements in this queue
31 // are references to collate state objects:
32 $gcollate_state queue[];
33 _Bool entered[];
34};
35
36struct _collator {
37 // The place of the process in a _gcollator who holds this handle:
38 int place;
39 // A handle to the _gcollator object:
40 $gcollator gcollator;
41};
42
43// TODO: don't use one queue for collate states and collective attributes
44struct _gcollate_state {
45 // An array of markers for whether a process has already arrived
46 // this entry or departed:
47 int status[];
48 // collate $state:
49 $state state;
50 // A customized attribute, it can be used to check some attribute
51 // that must be equivalent collectively at some point:
52 $bundle attribute;
53 // Note: for one $gcollate_state object, state and attribute cannot
54 // be in use at the same time.
55};
56
57struct _collate_state {
58 // The place of the process in a _gcollator who holds this handle:
59 int place;
60 // A reference to a _gcollate_state:
61 $gcollate_state gstate;
62};
63
64/******************* Function definitions ***************************/
65/* Creates an global collator object. The object is allocated in the
66 * given scope. It returns a handle $gcollator to the object.
67 *
68 * scope : The scope where the object is allocated.
69 * nprocs: The number of processes included in the global collator.
70 */
71$gcollator $gcollator_create($scope scope, int nprocs) {
72 $gcollator gcollator = ($gcollator)$malloc(scope, sizeof(struct _gcollator));
73
74 gcollator->nprocs = nprocs;
75 gcollator->procs = ($proc[nprocs])$lambda(int i) $proc_null;
76 gcollator->queue_length = 0;
77 $seq_init(&(gcollator->queue), 0, NULL);
78 gcollator->entered=(_Bool[nprocs])$lambda(int i) $false;
79 return gcollator;
80}
81
82/* Creates a local collate object. The object is allocated in the
83 * given scope. A local collate represents a local handle to part of
84 * the global collate object.
85 *
86 * gcollator: The handle to the global collate object.
87 * scope: The scope where the local collate object will be allocated.
88 * place: The place of the participant process in the global collate
89 * object. Each participant process has an unique place. Place shall
90 * be greater than or equal to 0 and less than the number of all
91 * participants.
92 */
93$collator $collator_create($gcollator gcollator, $scope scope, int place) {
94 $collator collator = ($collator)$malloc(scope, sizeof(struct _collator));
95
96 collator->place = place;
97 collator->gcollator = gcollator;
98 collator->gcollator->procs[place] = $self;
99 return collator;
100}
101
102$atomic_f void $collator_enters($collator collator){
103 collator->gcollator->entered[collator->place] = $true;
104}
105
106$atomic_f _Bool $collator_has_entered($collator collator, $range range){
107 $domain(1) dom=($domain(1)){range};
108 _Bool *entered=collator->gcollator->entered;
109
110 $for(int i: dom){
111 if(!entered[i])
112 return $false;
113 }
114 return $true;
115}
116
117$atomic_f $collate_state $collate_arrives($collator c, $scope scope) {
118 int place = c->place;
119 int queue_size, nprocs;
120 _Bool first = $true;
121 $gcollate_state * queue;
122 $gcollate_state gcollate_state;
123 $collate_state result;
124
125 nprocs = c->gcollator->nprocs;
126 queue = c->gcollator->queue;
127 queue_size = c->gcollator->queue_length;
128
129 // Looking for the first unarrived collate state. If no such a collate
130 // state, create and insert one:
131 for (int i = 0; i < queue_size; i++)
132 if (_STATE_USED(queue[i], place) && !_ARRIVED(queue[i], place)) {
133 gcollate_state = queue[i];
134 first = $false;
135 break;
136 }
137 if (first) {
138 _Bool initValue = $false;
139 $scope root = $scopeof(*c->gcollator);
140
141 gcollate_state = ($gcollate_state)$malloc(root, sizeof(struct _gcollate_state));
142 gcollate_state->status = (int[nprocs])$lambda(int i) NONARRIVED;
143 gcollate_state->state = $state_null;
144 $seq_append(&c->gcollator->queue, &gcollate_state, 1);
145 c->gcollator->queue_length++;
146 }
147 result.place = place;
148 result.gstate = gcollate_state;
149 $collate_snapshot(result, nprocs, scope);
150 gcollate_state->status[place] = ARRIVED;
151 return result;
152}
153
154$atomic_f void $collate_departs($collator c, $collate_state cs) {
155 int nprocs, queue_size, place, index;
156 $gcollate_state *queue;
157 $gcollate_state gcollate_state = cs.gstate;
158
159 place = c->place;
160 nprocs = c->gcollator->nprocs;
161 queue_size = c->gcollator->queue_length;
162 queue = c->gcollator->queue;
163 $assert(_STATE_USED(gcollate_state, place)
164 && _ARRIVED(gcollate_state, place),
165 "Only an arrived collate state can be freed");
166 // Mark the refered gcollate state as departed:
167 gcollate_state->status[place] = DEPARTED;
168
169 // Scan the queue in the gcollator to remove an entry
170 // that has already been marked as DEPARTED by all processes:
171 index = -1;
172 for (int i = 0; i < queue_size; i++) {
173 _Bool isGarbage = $true;
174
175 for (int j = 0; j < nprocs; j++)
176 if (!_DEPARTED(queue[i], j)) {
177 isGarbage = $false;
178 break;
179 }
180 if (isGarbage) {
181 index = i;
182 $free(gcollate_state);
183 break;
184 }
185 }
186 if (index >= 0) {
187 $seq_remove(&c->gcollator->queue, index, NULL, 1);
188 c->gcollator->queue_length--;
189 }
190 // set the gcollate state reference to NULL so that the process
191 // cannot access it after the call of departs():
192 cs.gstate = NULL;
193}
194
195$bundle $collate_check($collator c, $bundle bundle) {
196 int nprocs, queue_size, place, index;
197 _Bool first = $true;
198 $gcollate_state attr;
199 $bundle result;
200
201 nprocs = c->gcollator->nprocs;
202 place = c->place;
203 queue_size = c->gcollator->queue_length;
204 for (int i = 0; i < queue_size; i++) {
205 if (_ATTR_USED(c->gcollator->queue[i], place)
206 && !_CHECKED(c->gcollator->queue[i], place)) {
207 first = $false;
208 attr = c->gcollator->queue[i];
209 index = i;
210 break;
211 }
212 }
213
214 if (first) {
215 $scope gcollate_scope = $scopeof(*c->gcollator);
216
217 attr = ($gcollate_state)$malloc(gcollate_scope, sizeof(struct _gcollate_state));
218 attr->status = ((int[nprocs])$lambda(int i)UNCHECKED);
219 attr->attribute = bundle;
220 $seq_append(&c->gcollator->queue, &attr, 1);
221 index = c->gcollator->queue_length++;
222 }
223 attr->status[place] = CHECKED;
224 result = attr->attribute;
225
226 // if complete, dequeue; else modify the entry:
227 _Bool complete = $true;
228
229 for (int i = 0; i < nprocs; i++)
230 if (!_CHECKED(attr, i)) {
231 complete = $false;
232 break;
233 }
234 if (complete) {
235 $assert(index == 0);
236 $free(c->gcollator->queue[0]);
237 $seq_remove(&c->gcollator->queue, 0, NULL, 1);
238 c->gcollator->queue_length--;
239 }
240 return result;
241}
242
243$atomic_f $state_f $state $collate_get_state($collate_state state){
244 return state.gstate->state;
245}
246
247#endif
Note: See TracBrowser for help on using the repository browser.