4 #include "structdefs.h"
6 #include "checkpoint.h"
8 #include "SimpleHash.h"
9 #include "GenericHashtable.h"
10 #include <sys/select.h>
11 #include <sys/types.h>
20 #include <raw_compiler_defs.h>
21 //#include <libints.h>
22 #elif defined THREADSIMULATE
23 // use POSIX message queue
24 // for each core, its message queue named as
30 extern int injectfailures;
31 extern float failurechance;
37 #define TOTALCORE raw_get_num_tiles()
41 #include "instrument.h"
44 struct genhashtable * activetasks;
45 struct genhashtable * failedtasks;
46 struct taskparamdescriptor * currtpd;
48 struct RuntimeHash * forward;
49 struct RuntimeHash * reverse;
52 int corestatus[NUMCORES]; // records status of each core
55 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
56 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
58 struct RuntimeHash locktable;
59 static struct RuntimeHash* locktbl = &locktable;
60 void * curr_heapbase=0;
61 void * curr_heaptop=0;
63 int self_numreceiveobjs;
70 struct Queue objqueue;
81 void calCoords(int core_num, int* coordY, int* coordX);
82 #elif defined THREADSIMULATE
83 static struct RuntimeHash* locktbl;
91 struct thread_data thread_data_array[NUMCORES];
93 static pthread_key_t key;
94 static pthread_rwlock_t rwlock_tbl;
95 static pthread_rwlock_t rwlock_init;
100 bool transStallMsg(int targetcore);
101 void transTerminateMsg(int targetcore);
103 bool getreadlock(void* ptr);
104 void releasereadlock(void* ptr);
106 bool getreadlock_I(void* ptr);
107 void releasereadlock_I(void* ptr);
109 bool getwritelock(void* ptr);
110 void releasewritelock(void* ptr);
115 int main(int argc, char **argv) {
121 bool sendStall = false;
123 bool tocontinue = false;
124 struct QueueItem * objitem = NULL;
125 struct transObjInfo * objInfo = NULL;
127 bool allStall = true;
131 raw_test_pass(0xee01);
133 corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
135 // initialize the arrays
136 if(STARTUPCORE == corenum) {
137 // startup core to initialize corestatus[]
138 for(i = 0; i < NUMCORES; ++i) {
140 numsendobjs[i] = 0; // assume all variables in RAW are local variables! MAY BE WRONG!!!
141 numreceiveobjs[i] = 0;
144 self_numsendobjs = 0;
145 self_numreceiveobjs = 0;
146 for(i = 0; i < 30; ++i) {
154 for(i = 0; i < 30; ++i) {
160 isMsgHanging = false;
161 isMsgSending = false;
163 raw_test_pass(0xee02);
166 // create the lock table, lockresult table and obj queue
168 locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
169 /* Set allocation blocks*/
170 locktable.listhead=NULL;
171 locktable.listtail=NULL;
173 locktable.numelements = 0;
180 objqueue.head = NULL;
181 objqueue.tail = NULL;
183 raw_test_pass(0xee03);
187 if (corenum < NUMCORES) {
190 //setup_interrupts();
191 //start_gdn_avail_ints(recvMsg);
192 raw_user_interrupts_on();
194 raw_test_pass(0xee04);
199 #elif defined THREADSIMULATE
203 pthread_t threads[NUMCORES];
206 // initialize three arrays and msg queue array
207 char * pathhead = "/msgqueue_";
208 int targetlen = strlen(pathhead);
209 for(i = 0; i < NUMCORES; ++i) {
212 numreceiveobjs[i] = 0;
217 corenumstr[0] = i + '0';
218 corenumstr[1] = '\0';
221 corenumstr[1] = i %10 + '0';
222 corenumstr[0] = (i / 10) + '0';
223 corenumstr[2] = '\0';
226 printf("Error: i >= 100\n");
230 char path[targetlen + sourcelen + 1];
231 strcpy(path, pathhead);
232 strncat(path, corenumstr, sourcelen);
233 int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
234 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
236 mqd[i]= mq_open(path, oflags, omodes, NULL);
238 printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
241 printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
246 pthread_key_create(&key, NULL);
248 // create the lock table and initialize its mutex
249 locktbl = allocateRuntimeHash(20);
250 int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
251 printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
253 for(i = 0; i < NUMCORES; ++i) {
254 thread_data_array[i].corenum = i;
255 thread_data_array[i].argc = argc;
256 thread_data_array[i].argv = argv;
257 thread_data_array[i].numsendobjs = 0;
258 thread_data_array[i].numreceiveobjs = 0;
259 printf("[main] creating thread %d\n", i);
260 rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
262 printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
268 //pthread_exit(NULL);
273 void run(void* arg) {
274 struct thread_data * my_tdata = (struct thread_data *)arg;
275 pthread_setspecific(key, (void *)my_tdata->corenum);
276 int argc = my_tdata->argc;
277 char** argv = my_tdata->argv;
278 printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
284 GC_init(); // Initialize the garbage collector
292 initializeexithandler();
294 raw_test_pass(0xee05);
296 /* Create table for failed tasks */
298 if(corenum > NUMCORES - 1) {
306 raw_test_pass(0xee06);
309 /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
310 (int (*)(void *,void *)) &comparetpd);*/
313 raw_test_pass(0xee07);
315 /* Create queue of active tasks */
316 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
317 (int(*) (void *,void *)) &comparetpd);
319 raw_test_pass(0xee08);
322 /* Process task information */
325 raw_test_pass(0xee09);
328 if(STARTUPCORE == corenum) {
329 /* Create startup object */
330 createstartupobject(argc, argv);
333 raw_test_pass(0xee0a);
338 raw_test_pass(0xee0b);
343 while(receiveObject() != -1) {
347 // check if there are new active tasks can be executed
351 while(receiveObject() != -1) {
356 raw_test_pass(0xee0c);
359 // check if there are some pending objects, if yes, enqueue them and executetasks again
362 raw_test_pass(0xee0d);
364 while(!isEmpty(&objqueue)) {
367 raw_user_interrupts_off();
370 raw_test_pass(0xeee1);
374 objitem = getTail(&objqueue);
375 //obj = objitem->objectptr;
376 objInfo = (struct transObjInfo *)objitem->objectptr;
377 obj = objInfo->objptr;
379 raw_test_pass_reg((int)obj);
381 // grab lock and flush the obj
388 raw_test_pass_reg(grount);
400 raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
402 /*for(k = 0; k < classsize[((struct ___Object___ *)obj)->type]; ++k) {
403 invalidateAddr(obj + k);
405 // enqueue the object
406 for(k = 0; k < objInfo->length; ++k) {
407 int taskindex = objInfo->queues[2 * k];
408 int paramindex = objInfo->queues[2 * k + 1];
409 struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
411 raw_test_pass_reg(taskindex);
412 raw_test_pass_reg(paramindex);
414 enqueueObject_I(obj, queues, 1);
416 removeItem(&objqueue, objitem);
417 releasereadlock_I(obj);
418 RUNFREE(objInfo->queues);
420 /*enqueueObject_I(obj, NULL, 0);
421 removeItem(&objqueue, objitem);
422 releasereadlock_I(obj);*/
425 // put it at the end of the queue
426 // and try to execute active tasks already enqueued first
427 removeItem(&objqueue, objitem);
428 addNewItem_I(&objqueue, objInfo);
430 raw_user_interrupts_on();
435 raw_user_interrupts_on();
438 raw_test_pass(0xee0e);
442 raw_test_pass(0xee0f);
447 if(STARTUPCORE == corenum) {
450 raw_test_pass(0xee10);
455 raw_user_interrupts_off();
457 corestatus[corenum] = 0;
458 numsendobjs[corenum] = self_numsendobjs;
459 numreceiveobjs[corenum] = self_numreceiveobjs;
460 // check the status of all cores
463 raw_test_pass_reg(NUMCORES);
465 for(i = 0; i < NUMCORES; ++i) {
467 raw_test_pass(0xe000 + corestatus[i]);
469 if(corestatus[i] != 0) {
475 // check if the sum of send objs and receive obj are the same
477 // no->go on executing
479 for(i = 0; i < NUMCORES; ++i) {
480 sumsendobj += numsendobjs[i];
482 raw_test_pass(0xf000 + numsendobjs[i]);
485 for(i = 0; i < NUMCORES; ++i) {
486 sumsendobj -= numreceiveobjs[i];
488 raw_test_pass(0xf000 + numreceiveobjs[i]);
491 if(0 == sumsendobj) {
494 raw_test_pass(0xee11);
496 raw_test_pass(raw_get_cycle());
497 raw_test_done(1); // All done.
501 raw_user_interrupts_on();
506 raw_test_pass(0xee12);
509 // wait for some time
512 raw_test_pass(0xee13);
518 raw_test_pass(0xee14);
521 // send StallMsg to startup core
523 raw_test_pass(0xee15);
525 sendStall = transStallMsg(STARTUPCORE);
531 raw_test_pass(0xee16);
538 #elif defined THREADSIMULATE
539 /* Start executing the tasks */
543 // check if there are new objects coming
544 bool sendStall = false;
546 int numofcore = pthread_getspecific(key);
548 switch(receiveObject()) {
550 printf("[run, %d] receive an object\n", numofcore);
552 // received an object
553 // check if there are new active tasks can be executed
559 //printf("[run, %d] no msg\n", numofcore);
561 if(STARTUPCORE == numofcore) {
562 corestatus[numofcore] = 0;
563 // check the status of all cores
564 bool allStall = true;
565 for(i = 0; i < NUMCORES; ++i) {
566 if(corestatus[i] != 0) {
572 // check if the sum of send objs and receive obj are the same
574 // no->go on executing
576 for(i = 0; i < NUMCORES; ++i) {
577 sumsendobj += numsendobjs[i];
579 for(i = 0; i < NUMCORES; ++i) {
580 sumsendobj -= numreceiveobjs[i];
582 if(0 == sumsendobj) {
586 int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
587 printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
588 struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
589 while(0 != RunhasNext(it_lock)) {
590 int key = Runkey(it_lock);
591 pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
592 int rc_des = pthread_rwlock_destroy(rwlock_obj);
593 printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
596 freeRuntimeHash(locktbl);
600 // destroy all message queues
601 char * pathhead = "/msgqueue_";
602 int targetlen = strlen(pathhead);
603 for(i = 0; i < NUMCORES; ++i) {
607 corenumstr[0] = i + '0';
608 corenumstr[1] = '\0';
611 corenumstr[1] = i %10 + '0';
612 corenumstr[0] = (i / 10) + '0';
613 corenumstr[2] = '\0';
616 printf("Error: i >= 100\n");
620 char path[targetlen + sourcelen + 1];
621 strcpy(path, pathhead);
622 strncat(path, corenumstr, sourcelen);
626 printf("[run, %d] terminate!\n", numofcore);
633 // send StallMsg to startup core
634 sendStall = transStallMsg(STARTUPCORE);
641 printf("[run, %d] receive a stall msg\n", numofcore);
642 // receive a Stall Msg, do nothing
643 assert(STARTUPCORE == numofcore); // only startup core can receive such msg
649 printf("[run, %d] receive a terminate msg\n", numofcore);
650 // receive a terminate Msg
651 assert(STARTUPCORE != corenum); // only non-startup core can receive such msg
652 mq_close(mqd[corenum]);
658 printf("[run, %d] Error: invalid message type.\n", numofcore);
668 void createstartupobject(int argc, char ** argv) {
671 /* Allocate startup object */
673 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
674 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
676 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
677 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
679 /* Build array of strings */
680 startupobject->___parameters___=stringarray;
681 for(i=1; i<argc; i++) {
682 int length=strlen(argv[i]);
684 struct ___String___ *newstring=NewString(NULL, argv[i],length);
686 struct ___String___ *newstring=NewString(argv[i],length);
688 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
691 startupobject->isolate = 1;
692 startupobject->version = 0;
694 /* Set initialized flag for startup object */
695 flagorandinit(startupobject,1,0xFFFFFFFF);
696 enqueueObject(startupobject, NULL, 0);
699 raw_flush_entire_cache();
703 int hashCodetpd(struct taskparamdescriptor *ftd) {
704 int hash=(int)ftd->task;
706 for(i=0; i<ftd->numParameters; i++){
707 hash^=(int)ftd->parameterArray[i];
712 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
714 if (ftd1->task!=ftd2->task)
716 for(i=0; i<ftd1->numParameters; i++)
717 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
722 /* This function sets a tag. */
724 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
726 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
728 struct ArrayObject * ao=NULL;
729 struct ___Object___ * tagptr=obj->___tags___;
731 raw_test_pass(0xebb0);
735 raw_test_pass(0xebb1);
737 obj->___tags___=(struct ___Object___ *)tagd;
739 /* Have to check if it is already set */
740 if (tagptr->type==TAGTYPE) {
741 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
743 raw_test_pass(0xebb2);
747 raw_test_pass(0xebb3);
752 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
753 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
754 obj=(struct ___Object___ *)ptrarray[2];
755 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
756 td=(struct ___TagDescriptor___ *) obj->___tags___;
759 raw_test_pass(0xebb4);
761 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
764 raw_test_pass(0xebb5);
766 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
767 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
768 obj->___tags___=(struct ___Object___ *) ao;
769 ao->___cachedCode___=2;
771 raw_test_pass(0xebb6);
776 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
778 raw_test_pass(0xebb7);
780 for(i=0; i<ao->___cachedCode___; i++) {
781 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
783 raw_test_pass(0xebb8);
787 raw_test_pass(0xebb9);
792 if (ao->___cachedCode___<ao->___length___) {
794 raw_test_pass(0xebba);
796 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
797 ao->___cachedCode___++;
799 raw_test_pass(0xebbb);
803 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
804 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
805 obj=(struct ___Object___ *)ptrarray[2];
806 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
807 ao=(struct ArrayObject *)obj->___tags___;
809 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
812 raw_test_pass(0xebbc);
814 aonew->___cachedCode___=ao->___length___+1;
815 for(i=0; i<ao->___length___; i++) {
817 raw_test_pass(0xebbd);
819 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
822 raw_test_pass(0xebbe);
824 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
826 raw_test_pass(0xebbf);
833 struct ___Object___ * tagset=tagd->flagptr;
835 raw_test_pass(0xb008);
839 raw_test_pass(0xb009);
842 } else if (tagset->type!=OBJECTARRAYTYPE) {
844 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
845 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
846 obj=(struct ___Object___ *)ptrarray[2];
847 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
849 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
851 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
852 ARRAYSET(ao, struct ___Object___ *, 1, obj);
853 ao->___cachedCode___=2;
854 tagd->flagptr=(struct ___Object___ *)ao;
856 raw_test_pass(0xb00a);
859 struct ArrayObject *ao=(struct ArrayObject *) tagset;
860 if (ao->___cachedCode___<ao->___length___) {
862 raw_test_pass(0xb00b);
864 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
868 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
869 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
870 obj=(struct ___Object___ *)ptrarray[2];
871 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
872 ao=(struct ArrayObject *)tagd->flagptr;
874 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
876 aonew->___cachedCode___=ao->___cachedCode___+1;
877 for(i=0; i<ao->___length___; i++) {
878 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
880 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
881 tagd->flagptr=(struct ___Object___ *) aonew;
883 raw_test_pass(0xb00c);
890 /* This function clears a tag. */
892 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
894 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
896 /* We'll assume that tag is alway there.
897 Need to statically check for this of course. */
898 struct ___Object___ * tagptr=obj->___tags___;
900 if (tagptr->type==TAGTYPE) {
901 if ((struct ___TagDescriptor___ *)tagptr==tagd)
902 obj->___tags___=NULL;
905 printf("ERROR 1 in tagclear\n");
909 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
911 for(i=0; i<ao->___cachedCode___; i++) {
912 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
914 ao->___cachedCode___--;
915 if (i<ao->___cachedCode___)
916 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
917 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
918 if (ao->___cachedCode___==0)
919 obj->___tags___=NULL;
924 printf("ERROR 2 in tagclear\n");
930 struct ___Object___ *tagset=tagd->flagptr;
931 if (tagset->type!=OBJECTARRAYTYPE) {
936 printf("ERROR 3 in tagclear\n");
940 struct ArrayObject *ao=(struct ArrayObject *) tagset;
942 for(i=0; i<ao->___cachedCode___; i++) {
943 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
945 ao->___cachedCode___--;
946 if (i<ao->___cachedCode___)
947 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
948 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
949 if (ao->___cachedCode___==0)
955 printf("ERROR 4 in tagclear\n");
963 /* This function allocates a new tag. */
965 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
966 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
968 struct ___TagDescriptor___ * allocate_tag(int index) {
969 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
978 /* This function updates the flag for object ptr. It or's the flag
979 with the or mask and and's it with the andmask. */
981 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
983 int flagcomp(const int *val1, const int *val2) {
984 return (*val1)-(*val2);
987 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
989 int oldflag=((int *)ptr)[1];
990 int flag=ormask|oldflag;
993 raw_test_pass_reg((int)ptr);
994 raw_test_pass(0xaa000000 + oldflag);
995 raw_test_pass(0xaa000000 + flag);
997 flagbody(ptr, flag, queues, length, false);
1001 bool intflagorand(void * ptr, int ormask, int andmask) {
1003 int oldflag=((int *)ptr)[1];
1004 int flag=ormask|oldflag;
1006 if (flag==oldflag) /* Don't do anything */
1009 flagbody(ptr, flag, NULL, 0, false);
1015 void flagorandinit(void * ptr, int ormask, int andmask) {
1016 int oldflag=((int *)ptr)[1];
1017 int flag=ormask|oldflag;
1020 raw_test_pass(0xaa100000 + oldflag);
1021 raw_test_pass(0xaa100000 + flag);
1023 flagbody(ptr,flag,NULL,0,true);
1026 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1027 struct parameterwrapper * flagptr = NULL;
1029 struct parameterwrapper ** queues = vqueues;
1030 int length = vlength;
1032 int UNUSED, UNUSED2;
1033 int * enterflags = NULL;
1034 if((!isnew) && (queues == NULL)) {
1035 #ifdef THREADSIMULATE
1036 int numofcore = pthread_getspecific(key);
1037 queues = objectqueues[numofcore][ptr->type];
1038 length = numqueues[numofcore][ptr->type];
1041 if(corenum < NUMCORES) {
1043 queues = objectqueues[corenum][ptr->type];
1044 length = numqueues[corenum][ptr->type];
1054 raw_test_pass(0xbb000000 + ptr->flag);
1057 /*Remove object from all queues */
1058 for(i = 0; i < length; ++i) {
1059 flagptr = queues[i];
1060 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1061 ObjectHashremove(flagptr->objectset, (int)ptr);
1062 if (enterflags!=NULL)
1063 RUNFREE(enterflags);
1067 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1068 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1071 struct QueueItem *tmpptr;
1072 struct parameterwrapper * parameter=NULL;
1075 struct parameterwrapper * prevptr=NULL;
1076 struct ___Object___ *tagptr=NULL;
1077 struct parameterwrapper ** queues = vqueues;
1078 int length = vlength;
1080 if(corenum > NUMCORES - 1) {
1084 if(queues == NULL) {
1085 #ifdef THREADSIMULATE
1086 int numofcore = pthread_getspecific(key);
1087 queues = objectqueues[numofcore][ptr->type];
1088 length = numqueues[numofcore][ptr->type];
1090 queues = objectqueues[corenum][ptr->type];
1091 length = numqueues[corenum][ptr->type];
1094 tagptr=ptr->___tags___;
1096 /* Outer loop iterates through all parameter queues an object of
1097 this type could be in. */
1098 for(j = 0; j < length; ++j) {
1099 parameter = queues[j];
1101 if (parameter->numbertags>0) {
1103 goto nextloop; //that means the object has no tag but that param needs tag
1104 else if(tagptr->type==TAGTYPE) { //one tag
1105 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1106 for(i=0; i<parameter->numbertags; i++) {
1107 //slotid is parameter->tagarray[2*i];
1108 int tagid=parameter->tagarray[2*i+1];
1109 if (tagid!=tagptr->flag)
1110 goto nextloop; /*We don't have this tag */
1112 } else { //multiple tags
1113 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1114 for(i=0; i<parameter->numbertags; i++) {
1115 //slotid is parameter->tagarray[2*i];
1116 int tagid=parameter->tagarray[2*i+1];
1118 for(j=0; j<ao->___cachedCode___; j++) {
1119 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1130 for(i=0; i<parameter->numberofterms; i++) {
1131 int andmask=parameter->intarray[i*2];
1132 int checkmask=parameter->intarray[i*2+1];
1133 if ((ptr->flag&andmask)==checkmask) {
1135 raw_test_pass(0xcc000000 + andmask);
1136 raw_test_pass_reg((int)ptr);
1137 raw_test_pass(0xcc000000 + ptr->flag);
1138 raw_test_pass(0xcc000000 + checkmask);
1140 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1152 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1153 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1156 struct QueueItem *tmpptr;
1157 struct parameterwrapper * parameter=NULL;
1160 struct parameterwrapper * prevptr=NULL;
1161 struct ___Object___ *tagptr=NULL;
1162 struct parameterwrapper ** queues = vqueues;
1163 int length = vlength;
1165 if(corenum > NUMCORES - 1) {
1169 if(queues == NULL) {
1170 #ifdef THREADSIMULATE
1171 int numofcore = pthread_getspecific(key);
1172 queues = objectqueues[numofcore][ptr->type];
1173 length = numqueues[numofcore][ptr->type];
1175 queues = objectqueues[corenum][ptr->type];
1176 length = numqueues[corenum][ptr->type];
1180 raw_test_pass(0xeaa1);
1181 raw_test_pass_reg(queues);
1182 raw_test_pass_reg(length);
1184 tagptr=ptr->___tags___;
1186 /* Outer loop iterates through all parameter queues an object of
1187 this type could be in. */
1188 for(j = 0; j < length; ++j) {
1189 parameter = queues[j];
1191 if (parameter->numbertags>0) {
1193 raw_test_pass(0xeaa2);
1194 raw_test_pass_reg(tagptr);
1197 goto nextloop; //that means the object has no tag but that param needs tag
1198 else if(tagptr->type==TAGTYPE) { //one tag
1199 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1201 raw_test_pass(0xeaa3);
1203 for(i=0; i<parameter->numbertags; i++) {
1204 //slotid is parameter->tagarray[2*i];
1205 int tagid=parameter->tagarray[2*i+1];
1206 if (tagid!=tagptr->flag) {
1208 raw_test_pass(0xeaa4);
1210 goto nextloop; /*We don't have this tag */
1213 } else { //multiple tags
1214 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1216 raw_test_pass(0xeaa5);
1218 for(i=0; i<parameter->numbertags; i++) {
1219 //slotid is parameter->tagarray[2*i];
1220 int tagid=parameter->tagarray[2*i+1];
1222 for(j=0; j<ao->___cachedCode___; j++) {
1223 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1228 raw_test_pass(0xeaa6);
1238 for(i=0; i<parameter->numberofterms; i++) {
1239 int andmask=parameter->intarray[i*2];
1240 int checkmask=parameter->intarray[i*2+1];
1242 raw_test_pass(0xeaa7);
1243 raw_test_pass(0xcc000000 + andmask);
1244 raw_test_pass_reg(ptr);
1245 raw_test_pass(0xcc000000 + ptr->flag);
1246 raw_test_pass(0xcc000000 + checkmask);
1248 if ((ptr->flag&andmask)==checkmask) {
1250 raw_test_pass(0xeaa8);
1252 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1263 // helper function to compute the coordinates of a core from the core number
1264 void calCoords(int core_num, int* coordY, int* coordX) {
1265 *coordX = core_num % 4;
1266 *coordY = core_num / 4;
1270 /* Message format for RAW version:
1272 * type: 0 -- transfer object
1273 * 1 -- transfer stall msg
1279 * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1280 * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1281 * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
1282 * 3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
1283 * lock type: 0 -- read; 1 -- write
1286 // transfer an object to targetcore
1288 void transferObject(struct transObjInfo * transObj) {
1289 void * obj = transObj->objptr;
1290 int type=((int *)obj)[0];
1291 int size=classsize[type];
1292 int targetcore = transObj->targetcore;
1293 //assert(type < NUMCLASSES); // can only transfer normal object
1297 int self_y, self_x, target_y, target_x;
1299 // for 32 bit machine, the size of fixed part is always 3 words
1300 //int msgsize = sizeof(int) * 2 + sizeof(void *);
1301 int msgsize = 3 + transObj->length * 2;
1304 struct ___Object___ * newobj = (struct ___Object___ *)obj;
1305 /*if(0 == newobj->isolate) {
1309 calCoords(corenum, &self_y, &self_x);
1310 calCoords(targetcore, &target_y, &target_x);
1311 // Build the message header
1312 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1314 target_y, target_x);
1315 // start sending msg, set sand msg flag
1316 isMsgSending = true;
1317 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1319 raw_test_pass(0xbbbb);
1320 raw_test_pass(0xb000 + targetcore); // targetcore
1328 raw_test_pass_reg(msgsize);
1332 raw_test_pass_reg(obj);
1334 for(i = 0; i < transObj->length; ++i) {
1335 int taskindex = transObj->queues[2*i];
1336 int paramindex = transObj->queues[2*i+1];
1337 gdn_send(taskindex);
1339 raw_test_pass_reg(taskindex);
1341 gdn_send(paramindex);
1343 raw_test_pass_reg(paramindex);
1347 raw_test_pass(0xffff);
1349 ++(self_numsendobjs);
1350 // end of sending this msg, set sand msg flag false
1351 isMsgSending = false;
1352 // check if there are pending msgs
1353 while(isMsgHanging) {
1354 // get the msg from outmsgdata[]
1355 // length + target + msg
1356 outmsgleft = outmsgdata[outmsgindex++];
1357 targetcore = outmsgdata[outmsgindex++];
1358 calCoords(targetcore, &target_y, &target_x);
1359 // Build the message header
1360 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1362 target_y, target_x);
1363 isMsgSending = true;
1364 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1366 raw_test_pass(0xbbbb);
1367 raw_test_pass(0xb000 + targetcore); // targetcore
1369 while(outmsgleft-- > 0) {
1370 gdn_send(outmsgdata[outmsgindex++]);
1372 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1376 raw_test_pass(0xffff);
1378 isMsgSending = false;
1380 raw_user_interrupts_off();
1382 // check if there are still msg hanging
1383 if(outmsgindex == outmsglast) {
1385 outmsgindex = outmsglast = 0;
1386 isMsgHanging = false;
1389 raw_user_interrupts_on();
1392 #elif defined THREADSIMULATE
1393 int numofcore = pthread_getspecific(key);
1395 // use POSIX message queue to transfer objects between cores
1399 if(targetcore < 10) {
1400 corenumstr[0] = targetcore + '0';
1401 corenumstr[1] = '\0';
1403 } else if(targetcore < 100) {
1404 corenumstr[1] = targetcore % 10 + '0';
1405 corenumstr[0] = (targetcore / 10) + '0';
1406 corenumstr[2] = '\0';
1409 printf("Error: targetcore >= 100\n");
1413 char * pathhead = "/msgqueue_";
1414 int targetlen = strlen(pathhead);
1415 char path[targetlen + sourcelen + 1];
1416 strcpy(path, pathhead);
1417 strncat(path, corenumstr, sourcelen);
1418 int oflags = O_WRONLY|O_NONBLOCK;
1419 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1420 mqdnum = mq_open(path, oflags, omodes, NULL);
1422 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1426 /*struct ___Object___ * newobj = (struct ___Object___ *)obj;
1427 if(0 == newobj->isolate) {
1428 newobj = RUNMALLOC(size);
1429 memcpy(newobj, obj, size);
1430 newobj->original=obj;
1432 struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1433 memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1434 int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1435 memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1436 tmptransObj->queues = tmpqueue;
1437 struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1438 newobj->type = ((struct ___Object___ *)obj)->type;
1439 newobj->original = (struct ___Object___ *)tmptransObj;
1442 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1444 printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1448 if(numofcore == STARTUPCORE) {
1449 ++numsendobjs[numofcore];
1451 ++(thread_data_array[numofcore].numsendobjs);
1453 printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1457 // send terminate message to targetcore
1459 bool transStallMsg(int targetcore) {
1462 int self_y, self_x, target_y, target_x;
1463 // for 32 bit machine, the size is always 4 words
1464 //int msgsize = sizeof(int) * 4;
1467 calCoords(corenum, &self_y, &self_x);
1468 calCoords(targetcore, &target_y, &target_x);
1469 // Build the message header
1470 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1472 target_y, target_x);
1473 // start sending msgs, set msg sending flag
1474 isMsgSending = true;
1475 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1477 raw_test_pass(0xbbbb);
1478 raw_test_pass(0xb000 + targetcore); // targetcore
1486 raw_test_pass_reg(corenum);
1488 gdn_send(self_numsendobjs);
1490 raw_test_pass_reg(self_numsendobjs);
1492 gdn_send(self_numreceiveobjs);
1494 raw_test_pass_reg(self_numreceiveobjs);
1495 raw_test_pass(0xffff);
1497 // end of sending this msg, set sand msg flag false
1498 isMsgSending = false;
1499 // check if there are pending msgs
1500 while(isMsgHanging) {
1501 // get the msg from outmsgdata[]
1502 // length + target + msg
1503 outmsgleft = outmsgdata[outmsgindex++];
1504 targetcore = outmsgdata[outmsgindex++];
1505 calCoords(targetcore, &target_y, &target_x);
1506 // Build the message header
1507 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1509 target_y, target_x);
1510 isMsgSending = true;
1511 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1513 raw_test_pass(0xbbbb);
1514 raw_test_pass(0xb000 + targetcore); // targetcore
1516 while(outmsgleft-- > 0) {
1517 gdn_send(outmsgdata[outmsgindex++]);
1519 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1523 raw_test_pass(0xffff);
1525 isMsgSending = false;
1527 raw_user_interrupts_off();
1529 // check if there are still msg hanging
1530 if(outmsgindex == outmsglast) {
1532 outmsgindex = outmsglast = 0;
1533 isMsgHanging = false;
1536 raw_user_interrupts_on();
1540 #elif defined THREADSIMULATE
1541 struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1542 // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1544 int numofcore = pthread_getspecific(key);
1545 newobj->flag = numofcore;
1546 newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1547 newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1549 // use POSIX message queue to send stall msg to startup core
1550 assert(targetcore == STARTUPCORE);
1554 if(targetcore < 10) {
1555 corenumstr[0] = targetcore + '0';
1556 corenumstr[1] = '\0';
1558 } else if(targetcore < 100) {
1559 corenumstr[1] = targetcore % 10 + '0';
1560 corenumstr[0] = (targetcore / 10) + '0';
1561 corenumstr[2] = '\0';
1564 printf("Error: targetcore >= 100\n");
1568 char * pathhead = "/msgqueue_";
1569 int targetlen = strlen(pathhead);
1570 char path[targetlen + sourcelen + 1];
1571 strcpy(path, pathhead);
1572 strncat(path, corenumstr, sourcelen);
1573 int oflags = O_WRONLY|O_NONBLOCK;
1574 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1575 mqdnum = mq_open(path, oflags, omodes, NULL);
1577 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1582 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1584 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1588 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1589 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1596 // receive object transferred from other cores
1597 // or the terminate message from other cores
1598 // NOTICE: following format is for threadsimulate version only
1599 // RAW version please see previous description
1600 // format: type + object
1601 // type: -1--stall msg
1603 // return value: 0--received an object
1604 // 1--received nothing
1605 // 2--received a Stall Msg
1606 // 3--received a lock Msg
1607 // RAW version: -1 -- received nothing
1608 // otherwise -- received msg type
1609 int receiveObject() {
1613 int self_y, self_x, target_y, target_x;
1615 if(gdn_input_avail() == 0) {
1617 if(corenum < NUMCORES) {
1618 raw_test_pass(0xd001);
1625 raw_test_pass(0xcccc);
1627 while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
1628 msgdata[msgdataindex] = gdn_receive();
1629 if(msgdataindex == 0) {
1630 if(msgdata[0] > 2) {
1632 } else if(msgdata[0] > 0) {
1635 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
1636 msglength = msgdata[msgdataindex];
1639 raw_test_pass_reg(msgdata[msgdataindex]);
1643 /*if(msgdataindex == 0) {
1645 msgtype = gdn_receive();
1652 msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
1653 msgdata[msgdataindex] = msgtype;
1656 raw_test_pass_reg(msgtype);
1658 } else if((msgdataindex == 1) && (msgtype == 0)) {
1659 // object transfer msg
1660 msglength = gdn_receive();
1661 msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
1662 msgdata[0] = msgtype;
1663 msgdata[msgdataindex] = msglength;
1665 raw_test_pass_reg(msgdata[msgdataindex]);
1668 msgdata[msgdataindex] = gdn_receive();
1670 raw_test_pass_reg(msgdata[msgdataindex]);
1676 raw_test_pass(0xffff);
1678 if(msgdataindex == msglength) {
1679 // received a whole msg
1680 int type, data1, data2; // will receive at least 3 words including type
1686 // receive a object transfer msg
1687 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
1689 if(corenum > NUMCORES - 1) {
1690 raw_test_done(0xa00a);
1692 // store the object and its corresponding queue info, enqueue it later
1693 transObj->objptr = (void *)data2; // data1 is now size of the msg
1694 transObj->length = (msglength - 3) / 2;
1695 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1696 for(k = 0; k < transObj->length; ++k) {
1697 transObj->queues[2*k] = msgdata[3+2*k];
1699 raw_test_pass_reg(transObj->queues[2*k]);
1701 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1703 raw_test_pass_reg(transObj->queues[2*k+1]);
1706 // check if there is an existing duplicate item
1708 struct QueueItem * qitem = getTail(&objqueue);
1709 struct QueueItem * prev = NULL;
1710 while(qitem != NULL) {
1711 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
1712 if(tmpinfo->objptr == transObj->objptr) {
1713 // the same object, remove outdate one
1714 removeItem(&objqueue, qitem);
1719 qitem = getTail(&objqueue);
1721 qitem = getNext(prev);
1724 //memcpy(transObj->queues, msgdata[3], sizeof(int)*(msglength - 3));
1725 addNewItem_I(&objqueue, (void *)transObj);
1727 ++(self_numreceiveobjs);
1729 raw_test_pass(0xe881);
1732 addNewItem_I(&objqueue, (void *)data2);
1733 ++(self_numreceiveobjs);
1735 raw_test_pass(0xe881);
1742 // receive a stall msg
1743 if(corenum != STARTUPCORE) {
1744 // non startup core can not receive stall msg
1746 raw_test_done(0xa001);
1748 if(data1 < NUMCORES) {
1750 raw_test_pass(0xe882);
1752 corestatus[data1] = 0;
1753 numsendobjs[data1] = data2;
1754 numreceiveobjs[data1] = msgdata[3];
1760 // receive lock request msg
1761 // for 32 bit machine, the size is always 3 words
1762 //int msgsize = sizeof(int) * 3;
1764 // lock request msg, handle it right now
1765 // check to see if there is a lock exist in locktbl for the required obj
1766 int data3 = msgdata[3];
1768 if(!RuntimeHashcontainskey(locktbl, data2)) {
1769 // no locks for this object
1770 // first time to operate on this shared object
1771 // create a lock for it
1772 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
1774 raw_test_pass(0xe883);
1777 RuntimeHashadd_I(locktbl, data2, 1);
1779 RuntimeHashadd_I(locktbl, data2, -1);
1784 raw_test_pass(0xe884);
1786 RuntimeHashget(locktbl, data2, &rwlock_obj);
1788 raw_test_pass_reg(rwlock_obj);
1790 if(0 == rwlock_obj) {
1796 RuntimeHashremovekey(locktbl, data2);
1797 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1798 } else if((rwlock_obj > 0) && (data1 == 0)) {
1799 // read lock request and there are only read locks
1801 RuntimeHashremovekey(locktbl, data2);
1802 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1807 raw_test_pass_reg(rwlock_obj);
1811 // check if there is still some msg on sending
1814 raw_test_pass(0xe885);
1816 isMsgHanging = true;
1817 // cache the msg in outmsgdata and send it later
1818 // msglength + target core + msg
1819 outmsgdata[outmsglast++] = msgsize;
1820 outmsgdata[outmsglast++] = targetcore;
1822 outmsgdata[outmsglast++] = 4;
1824 outmsgdata[outmsglast++] = 3;
1826 outmsgdata[outmsglast++] = data1;
1827 outmsgdata[outmsglast++] = data2;
1830 raw_test_pass(0xe886);
1832 // no msg on sending, send it out
1833 calCoords(corenum, &self_y, &self_x);
1834 calCoords(targetcore, &target_y, &target_x);
1835 // Build the message header
1836 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1838 target_y, target_x);
1839 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1841 raw_test_pass(0xbbbb);
1842 raw_test_pass(0xb000 + targetcore); // targetcore
1845 // deny the lock request
1846 gdn_send(4); // lock request
1851 // grount the lock request
1852 gdn_send(3); // lock request
1857 gdn_send(data1); // lock type
1859 raw_test_pass_reg(data1);
1861 gdn_send(data2); // lock target
1863 raw_test_pass_reg(data2);
1864 raw_test_pass(0xffff);
1871 // receive lock grount msg
1872 if(corenum > NUMCORES - 1) {
1873 raw_test_done(0xa00b);
1875 if(lockobj == data2) {
1882 // conflicts on lockresults
1883 raw_test_done(0xa002);
1889 // receive lock grount/deny msg
1890 if(corenum > NUMCORES - 1) {
1891 raw_test_done(0xa00c);
1893 if(lockobj == data2) {
1900 // conflicts on lockresults
1901 raw_test_done(0xa003);
1907 // receive lock release msg
1908 if(!RuntimeHashcontainskey(locktbl, data2)) {
1909 // no locks for this object, something is wrong
1910 raw_test_done(0xa004);
1913 RuntimeHashget(locktbl, data2, &rwlock_obj);
1915 raw_test_pass(0xe887);
1916 raw_test_pass_reg(rwlock_obj);
1923 RuntimeHashremovekey(locktbl, data2);
1924 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1926 raw_test_pass_reg(rwlock_obj);
1937 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1938 msgdata[msgdataindex] = -1;
1944 raw_test_pass(0xe888);
1946 if(gdn_input_avail() != 0) {
1953 raw_test_pass(0xe889);
1957 #elif defined THREADSIMULATE
1958 int numofcore = pthread_getspecific(key);
1959 // use POSIX message queue to transfer object
1961 struct mq_attr mqattr;
1962 mq_getattr(mqd[numofcore], &mqattr);
1963 void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
1964 msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
1970 //printf("msg: %s\n",msgptr);
1971 if(((int*)msgptr)[0] == -1) {
1973 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
1974 int index = tmpptr->flag;
1975 corestatus[index] = 0;
1976 numsendobjs[index] = tmpptr->___cachedHash___;
1977 numreceiveobjs[index] = tmpptr->___cachedCode___;
1978 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
1981 } /*else if(((int*)msgptr)[0] == -2) {
1987 if(numofcore == STARTUPCORE) {
1988 ++(numreceiveobjs[numofcore]);
1990 ++(thread_data_array[numofcore].numreceiveobjs);
1992 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
1993 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
1994 tmpptr = (struct ___Object___ *)(transObj->objptr);
1995 int type = tmpptr->type;
1996 int size=classsize[type];
1997 struct ___Object___ * newobj=RUNMALLOC(size);
1998 memcpy(newobj, tmpptr, size);
1999 if(0 == newobj->isolate) {
2000 newobj->original=tmpptr;
2005 for(k = 0; k < transObj->length; ++k) {
2006 int taskindex = transObj->queues[2 * k];
2007 int paramindex = transObj->queues[2 * k + 1];
2008 struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2009 enqueueObject(newobj, queues, 1);
2011 RUNFREE(transObj->queues);
2018 bool getreadlock(void * ptr) {
2021 int self_y, self_x, target_y, target_x;
2022 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2023 // for 32 bit machine, the size is always 4 words
2024 //int msgsize = sizeof(int) * 4;
2028 raw_user_interrupts_off();
2030 targetcore = ((int)ptr >> 5) % tc;
2032 raw_user_interrupts_on();
2042 if(targetcore == corenum) {
2043 // reside on this core
2046 raw_user_interrupts_off();
2048 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2049 // no locks for this object
2050 // first time to operate on this shared object
2051 // create a lock for it
2052 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2053 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2056 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2057 if(-1 != rwlock_obj) {
2059 RuntimeHashremovekey(locktbl, (int)ptr);
2060 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2066 raw_user_interrupts_on();
2068 if(lockobj == (int)ptr) {
2079 // conflicts on lockresults
2080 raw_test_done(0xa005);
2085 calCoords(corenum, &self_y, &self_x);
2086 calCoords(targetcore, &target_y, &target_x);
2087 // Build the message header
2088 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2090 target_y, target_x);
2091 // start sending the msg, set send msg flag
2092 isMsgSending = true;
2093 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2095 raw_test_pass(0xbbbb);
2096 raw_test_pass(0xb000 + targetcore); // targetcore
2098 gdn_send(2); // lock request
2102 gdn_send(0); // read lock
2108 raw_test_pass_reg(ptr);
2112 raw_test_pass_reg(corenum);
2113 raw_test_pass(0xffff);
2115 // end of sending this msg, set sand msg flag false
2116 isMsgSending = false;
2117 // check if there are pending msgs
2118 while(isMsgHanging) {
2119 // get the msg from outmsgdata[]
2120 // length + target + msg
2121 outmsgleft = outmsgdata[outmsgindex++];
2122 targetcore = outmsgdata[outmsgindex++];
2123 calCoords(targetcore, &target_y, &target_x);
2124 // Build the message header
2125 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2127 target_y, target_x);
2128 isMsgSending = true;
2129 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2131 raw_test_pass(0xbbbb);
2132 raw_test_pass(0xb000 + targetcore); // targetcore
2134 while(outmsgleft-- > 0) {
2135 gdn_send(outmsgdata[outmsgindex++]);
2137 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2141 raw_test_pass(0xffff);
2143 isMsgSending = false;
2145 raw_user_interrupts_off();
2147 // check if there are still msg hanging
2148 if(outmsgindex == outmsglast) {
2150 outmsgindex = outmsglast = 0;
2151 isMsgHanging = false;
2154 raw_user_interrupts_on();
2158 #elif defined THREADSIMULATE
2159 int numofcore = pthread_getspecific(key);
2161 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2162 printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2166 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2167 // no locks for this object
2168 // first time to operate on this shared object
2169 // create a lock for it
2170 rc = pthread_rwlock_unlock(&rwlock_tbl);
2171 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2172 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2173 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2174 rc = pthread_rwlock_init(rwlock, NULL);
2175 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2176 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2177 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2182 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2184 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2187 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2189 rc = pthread_rwlock_unlock(&rwlock_tbl);
2190 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2192 rc = pthread_rwlock_tryrdlock(rwlock);
2193 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2200 pthread_rwlock_t* rwlock_obj = NULL;
2201 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2202 rc = pthread_rwlock_unlock(&rwlock_tbl);
2203 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2204 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
2205 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2215 void releasereadlock(void * ptr) {
2218 int self_y, self_x, target_y, target_x;
2219 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2220 // for 32 bit machine, the size is always 3 words
2221 //int msgsize = sizeof(int) * 3;
2225 raw_user_interrupts_off();
2227 targetcore = ((int)ptr >> 5) % tc;
2229 raw_user_interrupts_on();
2232 if(targetcore == corenum) {
2234 raw_user_interrupts_off();
2236 // reside on this core
2237 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2238 // no locks for this object, something is wrong
2239 raw_test_done(0xa006);
2242 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2244 RuntimeHashremovekey(locktbl, (int)ptr);
2245 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2248 raw_user_interrupts_on();
2253 calCoords(corenum, &self_y, &self_x);
2254 calCoords(targetcore, &target_y, &target_x);
2255 // Build the message header
2256 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2258 target_y, target_x);
2259 // start sending the msg, set send msg flag
2260 isMsgSending = true;
2261 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2263 raw_test_pass(0xbbbb);
2264 raw_test_pass(0xb000 + targetcore); // targetcore
2266 gdn_send(5); // lock release
2270 gdn_send(0); // read lock
2276 raw_test_pass_reg(ptr);
2277 raw_test_pass(0xffff);
2279 // end of sending this msg, set sand msg flag false
2280 isMsgSending = false;
2281 // check if there are pending msgs
2282 while(isMsgHanging) {
2283 // get the msg from outmsgdata[]
2284 // length + target + msg
2285 outmsgleft = outmsgdata[outmsgindex++];
2286 targetcore = outmsgdata[outmsgindex++];
2287 calCoords(targetcore, &target_y, &target_x);
2288 // Build the message header
2289 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2291 target_y, target_x);
2292 isMsgSending = true;
2293 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2295 raw_test_pass(0xbbbb);
2296 raw_test_pass(0xb000 + targetcore); // targetcore
2298 while(outmsgleft-- > 0) {
2299 gdn_send(outmsgdata[outmsgindex++]);
2301 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2305 raw_test_pass(0xffff);
2307 isMsgSending = false;
2309 raw_user_interrupts_off();
2311 // check if there are still msg hanging
2312 if(outmsgindex == outmsglast) {
2314 outmsgindex = outmsglast = 0;
2315 isMsgHanging = false;
2318 raw_user_interrupts_on();
2321 #elif defined THREADSIMULATE
2322 int numofcore = pthread_getspecific(key);
2323 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2324 printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2325 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2326 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2329 pthread_rwlock_t* rwlock_obj = NULL;
2330 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2331 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2332 printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2333 rc = pthread_rwlock_unlock(&rwlock_tbl);
2334 printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2339 bool getreadlock_I(void * ptr) {
2341 int self_y, self_x, target_y, target_x;
2342 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2343 // for 32 bit machine, the size is always 4 words
2344 //int msgsize = sizeof(int) * 4;
2354 if(targetcore == corenum) {
2355 // reside on this core
2357 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2358 // no locks for this object
2359 // first time to operate on this shared object
2360 // create a lock for it
2361 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2362 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2365 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2366 if(-1 != rwlock_obj) {
2368 RuntimeHashremovekey(locktbl, (int)ptr);
2369 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2374 if(lockobj == (int)ptr) {
2385 // conflicts on lockresults
2386 raw_test_done(0xa005);
2391 calCoords(corenum, &self_y, &self_x);
2392 calCoords(targetcore, &target_y, &target_x);
2393 // Build the message header
2394 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2396 target_y, target_x);
2397 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2399 raw_test_pass(0xbbbb);
2400 raw_test_pass(0xb000 + targetcore); // targetcore
2402 gdn_send(2); // lock request
2406 gdn_send(0); // read lock
2412 raw_test_pass_reg(ptr);
2416 raw_test_pass_reg(corenum);
2417 raw_test_pass(0xffff);
2422 void releasereadlock_I(void * ptr) {
2424 int self_y, self_x, target_y, target_x;
2425 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2426 // for 32 bit machine, the size is always 3 words
2427 //int msgsize = sizeof(int) * 3;
2430 if(targetcore == corenum) {
2431 // reside on this core
2432 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2433 // no locks for this object, something is wrong
2434 raw_test_done(0xa006);
2437 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2439 RuntimeHashremovekey(locktbl, (int)ptr);
2440 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2445 calCoords(corenum, &self_y, &self_x);
2446 calCoords(targetcore, &target_y, &target_x);
2447 // Build the message header
2448 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2450 target_y, target_x);
2451 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2453 raw_test_pass(0xbbbb);
2454 raw_test_pass(0xb000 + targetcore); // targetcore
2456 gdn_send(5); // lock release
2460 gdn_send(0); // read lock
2466 raw_test_pass_reg(ptr);
2467 raw_test_pass(0xffff);
2473 bool getwritelock(void * ptr) {
2476 int self_y, self_x, target_y, target_x;
2477 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2478 // for 32 bit machine, the size is always 4 words
2479 //int msgsize = sizeof(int) * 4;
2483 raw_user_interrupts_off();
2485 targetcore = ((int)ptr >> 5) % tc;
2487 raw_user_interrupts_on();
2491 raw_test_pass(0xe551);
2492 raw_test_pass_reg(ptr);
2493 raw_test_pass_reg(targetcore);
2494 raw_test_pass_reg(tc);
2504 if(targetcore == corenum) {
2505 // reside on this core
2508 raw_user_interrupts_off();
2510 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2511 // no locks for this object
2512 // first time to operate on this shared object
2513 // create a lock for it
2514 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2516 raw_test_pass(0xe552);
2518 RuntimeHashadd_I(locktbl, (int)ptr, -1);
2521 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2523 raw_test_pass(0xe553);
2524 raw_test_pass_reg(rwlock_obj);
2526 if(0 == rwlock_obj) {
2528 RuntimeHashremovekey(locktbl, (int)ptr);
2529 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2535 raw_user_interrupts_on();
2538 raw_test_pass(0xe554);
2539 raw_test_pass_reg(lockresult);
2541 if(lockobj == (int)ptr) {
2558 // conflicts on lockresults
2559 raw_test_done(0xa007);
2565 raw_test_pass(0xe555);
2567 calCoords(corenum, &self_y, &self_x);
2568 calCoords(targetcore, &target_y, &target_x);
2569 // Build the message header
2570 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2572 target_y, target_x);
2573 // start sending the msg, set send msg flag
2574 isMsgSending = true;
2575 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2577 raw_test_pass(0xbbbb);
2578 raw_test_pass(0xb000 + targetcore); // targetcore
2580 gdn_send(2); // lock request
2584 gdn_send(1); // write lock
2590 raw_test_pass_reg(ptr);
2594 raw_test_pass_reg(corenum);
2595 raw_test_pass(0xffff);
2597 // end of sending this msg, set sand msg flag false
2598 isMsgSending = false;
2599 // check if there are pending msgs
2600 while(isMsgHanging) {
2601 // get the msg from outmsgdata[]
2602 // length + target + msg
2603 outmsgleft = outmsgdata[outmsgindex++];
2604 targetcore = outmsgdata[outmsgindex++];
2605 calCoords(targetcore, &target_y, &target_x);
2606 // Build the message header
2607 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2609 target_y, target_x);
2610 isMsgSending = true;
2611 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2613 raw_test_pass(0xbbbb);
2614 raw_test_pass(0xb000 + targetcore); // targetcore
2616 while(outmsgleft-- > 0) {
2617 gdn_send(outmsgdata[outmsgindex++]);
2619 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2623 raw_test_pass(0xffff);
2625 isMsgSending = false;
2627 raw_user_interrupts_off();
2629 // check if there are still msg hanging
2630 if(outmsgindex == outmsglast) {
2632 outmsgindex = outmsglast = 0;
2633 isMsgHanging = false;
2636 raw_user_interrupts_on();
2640 #elif defined THREADSIMULATE
2641 int numofcore = pthread_getspecific(key);
2643 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2644 printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2648 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2649 // no locks for this object
2650 // first time to operate on this shared object
2651 // create a lock for it
2652 rc = pthread_rwlock_unlock(&rwlock_tbl);
2653 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2654 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2655 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2656 rc = pthread_rwlock_init(rwlock, NULL);
2657 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2658 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2659 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2661 pthread_rwlock_destroy(rwlock);
2665 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2667 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2669 pthread_rwlock_destroy(rwlock);
2671 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2673 rc = pthread_rwlock_unlock(&rwlock_tbl);
2674 printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2676 rc = pthread_rwlock_trywrlock(rwlock);
2677 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2684 pthread_rwlock_t* rwlock_obj = NULL;
2685 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2686 rc = pthread_rwlock_unlock(&rwlock_tbl);
2687 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2688 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
2689 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2700 void releasewritelock(void * ptr) {
2703 int self_y, self_x, target_y, target_x;
2704 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2705 // for 32 bit machine, the size is always 3 words
2706 //int msgsize = sizeof(int) * 3;
2710 raw_user_interrupts_off();
2712 targetcore = ((int)ptr >> 5) % tc;
2714 raw_user_interrupts_on();
2717 if(targetcore == corenum) {
2719 raw_user_interrupts_off();
2721 // reside on this core
2722 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2723 // no locks for this object, something is wrong
2724 raw_test_done(0xa008);
2728 raw_test_pass(0xe662);
2730 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2732 raw_test_pass_reg(rwlock_obj);
2735 RuntimeHashremovekey(locktbl, (int)ptr);
2736 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2738 raw_test_pass_reg(rwlock_obj);
2742 raw_user_interrupts_on();
2748 raw_test_pass(0xe663);
2750 calCoords(corenum, &self_y, &self_x);
2751 calCoords(targetcore, &target_y, &target_x);
2752 // Build the message header
2753 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2755 target_y, target_x);
2756 // start sending the msg, set send msg flag
2757 isMsgSending = true;
2758 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2760 raw_test_pass(0xbbbb);
2761 raw_test_pass(0xb000 + targetcore);
2763 gdn_send(5); // lock release
2767 gdn_send(1); // write lock
2773 raw_test_pass_reg(ptr);
2774 raw_test_pass(0xffff);
2776 // end of sending this msg, set sand msg flag false
2777 isMsgSending = false;
2778 // check if there are pending msgs
2779 while(isMsgHanging) {
2780 // get the msg from outmsgdata[]
2781 // length + target + msg
2782 outmsgleft = outmsgdata[outmsgindex++];
2783 targetcore = outmsgdata[outmsgindex++];
2784 calCoords(targetcore, &target_y, &target_x);
2785 // Build the message header
2786 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2788 target_y, target_x);
2789 isMsgSending = true;
2790 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2792 raw_test_pass(0xbbbb);
2793 raw_test_pass(0xb000 + targetcore); // targetcore
2795 while(outmsgleft-- > 0) {
2796 gdn_send(outmsgdata[outmsgindex++]);
2798 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2802 raw_test_pass(0xffff);
2804 isMsgSending = false;
2806 raw_user_interrupts_off();
2808 // check if there are still msg hanging
2809 if(outmsgindex == outmsglast) {
2811 outmsgindex = outmsglast = 0;
2812 isMsgHanging = false;
2815 raw_user_interrupts_on();
2818 #elif defined THREADSIMULATE
2819 int numofcore = pthread_getspecific(key);
2820 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2821 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2822 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2823 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2826 pthread_rwlock_t* rwlock_obj = NULL;
2827 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2828 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2829 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2830 rc = pthread_rwlock_unlock(&rwlock_tbl);
2831 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2835 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
2836 void * taskpointerarray[MAXTASKPARAMS];
2838 int numparams=parameter->task->numParameters;
2839 int numiterators=parameter->task->numTotal-1;
2844 struct taskdescriptor * task=parameter->task;
2846 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
2848 /* Add enqueued object to parameter vector */
2849 taskpointerarray[parameter->slot]=ptr;
2851 /* Reset iterators */
2852 for(j=0; j<numiterators; j++) {
2853 toiReset(¶meter->iterators[j]);
2856 /* Find initial state */
2857 for(j=0; j<numiterators; j++) {
2859 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2860 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2862 /* Need to backtrack */
2863 toiReset(¶meter->iterators[j]);
2867 /* Nothing to enqueue */
2874 /* Enqueue current state */
2876 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
2878 tpd->numParameters=numiterators+1;
2879 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2880 for(j=0; j<=numiterators; j++){
2881 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
2884 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
2885 genputtable(activetasks, tpd, tpd);
2887 RUNFREE(tpd->parameterArray);
2891 /* This loop iterates to the next parameter combination */
2892 if (numiterators==0)
2895 for(j=numiterators-1; j<numiterators; j++) {
2897 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2898 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2900 /* Need to backtrack */
2901 toiReset(¶meter->iterators[j]);
2905 /* Nothing more to enqueue */
2914 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
2915 void * taskpointerarray[MAXTASKPARAMS];
2917 int numparams=parameter->task->numParameters;
2918 int numiterators=parameter->task->numTotal-1;
2923 struct taskdescriptor * task=parameter->task;
2925 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
2927 /* Add enqueued object to parameter vector */
2928 taskpointerarray[parameter->slot]=ptr;
2930 /* Reset iterators */
2931 for(j=0; j<numiterators; j++) {
2932 toiReset(¶meter->iterators[j]);
2935 /* Find initial state */
2936 for(j=0; j<numiterators; j++) {
2938 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2939 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2941 /* Need to backtrack */
2942 toiReset(¶meter->iterators[j]);
2946 /* Nothing to enqueue */
2952 /* Enqueue current state */
2954 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2956 tpd->numParameters=numiterators+1;
2957 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2958 for(j=0; j<=numiterators; j++){
2959 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
2962 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
2963 genputtable_I(activetasks, tpd, tpd);
2965 RUNFREE(tpd->parameterArray);
2969 /* This loop iterates to the next parameter combination */
2970 if (numiterators==0)
2973 for(j=numiterators-1; j<numiterators; j++) {
2975 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2976 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2978 /* Need to backtrack */
2979 toiReset(¶meter->iterators[j]);
2983 /* Nothing more to enqueue */
2992 /* Handler for signals. The signals catch null pointer errors and
2993 arithmatic errors. */
2995 void myhandler(int sig, siginfo_t *info, void *uap) {
2998 printf("sig=%d\n",sig);
3001 sigemptyset(&toclear);
3002 sigaddset(&toclear, sig);
3003 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
3004 longjmp(error_handler,1);
3010 struct RuntimeHash *fdtoobject;
3012 void addreadfd(int fd) {
3015 FD_SET(fd, &readfds);
3018 void removereadfd(int fd) {
3019 FD_CLR(fd, &readfds);
3020 if (maxreadfd==(fd+1)) {
3022 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
3033 void executetasks() {
3034 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
3037 struct ___Object___ * tmpparam = NULL;
3038 struct parameterdescriptor * pd=NULL;
3039 struct parameterwrapper *pw=NULL;
3049 raw_test_pass(0xe991);
3054 /* Set up signal handlers */
3055 struct sigaction sig;
3056 sig.sa_sigaction=&myhandler;
3057 sig.sa_flags=SA_SIGINFO;
3058 sigemptyset(&sig.sa_mask);
3060 /* Catch bus errors, segmentation faults, and floating point exceptions*/
3061 sigaction(SIGBUS,&sig,0);
3062 sigaction(SIGSEGV,&sig,0);
3063 sigaction(SIGFPE,&sig,0);
3064 sigaction(SIGPIPE,&sig,0);
3073 fdtoobject=allocateRuntimeHash(100);
3077 /* Map first block of memory to protected, anonymous page */
3078 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
3082 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
3086 raw_test_pass(0xe992);
3089 /* Check if any filedescriptors have IO pending */
3092 struct timeval timeout={0,0};
3096 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
3098 /* Process ready fd's */
3100 for(fd=0; fd<maxreadfd; fd++) {
3101 if (FD_ISSET(fd, &tmpreadfds)) {
3102 /* Set ready flag on object */
3104 // printf("Setting fd %d\n",fd);
3105 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
3106 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
3107 enqueueObject(objptr, NULL, 0);
3116 /* See if there are any active tasks */
3117 if (hashsize(activetasks)>0) {
3119 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
3120 genfreekey(activetasks, currtpd);
3122 /* Check if this task has failed, allow a task that contains optional objects to fire */
3123 /*if (gencontains(failedtasks, currtpd)) {
3124 // Free up task parameter descriptor
3125 RUNFREE(currtpd->parameterArray);
3129 numparams=currtpd->task->numParameters;
3130 numtotal=currtpd->task->numTotal;
3132 #ifdef THREADSIMULATE
3133 int isolateflags[numparams];
3135 /* Make sure that the parameters are still in the queues */
3136 for(i=0; i<numparams; i++) {
3137 void * parameter=currtpd->parameterArray[i];
3140 raw_test_pass(0xe993);
3143 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3145 taskpointerarray[i+OFFSET]=parameter;
3149 // require locks for this parameter if it is not a startup object
3150 getwritelock(parameter);
3154 raw_user_interrupts_off();
3161 while(receiveObject() != -1) {
3165 grount = lockresult;
3174 raw_user_interrupts_on();
3179 raw_test_pass(0xe994);
3181 // can not get the lock, try later
3182 for(j = 0; j < i; ++j) {
3183 releasewritelock(taskpointerarray[j+OFFSET]);
3185 genputtable(activetasks, currtpd, currtpd);
3186 if(hashsize(activetasks) == 1) {
3187 // only one task right now, wait a little while before next try
3196 raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
3198 for(tmp = 0; tmp < classsize[((struct ___Object___ *)parameter)->type]; ++tmp) {
3199 invalidateAddr(parameter + tmp);
3203 tmpparam = (struct ___Object___ *)parameter;
3204 #ifdef THREADSIMULATE
3205 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3207 taskpointerarray[i+OFFSET]=parameter;
3211 if(0 == tmpparam->isolate) {
3212 isolateflags[i] = 0;
3213 // shared object, need to flush with current value
3214 //if(!getreadlock(tmpparam->original)) {
3215 // // fail to get read lock of the original object, try this task later
3216 if(!getwritelock(tmpparam->original)) {
3217 // fail to get write lock, release all obtained locks and try this task later
3219 for(j = 0; j < i; ++j) {
3220 if(0 == isolateflags[j]) {
3221 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3224 genputtable(activetasks, currtpd, currtpd);
3227 if(tmpparam->version != tmpparam->original->version) {
3228 // some task on another core has changed this object
3229 // flush this object
3230 //memcpy(tmpparam, tmpparam->original, classsize[tmpparam->type]);
3231 // release all obtained locks
3233 for(j = 0; j < i; ++j) {
3234 if(0 == isolateflags[j]) {
3235 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3238 releasewritelock(tmpparam->original);
3240 // dequeue this object
3241 int numofcore = pthread_getspecific(key);
3242 struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
3243 int length = numqueues[numofcore][tmpparam->type];
3244 for(j = 0; j < length; ++j) {
3245 struct parameterwrapper * pw = queues[j];
3246 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
3248 int UNUSED, UNUSED2;
3250 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3251 ObjectHashremove(pw->objectset, (int)tmpparam);
3252 if (enterflags!=NULL)
3256 // try to enqueue it again to check if it feeds other tasks;
3257 //enqueueObject(tmpparam, NULL, 0);
3258 // Free up task parameter descriptor
3259 RUNFREE(currtpd->parameterArray);
3264 isolateflags[i] = 1;
3267 pd=currtpd->task->descriptorarray[i];
3268 pw=(struct parameterwrapper *) pd->queue;
3269 /* Check that object is still in queue */
3271 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
3273 raw_test_pass(0xe995);
3275 // release grabbed locks
3276 for(j = 0; j < i; ++j) {
3277 releasewritelock(taskpointerarray[j+OFFSET]);
3279 releasewritelock(parameter);
3280 RUNFREE(currtpd->parameterArray);
3286 /* Check if the object's flags still meets requirements */
3290 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
3291 andmask=pw->intarray[tmpi*2];
3292 checkmask=pw->intarray[tmpi*2+1];
3294 raw_test_pass(0xdd000000 + andmask);
3295 raw_test_pass_reg((int)parameter);
3296 raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
3297 raw_test_pass(0xdd000000 + checkmask);
3299 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
3305 // flags are never suitable
3306 // remove this obj from the queue
3308 int UNUSED, UNUSED2;
3311 raw_test_pass(0xe996);
3313 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3314 ObjectHashremove(pw->objectset, (int)parameter);
3315 if (enterflags!=NULL)
3317 // release grabbed locks
3318 for(j = 0; j < i; ++j) {
3319 releasewritelock(taskpointerarray[j+OFFSET]);
3321 releasewritelock(parameter);
3322 RUNFREE(currtpd->parameterArray);
3330 /* Check that object still has necessary tags */
3331 for(j=0; j<pd->numbertags; j++) {
3332 int slotid=pd->tagarray[2*j]+numparams;
3333 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
3334 if (!containstag(parameter, tagd)) {
3336 raw_test_pass(0xe997);
3338 RUNFREE(currtpd->parameterArray);
3344 taskpointerarray[i+OFFSET]=parameter;
3347 for(; i<numtotal; i++) {
3348 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
3351 #ifdef THREADSIMULATE
3352 for(i = 0; i < numparams; ++i) {
3353 if(0 == isolateflags[i]) {
3354 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3355 if(tmpparam != tmpparam->original) {
3356 taskpointerarray[i+OFFSET] = tmpparam->original;
3365 /* Checkpoint the state */
3366 forward=allocateRuntimeHash(100);
3367 reverse=allocateRuntimeHash(100);
3368 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
3371 if (x=setjmp(error_handler)) {
3376 printf("Fatal Error=%d, Recovering!\n",x);
3380 genputtable(failedtasks,currtpd,currtpd);
3381 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
3383 freeRuntimeHash(forward);
3384 freeRuntimeHash(reverse);
3392 raw_test_pass_reg(x);
3394 raw_test_done(0xa009);
3399 /*if (injectfailures) {
3400 if ((((double)random())/RAND_MAX)<failurechance) {
3401 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
3402 longjmp(error_handler,10);
3405 /* Actually call task */
3407 ((int *)taskpointerarray)[0]=currtpd->numParameters;
3408 taskpointerarray[1]=NULL;
3413 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3415 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3417 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3420 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3423 raw_test_pass(0xe998);
3424 raw_test_pass_reg(lock);
3429 for(i = 0; i < numparams; ++i) {
3431 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3433 raw_test_pass(0xe999);
3434 raw_test_pass(0xdd100000 + tmpparam->flag);
3436 releasewritelock(tmpparam);
3438 #elif defined THREADSIMULATE
3439 for(i = 0; i < numparams; ++i) {
3440 if(0 == isolateflags[i]) {
3441 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3442 releasewritelock(tmpparam);
3450 freeRuntimeHash(forward);
3451 freeRuntimeHash(reverse);
3455 // Free up task parameter descriptor
3456 RUNFREE(currtpd->parameterArray);
3465 raw_test_pass(0xe99a);
3468 raw_test_pass(0xe99a);
3476 raw_test_pass(0xe999);
3480 /* This function processes an objects tags */
3481 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
3484 for(i=0; i<pd->numbertags; i++) {
3485 int slotid=pd->tagarray[2*i];
3486 int tagid=pd->tagarray[2*i+1];
3488 if (statusarray[slotid+numparams]==0) {
3489 parameter->iterators[*iteratorcount].istag=1;
3490 parameter->iterators[*iteratorcount].tagid=tagid;
3491 parameter->iterators[*iteratorcount].slot=slotid+numparams;
3492 parameter->iterators[*iteratorcount].tagobjectslot=index;
3493 statusarray[slotid+numparams]=1;
3500 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
3503 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
3505 parameter->iterators[*iteratorcount].istag=0;
3506 parameter->iterators[*iteratorcount].slot=index;
3507 parameter->iterators[*iteratorcount].objectset=objectset;
3508 statusarray[index]=1;
3510 for(i=0; i<pd->numbertags; i++) {
3511 int slotid=pd->tagarray[2*i];
3512 int tagid=pd->tagarray[2*i+1];
3513 if (statusarray[slotid+numparams]!=0) {
3514 /* This tag has already been enqueued, use it to narrow search */
3515 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
3519 parameter->iterators[*iteratorcount].numtags=tagcount;
3524 /* This function builds the iterators for a task & parameter */
3526 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
3527 int statusarray[MAXTASKPARAMS];
3529 int numparams=task->numParameters;
3530 int iteratorcount=0;
3531 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
3533 statusarray[index]=1; /* Initial parameter */
3534 /* Process tags for initial iterator */
3536 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
3540 /* Check for objects with existing tags */
3541 for(i=0; i<numparams; i++) {
3542 if (statusarray[i]==0) {
3543 struct parameterdescriptor *pd=task->descriptorarray[i];
3545 for(j=0; j<pd->numbertags; j++) {
3546 int slotid=pd->tagarray[2*j];
3547 if(statusarray[slotid+numparams]!=0) {
3548 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
3549 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3556 /* Next do objects w/ unbound tags*/
3558 for(i=0; i<numparams; i++) {
3559 if (statusarray[i]==0) {
3560 struct parameterdescriptor *pd=task->descriptorarray[i];
3561 if (pd->numbertags>0) {
3562 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
3563 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3569 /* Nothing with a tag enqueued */
3571 for(i=0; i<numparams; i++) {
3572 if (statusarray[i]==0) {
3573 struct parameterdescriptor *pd=task->descriptorarray[i];
3574 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
3575 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3588 #ifdef THREADSIMULATE
3589 int numofcore = pthread_getspecific(key);
3590 for(i=0; i<numtasks[numofcore]; i++) {
3591 struct taskdescriptor * task=taskarray[numofcore][i];
3594 if(corenum > NUMCORES - 1) {
3598 for(i=0; i<numtasks[corenum]; i++) {
3599 struct taskdescriptor * task=taskarray[corenum][i];
3602 printf("%s\n", task->name);
3604 for(j=0; j<task->numParameters; j++) {
3605 struct parameterdescriptor *param=task->descriptorarray[j];
3606 struct parameterwrapper *parameter=param->queue;
3607 struct ObjectHash * set=parameter->objectset;
3608 struct ObjectIterator objit;
3610 printf(" Parameter %d\n", j);
3612 ObjectHashiterator(set, &objit);
3613 while(ObjhasNext(&objit)) {
3614 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
3615 struct ___Object___ * tagptr=obj->___tags___;
3616 int nonfailed=Objdata4(&objit);
3617 int numflags=Objdata3(&objit);
3618 int flags=Objdata2(&objit);
3621 printf(" Contains %lx\n", obj);
3622 printf(" flag=%d\n", obj->flag);
3625 } else if (tagptr->type==TAGTYPE) {
3627 printf(" tag=%lx\n",tagptr);
3632 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
3633 for(; tagindex<ao->___cachedCode___; tagindex++) {
3635 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
3645 /* This function processes the task information to create queues for
3646 each parameter type. */
3648 void processtasks() {
3651 if(corenum > NUMCORES - 1) {
3655 #ifdef THREADSIMULATE
3656 int numofcore = pthread_getspecific(key);
3657 for(i=0; i<numtasks[numofcore]; i++) {
3658 struct taskdescriptor *task=taskarray[numofcore][i];
3660 for(i=0; i<numtasks[corenum]; i++) {
3661 struct taskdescriptor * task=taskarray[corenum][i];
3665 /* Build objectsets */
3666 for(j=0; j<task->numParameters; j++) {
3667 struct parameterdescriptor *param=task->descriptorarray[j];
3668 struct parameterwrapper *parameter=param->queue;
3669 parameter->objectset=allocateObjectHash(10);
3670 parameter->task=task;
3673 /* Build iterators for parameters */
3674 for(j=0; j<task->numParameters; j++) {
3675 struct parameterdescriptor *param=task->descriptorarray[j];
3676 struct parameterwrapper *parameter=param->queue;
3677 builditerators(task, j, parameter);
3682 void toiReset(struct tagobjectiterator * it) {
3685 } else if (it->numtags>0) {
3688 ObjectHashiterator(it->objectset, &it->it);
3692 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
3695 /* Get object with tags */
3696 struct ___Object___ *obj=objectarray[it->tagobjectslot];
3697 struct ___Object___ *tagptr=obj->___tags___;
3698 if (tagptr->type==TAGTYPE) {
3699 if ((it->tagobjindex==0)&& /* First object */
3700 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
3705 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3706 int tagindex=it->tagobjindex;
3707 for(; tagindex<ao->___cachedCode___; tagindex++) {
3708 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
3709 if (td->flag==it->tagid) {
3710 it->tagobjindex=tagindex; /* Found right type of tag */
3716 } else if (it->numtags>0) {
3717 /* Use tags to locate appropriate objects */
3718 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3719 struct ___Object___ *objptr=tag->flagptr;
3721 if (objptr->type!=OBJECTARRAYTYPE) {
3722 if (it->tagobjindex>0)
3724 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3726 for(i=1; i<it->numtags; i++) {
3727 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3728 if (!containstag(objptr,tag2))
3733 struct ArrayObject *ao=(struct ArrayObject *) objptr;
3736 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
3737 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
3738 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3740 for(i=1; i<it->numtags; i++) {
3741 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3742 if (!containstag(objptr,tag2))
3745 it->tagobjindex=tagindex;
3750 it->tagobjindex=tagindex;
3754 return ObjhasNext(&it->it);
3758 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
3760 struct ___Object___ * objptr=tag->flagptr;
3761 if (objptr->type==OBJECTARRAYTYPE) {
3762 struct ArrayObject *ao=(struct ArrayObject *)objptr;
3763 for(j=0; j<ao->___cachedCode___; j++) {
3764 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
3772 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
3773 /* hasNext has all of the intelligence */
3776 /* Get object with tags */
3777 struct ___Object___ *obj=objectarray[it->tagobjectslot];
3778 struct ___Object___ *tagptr=obj->___tags___;
3779 if (tagptr->type==TAGTYPE) {
3781 objectarray[it->slot]=tagptr;
3783 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3784 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
3786 } else if (it->numtags>0) {
3787 /* Use tags to locate appropriate objects */
3788 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3789 struct ___Object___ *objptr=tag->flagptr;
3790 if (objptr->type!=OBJECTARRAYTYPE) {
3792 objectarray[it->slot]=objptr;
3794 struct ArrayObject *ao=(struct ArrayObject *) objptr;
3795 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
3798 /* Iterate object */
3799 objectarray[it->slot]=(void *)Objkey(&it->it);