00001 #include <converse.h>
00002 #include <stdarg.h>
00003
00004
00005
00006
00007
00008
00009
00010 #define CrcGenericAlign 8
00011 #define CrcGenericAlignInt(n) (((n)+CrcGenericAlign-1)&(~(CrcGenericAlign-1)))
00012 #define CrcGenericAlignPtr(p) ((void*)CrcGenericAlignInt((size_t)(p)))
00013
00014 typedef struct buffer buffer;
00015 typedef struct eltset *eltset;
00016 typedef struct single *single;
00017 typedef struct reduction *reduction;
00018
00019 struct buffer
00020 {
00021 unsigned char *data;
00022 int fill;
00023 int size;
00024 };
00025
00026 struct eltset
00027 {
00028 eltset next;
00029 CPath path;
00030 int eltno;
00031 int root;
00032 int inset;
00033 int parent;
00034 int child1;
00035 int child2;
00036 reduction reductions;
00037 int nlocals;
00038 single locals[1];
00039 };
00040
00041 struct single
00042 {
00043 single next;
00044 CPath path;
00045 int eltno;
00046 int waiting;
00047 CmmTable mm;
00048 CthThread thread;
00049 };
00050
00051 struct reduction
00052 {
00053 eltset over;
00054 CPath dest; int desteltno;
00055 int reducer;
00056 int vecsize; int eltsize;
00057 char *msg_begin, *msg_data, *msg_end;
00058 int anydata, waitcount;
00059 struct reduction *next;
00060 int ntags;
00061 int tags[1];
00062 };
00063
00064 CpvStaticDeclare(int *, PElist);
00065 CpvStaticDeclare(char *, PEflags);
00066 CpvStaticDeclare(int, seqno);
00067 CpvStaticDeclare(int, CPathSendIdx);
00068 CpvStaticDeclare(int, CPathReduceIdx);
00069 CpvStaticDeclare(eltset *, EltsetTable);
00070 CpvStaticDeclare(int, EltsetTabsize);
00071 CpvStaticDeclare(single *, SingleTable);
00072 CpvStaticDeclare(int, SingleTabsize);
00073 CpvStaticDeclare(reduction *, ReduceTable);
00074 CpvStaticDeclare(int, ReduceTabsize);
00075 CtvStaticDeclare(single, thisthread);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static void *bufalloc(buffer *b, int n)
00087 {
00088 int fill = CrcGenericAlignInt(b->fill);
00089 int nfill = fill+n;
00090 int nsize; char *ndata;
00091
00092 b->fill = nfill;
00093 if (nfill > b->size) {
00094 nsize = nfill*2;
00095 b->size = nsize;
00096 ndata = (char*)CmiAlloc(nsize);
00097 memcpy(ndata, b->data, fill);
00098 CmiFree(b->data);
00099 b->data = ndata;
00100 }
00101 return b->data + fill;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 unsigned int CPathIndicesToEltno(int nsizes, int *sizes, int *indices)
00114 {
00115 unsigned int size, eltno; int i, index;
00116 eltno=0;
00117 for (i=0; i<nsizes; i++) {
00118 size = sizes[i];
00119 index = indices[i];
00120 eltno *= (size + 1);
00121 if (index == CPATH_ALL) index = size;
00122 eltno += index;
00123 }
00124 return eltno;
00125 }
00126
00127 void CPathEltnoToIndices(int nsizes, int *sizes,
00128 unsigned int eltno, int *indices)
00129 {
00130 unsigned int size; int i, index;
00131 for (i=nsizes-1; i>=0; i--) {
00132 size = sizes[i];
00133 index = eltno % (size + 1);
00134 eltno /= (size + 1);
00135 if (index == size) index = CPATH_ALL;
00136 indices[i] = index;
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 int CPathMap(CPath *path, int *indices)
00153 {
00154 CPathMapFn mapper = (CPathMapFn)CmiHandlerToFunction(path->mapfn);
00155 return mapper(path, indices) % CmiNumPes();
00156 }
00157
00158 int CPathRoot(CPath *path, int *indices)
00159 {
00160 int nindices[13], i;
00161 for (i=0; i<path->nsizes; i++) {
00162 nindices[i] = indices[i];
00163 if (nindices[i] == CPATH_ALL)
00164 nindices[i] = path->sizes[i] - 1;
00165 }
00166 return CPathMap(path, nindices);
00167 }
00168
00169 void CPathExecute(single t)
00170 {
00171 unsigned int indices[13];
00172 CthVoidFn fn = CmiHandlerToFunction(t->path.startfn);
00173 CtvAccess(thisthread) = t;
00174 CPathEltnoToIndices(t->path.nsizes, t->path.sizes, t->eltno, indices);
00175 fn(&(t->path), indices);
00176
00177 }
00178
00179 single CPathGetSingle(CPath *path, int *indices)
00180 {
00181 single *table = CpvAccess(SingleTable);
00182 unsigned int eltno = CPathIndicesToEltno(path->nsizes, path->sizes, indices);
00183 unsigned int hashval = path->seqno ^ path->creator ^ eltno;
00184 unsigned int bucket = hashval % CpvAccess(SingleTabsize);
00185 single result;
00186
00187 for (result=table[bucket]; result; result=result->next) {
00188 if ((result->path.seqno == path->seqno)&&
00189 (result->path.creator == path->creator)&&
00190 (result->eltno == eltno))
00191 return result;
00192 }
00193
00194 result = (single)malloc(sizeof(struct single));
00195 _MEMCHECK(result);
00196 result->path = *path;
00197 result->eltno = eltno;
00198 result->waiting = 0;
00199 result->mm = CmmNew();
00200 result->thread = CthCreate(CPathExecute, result, 0);
00201 result->next = table[bucket];
00202 table[bucket] = result;
00203 CthAwaken(result->thread);
00204 return result;
00205 }
00206
00207 eltset CPathAllocEltset(eltset old, int nlocals)
00208 {
00209 return (eltset)realloc(old, sizeof(struct eltset) + nlocals*sizeof(single));
00210 }
00211
00212 void CPathDecrementOdometer(int *odometer, int *sizes, int nvary, int *vary)
00213 {
00214 int i = 0;
00215 while (odometer[vary[i]]==0) {
00216 odometer[vary[i]] = sizes[vary[i]] - 1;
00217 i++;
00218 }
00219 odometer[vary[i]]--;
00220 }
00221
00222 eltset CPathGetEltset(CPath *path, int *indices)
00223 {
00224 int nsizes;
00225 int *sizes;
00226 unsigned int eltno;
00227 eltset *table;
00228 unsigned int hashval;
00229 unsigned int bucket;
00230 int nelts;
00231 int nvary;
00232 int vary[13];
00233 int mype;
00234 int root;
00235 char *peflags;
00236 int *pelist;
00237 int pecount;
00238 int peself;
00239 eltset result;
00240 int resultfill;
00241 int resultsize;
00242 int tsize, tpe, teltno, i, j;
00243
00244
00245 nsizes = path->nsizes;
00246 sizes = path->sizes;
00247
00248
00249 eltno = CPathIndicesToEltno(nsizes, sizes, indices);
00250 hashval = path->seqno ^ path->creator ^ eltno;
00251 bucket = hashval % CpvAccess(EltsetTabsize);
00252 table = CpvAccess(EltsetTable);
00253
00254
00255 for (result=table[bucket]; result; result=result->next) {
00256 if ((result->eltno == eltno) &&
00257 (result->path.seqno == path->seqno) &&
00258 (result->path.creator == path->creator)) {
00259 return result;
00260 }
00261 }
00262
00263
00264 nelts = 1; nvary = 0;
00265 for (i=0; i<nsizes; i++) {
00266 if (indices[i] == CPATH_ALL) {
00267 tsize = sizes[i];
00268 nelts *= tsize;
00269 indices[i] = tsize - 1;
00270 vary[nvary++] = i;
00271 }
00272 }
00273
00274
00275 root = CPathMap(path, indices);
00276 mype = CmiMyPe();
00277
00278
00279
00280
00281 pelist = CpvAccess(PElist);
00282 peflags = CpvAccess(PEflags);
00283 pecount = 0;
00284 peself = -1;
00285 resultfill = 0;
00286 resultsize = (nelts > 10) ? 10 : nelts;
00287 result = CPathAllocEltset(0, resultsize);
00288
00289
00290 i = 0;
00291 while (1) {
00292 tpe = CPathMap(path, indices);
00293 if (peflags[tpe]==0) {
00294 if (tpe == mype) peself = pecount;
00295 peflags[tpe] = 1;
00296 pelist[pecount++] = tpe;
00297 }
00298 if (tpe == mype) {
00299 if (resultfill == resultsize) {
00300 resultsize <<= 1;
00301 result = CPathAllocEltset(result, resultsize);
00302 }
00303 result->locals[resultfill++] = CPathGetSingle(path, indices);
00304 }
00305 i++; if (i==nelts) break;
00306 CPathDecrementOdometer(indices, sizes, nvary, vary);
00307 }
00308
00309
00310 for (i=0; i<pecount; i++) peflags[pelist[i]] = 0;
00311 for (i=0; i<nvary; i++) indices[vary[i]] = CPATH_ALL;
00312
00313
00314 result = CPathAllocEltset(result, resultfill);
00315 result->next = table[bucket];
00316 table[bucket] = result;
00317 result->path = (*path);
00318 result->eltno = eltno;
00319 result->root = root;
00320 if (peself < 0) {
00321 result->inset = 0;
00322 result->parent = -1;
00323 result->child1 = -1;
00324 result->child2 = -1;
00325 } else {
00326 i = (peself+1)<<1;
00327 j = i-1;
00328 result->inset = 1;
00329 result->parent = peself ? pelist[(peself-1)>>1] : -1;
00330 result->child1 = (i<pecount) ? pelist[i] : -1;
00331 result->child2 = (j<pecount) ? pelist[j] : -1;
00332 }
00333 result->nlocals = resultfill;
00334 return result;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 void CPathSend(int key, ...)
00348 {
00349 buffer buf; va_list p; CPath *path;
00350 char *src, *cpy; int root, i, vecsize, eltsize, size, idx, ntags, eltno;
00351 int indices[13], tags[256], *tagv;
00352
00353 buf.data = (unsigned char*)CmiAlloc(128);
00354 buf.fill = CmiMsgHeaderSizeBytes;
00355 buf.size = 128;
00356 va_start(p, key);
00357
00358
00359 switch(key) {
00360 case CPATH_DEST:
00361 path = va_arg(p, CPath *);
00362 for (i=0; i<path->nsizes; i++)
00363 indices[i] = va_arg(p, int);
00364 break;
00365 case CPATH_DESTELT:
00366 path = va_arg(p, CPath *);
00367 eltno = va_arg(p, int);
00368 CPathEltnoToIndices(path->nsizes, path->sizes, eltno, indices);
00369 break;
00370 default: goto synerr;
00371 }
00372 cpy = bufalloc(&buf,sizeof(CPath));
00373 memcpy(cpy, path, sizeof(CPath));
00374 cpy = bufalloc(&buf,path->nsizes * sizeof(int));
00375 memcpy(cpy, indices, path->nsizes * sizeof(int));
00376 root = CPathRoot(path, indices);
00377
00378
00379 key = va_arg(p, int);
00380 switch (key) {
00381 case CPATH_TAG:
00382 ntags = 1;
00383 tags[0] = va_arg(p, int);
00384 tagv = tags;
00385 break;
00386 case CPATH_TAGS:
00387 ntags = va_arg(p, int);
00388 for (i=0; i<ntags; i++)
00389 tags[i] = va_arg(p, int);
00390 tagv = tags;
00391 break;
00392 case CPATH_TAGVEC:
00393 ntags = va_arg(p, int);
00394 tagv = va_arg(p, int*);
00395 break;
00396 }
00397 cpy = bufalloc(&buf,(ntags+1)*sizeof(int));
00398 ((int*)cpy)[0] = ntags;
00399 for (i=0; i<ntags; i++)
00400 ((int*)cpy)[i+1] = tagv[i];
00401
00402
00403 key = va_arg(p, int);
00404 switch (key) {
00405 case CPATH_BYTES:
00406 size = va_arg(p, int);
00407 src = va_arg(p, char*);
00408 cpy = bufalloc(&buf,sizeof(int)+size);
00409 *((int*)cpy) = size;
00410 memcpy(cpy + sizeof(int), src, size);
00411 break;
00412 case CPATH_REDBYTES:
00413 vecsize = va_arg(p, int);
00414 eltsize = va_arg(p, int);
00415 size = vecsize * eltsize;
00416 src = va_arg(p, char *);
00417 cpy = bufalloc(&buf,2*sizeof(int)+(vecsize*eltsize));
00418 ((int*)cpy)[0] = size;
00419 ((int*)cpy)[1] = vecsize;
00420 memcpy(cpy + sizeof(int) + sizeof(int), src, size);
00421 break;
00422 default: goto synerr;
00423 }
00424 key = va_arg(p, int);
00425 if (key!=CPATH_END) goto synerr;
00426
00427
00428 CmiSetHandler(buf.data, CpvAccess(CPathSendIdx));
00429 CmiSyncSendAndFree(root, buf.fill, buf.data);
00430 return;
00431
00432 synerr:
00433 CmiError("CPathSend: syntax error in argument list.\n");
00434 exit(1);
00435 }
00436
00437 void CPathSendHandler(char *decoded)
00438 {
00439 char *p; CPath *path;
00440 int *indices, *tags, ntags, mype, i, *tail, len;
00441 eltset set; single sing; char *mend;
00442
00443 mype = CmiMyPe();
00444 path = (CPath*)CrcGenericAlignPtr(decoded + CmiMsgHeaderSizeBytes);
00445 indices = (int*)CrcGenericAlignPtr(path + 1);
00446 tags = (int*)CrcGenericAlignPtr(indices + path->nsizes);
00447 ntags = *tags++;
00448 tail = (int*)CrcGenericAlignPtr(tags + ntags);
00449 len = *tail++;
00450 mend = ((char*)tail)+len;
00451
00452 set = CPathGetEltset(path, indices);
00453 if (set->child1 >= 0) CmiSyncSend(set->child1, mend-decoded, decoded);
00454 if (set->child2 >= 0) CmiSyncSend(set->child2, mend-decoded, decoded);
00455
00456 *((int*)decoded) = set->nlocals;
00457 for (i=0; i<set->nlocals; i++) {
00458 sing = set->locals[i];
00459 CmmPut(sing->mm, ntags, tags, decoded);
00460 if (sing->waiting) {
00461 sing->waiting = 0;
00462 CthAwaken(sing->thread);
00463 }
00464 }
00465 }
00466
00467 void *CPathRecv(int key, ...)
00468 {
00469 va_list p; int i, ntags, *tags; int tagbuf[256], rtags[256];
00470 int *hlen; char **buffer; void *msg;
00471 single t = CtvAccess(thisthread);
00472
00473 va_start(p, key);
00474 switch(key) {
00475 case CPATH_TAG:
00476 ntags = 1;
00477 tagbuf[0] = va_arg(p, int);
00478 tags = tagbuf;
00479 break;
00480 case CPATH_TAGS:
00481 ntags = va_arg(p, int);
00482 if (ntags>256) goto sizerr;
00483 for (i=0; i<ntags; i++)
00484 tagbuf[i] = va_arg(p, int);
00485 tags = tagbuf;
00486 break;
00487 default: goto synerr;
00488 }
00489
00490 key = va_arg(p, int);
00491 if (key != CPATH_END) goto synerr;
00492
00493 while (1) {
00494 msg = CmmGet(t->mm, ntags, tags, rtags);
00495 if (msg) break;
00496 t->waiting = 1;
00497 CthSuspend();
00498 }
00499 return msg;
00500
00501 synerr:
00502 CmiError("CPathRecv: syntax error in argument list.\n");
00503 exit(1);
00504 sizerr:
00505 CmiError("CPathRecv: too many tags.\n");
00506 exit(1);
00507 }
00508
00509 void CPathMsgDecodeBytes(void *msg, int *len, void *bytes)
00510 {
00511 CPath *path; int *indices; unsigned int *tags, ntags, *tail;
00512 path = (CPath*)CrcGenericAlignPtr(((char*)msg)+CmiMsgHeaderSizeBytes);
00513 indices = (int*)CrcGenericAlignPtr(path + 1);
00514 tags = CrcGenericAlignPtr(indices + path->nsizes);
00515 ntags = *tags++;
00516 tail = CrcGenericAlignPtr(tags + ntags);
00517 *len = *tail++;
00518 *((void**)bytes) = (void*)tail;
00519 }
00520
00521 void CPathMsgDecodeReduction(void *msg,int *vecsize,int *eltsize,void *bytes)
00522 {
00523 CPath *path; int *indices; unsigned int *tags, ntags, *tail, size;
00524 path = (CPath*)CrcGenericAlignPtr(((char*)msg)+CmiMsgHeaderSizeBytes);
00525 indices = (int*)CrcGenericAlignPtr(path + 1);
00526 tags = CrcGenericAlignPtr(indices + path->nsizes);
00527 ntags = *tags++;
00528 tail = CrcGenericAlignPtr(tags + ntags);
00529 size = *tail++;
00530 *vecsize = *tail++;
00531 *eltsize = size / (*vecsize);
00532 *((void**)bytes) = (void*)tail;
00533 }
00534
00535 void CPathMsgFree(void *msg)
00536 {
00537 int ref = ((int*)msg)[0] - 1;
00538 if (ref==0) {
00539 CmiFree(msg);
00540 } else {
00541 ((int*)msg)[0] = ref;
00542 }
00543 }
00544
00545 void CPathMakeArray(CPath *path, int startfn, int mapfn, ...)
00546 {
00547 int size, seq, pe, nsizes; va_list p;
00548 va_start(p, mapfn);
00549 nsizes = 0;
00550 while (1) {
00551 size = va_arg(p, int);
00552 if (size==0) break;
00553 if (nsizes==13) {
00554 CmiError("CPathMakeArray: Limit of 13 dimensions.\n");
00555 exit(1);
00556 }
00557 path->sizes[nsizes++] = size;
00558 }
00559 path->creator = CmiMyPe();
00560 path->seqno = CpvAccess(seqno)++;
00561 path->mapfn = mapfn;
00562 path->startfn = startfn;
00563 path->nsizes = nsizes;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 void CPathMergeReduction(reduction red, void *data);
00578
00579 void CPathReduceMismatch(void)
00580 {
00581 CmiError("CPathReduce: all members of reduction do not agree on reduction parameters.\n");
00582 exit(1);
00583 }
00584
00585 void CPathCreateRedmsg(reduction red)
00586 {
00587
00588
00589
00590
00591 int o_paths, o_params, o_tags, o_data, o_end;
00592 int i, *t; char *msg;
00593
00594 o_paths = CrcGenericAlignInt(CmiMsgHeaderSizeBytes);
00595 o_params = CrcGenericAlignInt(o_paths + 2*sizeof(CPath));
00596 o_tags = CrcGenericAlignInt(o_params + 6*sizeof(int));
00597 o_data = CrcGenericAlignInt(o_tags + red->ntags*sizeof(int));
00598 o_end = o_data + (red->vecsize * red->eltsize);
00599
00600 msg = (char*)CmiAlloc(o_end);
00601 CmiSetHandler(msg, CpvAccess(CPathReduceIdx));
00602 ((CPath*)(msg+o_paths))[0] = red->over->path;
00603 ((CPath*)(msg+o_paths))[1] = red->dest;
00604 ((int*)(msg+o_params))[0] = red->over->eltno;
00605 ((int*)(msg+o_params))[1] = red->desteltno;
00606 ((int*)(msg+o_params))[2] = red->reducer;
00607 ((int*)(msg+o_params))[3] = red->vecsize;
00608 ((int*)(msg+o_params))[4] = red->eltsize;
00609 ((int*)(msg+o_params))[5] = red->ntags;
00610 t = (int*)(msg+o_tags);
00611 for (i=0; i<red->ntags; i++) *t++ = red->tags[i];
00612
00613 red->msg_begin = msg;
00614 red->msg_data = msg + o_data;
00615 red->msg_end = msg + o_end;
00616 }
00617
00618 reduction CPathGetReduction(eltset set, int ntags, int *tags,
00619 int vecsize, int eltsize,
00620 int reducer, CPath *dest, int desteltno)
00621 {
00622 reduction red; int i;
00623
00624 for (red=set->reductions; red; red=red->next) {
00625 if (red->ntags != ntags) continue;
00626 for (i=0; i<ntags; i++)
00627 if (red->tags[i] != tags[i]) continue;
00628
00629 if (red->vecsize != vecsize) CPathReduceMismatch();
00630 if (red->eltsize != eltsize) CPathReduceMismatch();
00631 if (red->reducer != reducer) CPathReduceMismatch();
00632 if (red->dest.creator != dest->creator) CPathReduceMismatch();
00633 if (red->dest.seqno != dest->seqno) CPathReduceMismatch();
00634 if (red->desteltno != desteltno) CPathReduceMismatch();
00635
00636 return red;
00637 }
00638
00639 red = (reduction)malloc(sizeof(struct reduction) + ntags*sizeof(int));
00640 _MEMCHECK(red);
00641
00642 red->over = set;
00643 red->ntags = ntags;
00644 for (i=0; i<ntags; i++) red->tags[i] = tags[i];
00645 red->vecsize = vecsize;
00646 red->eltsize = eltsize;
00647 red->reducer = reducer;
00648 red->dest = (*dest);
00649 red->desteltno = desteltno;
00650
00651 red->anydata = 0;
00652 red->waitcount = set->nlocals;
00653 if (set->child1 >= 0) red->waitcount++;
00654 if (set->child2 >= 0) red->waitcount++;
00655
00656 CPathCreateRedmsg(red);
00657
00658 red->next = set->reductions;
00659 set->reductions = red;
00660
00661 return red;
00662 }
00663
00664 void CPathReduceHandler(void *decoded)
00665 {
00666
00667 CPath *paths, *over, *dest; int *params, *tags;
00668 int o_paths, o_params, o_tags, o_data, o_end;
00669 int overeltno, desteltno, reducer, vecsize, eltsize, ntags;
00670 eltset set; reduction red; int overidx[13]; void *data;
00671
00672 paths = (CPath*)CrcGenericAlignPtr(decoded + CmiMsgHeaderSizeBytes);
00673 params = (int*)CrcGenericAlignPtr(paths + 2);
00674 over = paths+0;
00675 dest = paths+1;
00676 overeltno = params[0];
00677 desteltno = params[1];
00678 reducer = params[2];
00679 vecsize = params[3];
00680 eltsize = params[4];
00681 ntags = params[5];
00682 tags = (int*)CrcGenericAlignPtr(params+6);
00683 data = (void*)CrcGenericAlignPtr(tags + ntags);
00684
00685 CPathEltnoToIndices(over->nsizes, over->sizes, overeltno, overidx);
00686 set = CPathGetEltset(over, overidx);
00687 red = CPathGetReduction
00688 (set, ntags, tags, vecsize, eltsize, reducer, dest, desteltno);
00689 CPathMergeReduction(red, data);
00690 }
00691
00692 void CPathForwardReduction(reduction red)
00693 {
00694 int pe; eltset set; reduction *hred;
00695
00696 pe = red->over->parent;
00697 if (pe >= 0) {
00698 CmiSyncSendAndFree(pe, (red->msg_end) - (red->msg_begin), red->msg_begin);
00699 } else {
00700 CPathSend(CPATH_DESTELT, &(red->dest), red->desteltno,
00701 CPATH_TAGVEC, red->ntags, red->tags,
00702 CPATH_REDBYTES, red->vecsize, red->eltsize, red->msg_data,
00703 CPATH_END);
00704 CmiFree(red->msg_begin);
00705 }
00706
00707 set = red->over;
00708 hred = &(set->reductions);
00709 while (*hred) {
00710 if (*hred == red) *hred = red->next;
00711 else hred = &((*hred)->next);
00712 }
00713 free(red);
00714 }
00715
00716 void CPathMergeReduction(reduction red, void *data)
00717 {
00718 if (red->anydata) {
00719 CmiHandlerToFunction(red->reducer)(red->vecsize, red->msg_data, data);
00720 } else {
00721 memcpy(red->msg_data, data, red->vecsize * red->eltsize);
00722 }
00723 red->anydata = 1;
00724 red->waitcount--;
00725 if (red->waitcount==0) CPathForwardReduction(red);
00726 }
00727
00728 void CPathReduce(int key, ...)
00729 {
00730 CPath *over; int overidx[13];
00731 CPath *dest; int destidx[13];
00732 int desteltno;
00733 int ntags, tags[256];
00734 int reducer;
00735 int vecsize, eltsize; void *data;
00736 va_list p; int i;
00737 eltset set; reduction red;
00738
00739
00740 va_start(p, key);
00741 if (key != CPATH_OVER) goto synerr;
00742 over = va_arg(p, CPath *);
00743 for (i=0; i<over->nsizes; i++)
00744 overidx[i] = va_arg(p, int);
00745
00746 key = va_arg(p, int);
00747 switch(key) {
00748 case CPATH_TAG:
00749 ntags = 1;
00750 tags[0] = va_arg(p, int);
00751 break;
00752 case CPATH_TAGS:
00753 ntags = va_arg(p, int);
00754 if (ntags > 256) goto synerr;
00755 for (i=0; i<ntags; i++)
00756 tags[i] = va_arg(p, int);
00757 break;
00758 default: goto synerr;
00759 }
00760
00761 key = va_arg(p, int);
00762 if (key != CPATH_REDUCER) goto synerr;
00763 reducer = va_arg(p,int);
00764
00765 key = va_arg(p, int);
00766 if (key != CPATH_DEST) goto synerr;
00767 dest = va_arg(p, CPath *);
00768 for (i=0; i<dest->nsizes; i++)
00769 destidx[i] = va_arg(p,int);
00770 desteltno = CPathIndicesToEltno(dest->nsizes, dest->sizes, destidx);
00771
00772 key = va_arg(p, int);
00773 if (key != CPATH_BYTES) goto synerr;
00774 vecsize = va_arg(p, int);
00775 eltsize = va_arg(p, int);
00776 data = va_arg(p, void *);
00777
00778 key = va_arg(p, int);
00779 if (key != CPATH_END) goto synerr;
00780
00781 set = CPathGetEltset(over, overidx);
00782 red = CPathGetReduction
00783 (set, ntags, tags, vecsize, eltsize, reducer, dest, desteltno);
00784 CPathMergeReduction(red, data);
00785 return;
00786
00787 synerr:
00788 CmiError("CPathReduce: arglist must have these clauses: OVER, TAGS, REDUCER, DEST, BYTES, END (in that order).\n");
00789 exit(1);
00790 }
00791
00792 void CPathModuleInit(void)
00793 {
00794 CpvInitialize(int, seqno);
00795 CpvInitialize(int, CPathSendIdx);
00796 CpvInitialize(int, CPathReduceIdx);
00797 CpvInitialize(eltset *, EltsetTable);
00798 CpvInitialize(int, EltsetTabsize);
00799 CpvInitialize(single *, SingleTable);
00800 CpvInitialize(int, SingleTabsize);
00801 CpvInitialize(reduction *, ReduceTable);
00802 CpvInitialize(int, ReduceTabsize);
00803 CtvInitialize(single, thisthread);
00804 CpvInitialize(char *, PEflags);
00805 CpvInitialize(int *, PElist);
00806
00807 CpvAccess(seqno) = 0;
00808 CpvAccess(CPathSendIdx) = CmiRegisterHandler(CPathSendHandler);
00809 CpvAccess(CPathReduceIdx) = CmiRegisterHandler(CPathReduceHandler);
00810 CpvAccess(EltsetTabsize) = 1091;
00811 CpvAccess(EltsetTable) = (eltset*)calloc(1091,sizeof(eltset));
00812 CpvAccess(SingleTabsize) = 1091;
00813 CpvAccess(SingleTable) = (single*)calloc(1091,sizeof(single));
00814 CpvAccess(ReduceTabsize) = 1091;
00815 CpvAccess(ReduceTable) = (reduction*)calloc(1091,sizeof(reduction));
00816
00817 CpvAccess(PEflags) = (char*)calloc(1,CmiNumPes());
00818 CpvAccess(PElist) = (int*)malloc(CmiNumPes()*sizeof(int));
00819 _MEMCHECK(CpvAccess(PElist));
00820 }