source: CIVL/src/include/civl/collate.cvl@ 950f705

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 950f705 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
RevLine 
[68c784e]1#ifndef _CIVL_COLLATE_
2#define _CIVL_COLLATE_
3
4#include<collate.cvh>
5#include<civlc.cvh>
[18b148f]6#include<seq.cvh>
[68c784e]7
[3f2fd9e]8// Status of a collate state for a process:
[59b8938]9#define NONARRIVED 0
10#define ARRIVED 1
11#define DEPARTED 2
[3f2fd9e]12// Status of a collate attribute checker:
[dea8621]13#define UNCHECKED 3
14#define CHECKED 4
15// The $gcollate_state whose state field is significant:
[59cab66]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)
[dea8621]19// The $gcollate_state whose attribute field is significant:
[59cab66]20#define _ATTR_USED(gstate, place) ((gstate)->status[(place)] >= UNCHECKED && (gstate)->status[(place)] <= CHECKED)
21#define _CHECKED(gstate, place) ((gstate)->status[(place)] == CHECKED)
[59b8938]22
23/******************* Definition of datatypes: *******************/
[68c784e]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:
[58ef4e5]33 $gcollate_state queue[];
34 _Bool entered[];
[68c784e]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
[59cab66]44// TODO: don't use one queue for collate states and collective attributes
[68c784e]45struct _gcollate_state {
46 // An array of markers for whether a process has already arrived
[59b8938]47 // this entry or departed:
48 int status[];
[9372523]49 // collate $state:
50 $state state;
[ef8e46c]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.
[68c784e]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
[9372523]65/******************* Function definitions ***************************/
[7e7c77c]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 */
[1b7d18d]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);
[7e7c77c]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 */
[1b7d18d]109$atomic_f $collator $collator_create($gcollator gcollator, $scope scope, int place) {
110 $collator collator = ($collator)$malloc(scope, sizeof(struct _collator));
[7e7c77c]111
[1b7d18d]112 collator->place = place;
113 collator->gcollator = gcollator;
114 collator->gcollator->procs[place] = $self;
115 return collator;
[7e7c77c]116}
117
[58ef4e5]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}
[59b8938]132
[dc5d8cd]133$atomic_f $collate_state $collate_arrives($collator c, $scope scope) {
[7e7c77c]134 int place = c->place;
135 int queue_size, nprocs;
136 _Bool first = $true;
[18b148f]137 $gcollate_state * queue;
[dc5d8cd]138 $gcollate_state gcollate_state;
[1b69190]139 $collate_state result = {0, NULL};
[7e7c77c]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++)
[dea8621]148 if (_STATE_USED(queue[i], place) && !_ARRIVED(queue[i], place)) {
[7e7c77c]149 gcollate_state = queue[i];
150 first = $false;
151 break;
152 }
153 if (first) {
154 _Bool initValue = $false;
[18b148f]155 $scope root = $scopeof(*c->gcollator);
156
[1b7d18d]157 gcollate_state = ($gcollate_state)$malloc(root, sizeof(struct _gcollate_state));
[59cab66]158 gcollate_state->status = (int[nprocs])$lambda(int i) NONARRIVED;
[dc5d8cd]159 gcollate_state->state = $state_null;
[1b7d18d]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);
[7e7c77c]163 c->gcollator->queue_length++;
[dc5d8cd]164 }
[7e7c77c]165 result.place = place;
166 result.gstate = gcollate_state;
[dc5d8cd]167 $collate_snapshot(result, nprocs, scope);
[59b8938]168 gcollate_state->status[place] = ARRIVED;
[7e7c77c]169 return result;
170}
171
[762b93c]172$atomic_f void $collate_departs($collator c, $collate_state cs) {
[7e7c77c]173 int nprocs, queue_size, place, index;
[18b148f]174 $gcollate_state *queue;
[762b93c]175 $gcollate_state gcollate_state = cs.gstate;
[7e7c77c]176
177 place = c->place;
178 nprocs = c->gcollator->nprocs;
179 queue_size = c->gcollator->queue_length;
180 queue = c->gcollator->queue;
[762b93c]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
[1b7d18d]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. */
[762b93c]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) {
[7e7c77c]212 index = i;
213 break;
214 }
[762b93c]215 }
216 if (index >= 0) {
217 $seq_remove(&c->gcollator->queue, index, NULL, 1);
[1b7d18d]218 $seq_append(&c->gcollator->queue, &gcollate_state, 1);
[7e7c77c]219 c->gcollator->queue_length--;
220 }
[762b93c]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;
[7e7c77c]224}
225
[1b7d18d]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 }
[ef8e46c]243 }
[dea8621]244
[1b7d18d]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;
[ef8e46c]261
[1b7d18d]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--;
[ef8e46c]271 }
[1b7d18d]272 return result;
[ef8e46c]273}
274
[758a827]275$atomic_f $state_f $state * $collate_get_state($collate_state state){
276 return &state.gstate->state;
[21a4c56]277}
278
[68c784e]279#endif
Note: See TracBrowser for help on using the repository browser.