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

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since bd9857f was 758a827, checked in by Ziqing Luo <ziqing@…>, 9 years ago

corresponding changes in collate implementation

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

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