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>
26 #include <raw_compiler_defs.h>
27 #elif defined THREADSIMULATE
28 // use POSIX message queue
29 // for each core, its message queue named as
35 extern int injectfailures;
36 extern float failurechance;
42 #define TOTALCORE raw_get_num_tiles()
46 #include "instrument.h"
49 struct genhashtable * activetasks;
50 struct genhashtable * failedtasks;
51 struct taskparamdescriptor * currtpd;
53 struct RuntimeHash * forward;
54 struct RuntimeHash * reverse;
57 int corestatus[NUMCORES]; // records status of each core
60 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
61 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
63 struct RuntimeHash locktable;
64 static struct RuntimeHash* locktbl = &locktable;
65 void * curr_heapbase=0;
66 void * curr_heaptop=0;
68 int self_numreceiveobjs;
75 struct Queue objqueue;
86 void calCoords(int core_num, int* coordY, int* coordX);
87 #elif defined THREADSIMULATE
88 static struct RuntimeHash* locktbl;
96 struct thread_data thread_data_array[NUMCORES];
98 static pthread_key_t key;
99 static pthread_rwlock_t rwlock_tbl;
100 static pthread_rwlock_t rwlock_init;
102 void run(void * arg);
105 bool transStallMsg(int targetcore);
106 void transTerminateMsg(int targetcore);
108 bool getreadlock(void* ptr);
109 void releasereadlock(void* ptr);
111 bool getreadlock_I(void* ptr);
112 void releasereadlock_I(void* ptr);
114 bool getwritelock(void* ptr);
115 void releasewritelock(void* ptr);
117 // profiling mode of RAW version
120 #define TASKINFOLENGTH 10000
121 //#define INTERRUPTINFOLENGTH 500
127 typedef struct task_info {
132 struct Queue * newObjs;
135 /*typedef struct interrupt_info {
140 TaskInfo * taskInfoArray[TASKINFOLENGTH];
142 bool taskInfoOverflow;
143 /*InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
144 int interruptInfoIndex;
145 bool interruptInfoOverflow;*/
146 int profilestatus[NUMCORES]; // records status of each core
149 bool transProfileRequestMsg(int targetcore);
150 void outputProfileData();
160 int main(int argc, char **argv) {
166 bool sendStall = false;
168 bool tocontinue = false;
169 struct QueueItem * objitem = NULL;
170 struct transObjInfo * objInfo = NULL;
172 bool allStall = true;
176 raw_test_pass(0xee01);
178 corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
180 // initialize the arrays
181 if(STARTUPCORE == corenum) {
182 // startup core to initialize corestatus[]
183 for(i = 0; i < NUMCORES; ++i) {
185 numsendobjs[i] = 0; // assume all variables in RAW are local variables! MAY BE WRONG!!!
186 numreceiveobjs[i] = 0;
189 for(i = 0; i < NUMCORES; ++i) {
190 profilestatus[i] = 1;
194 self_numsendobjs = 0;
195 self_numreceiveobjs = 0;
196 for(i = 0; i < 30; ++i) {
203 for(i = 0; i < 30; ++i) {
209 isMsgHanging = false;
210 isMsgSending = false;
212 raw_test_pass(0xee02);
215 // create the lock table, lockresult table and obj queue
217 locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
218 /* Set allocation blocks*/
219 locktable.listhead=NULL;
220 locktable.listtail=NULL;
222 locktable.numelements = 0;
229 objqueue.head = NULL;
230 objqueue.tail = NULL;
232 raw_test_pass(0xee03);
237 //isInterrupt = true;
240 /*interruptInfoIndex = 0;
241 taskInfoOverflow = false;
242 interruptInfoOverflow = false;*/
246 if (corenum < NUMCORES) {
249 raw_user_interrupts_on();
251 raw_test_pass(0xee04);
256 #elif defined THREADSIMULATE
260 pthread_t threads[NUMCORES];
263 // initialize three arrays and msg queue array
264 char * pathhead = "/msgqueue_";
265 int targetlen = strlen(pathhead);
266 for(i = 0; i < NUMCORES; ++i) {
269 numreceiveobjs[i] = 0;
274 corenumstr[0] = i + '0';
275 corenumstr[1] = '\0';
278 corenumstr[1] = i %10 + '0';
279 corenumstr[0] = (i / 10) + '0';
280 corenumstr[2] = '\0';
283 printf("Error: i >= 100\n");
287 char path[targetlen + sourcelen + 1];
288 strcpy(path, pathhead);
289 strncat(path, corenumstr, sourcelen);
290 int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
291 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
293 mqd[i]= mq_open(path, oflags, omodes, NULL);
295 printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
298 printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
303 pthread_key_create(&key, NULL);
305 // create the lock table and initialize its mutex
306 locktbl = allocateRuntimeHash(20);
307 int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
308 printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
310 for(i = 0; i < NUMCORES; ++i) {
311 thread_data_array[i].corenum = i;
312 thread_data_array[i].argc = argc;
313 thread_data_array[i].argv = argv;
314 thread_data_array[i].numsendobjs = 0;
315 thread_data_array[i].numreceiveobjs = 0;
316 printf("[main] creating thread %d\n", i);
317 rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
319 printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
329 void run(void* arg) {
330 struct thread_data * my_tdata = (struct thread_data *)arg;
331 pthread_setspecific(key, (void *)my_tdata->corenum);
332 int argc = my_tdata->argc;
333 char** argv = my_tdata->argv;
334 printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
340 GC_init(); // Initialize the garbage collector
348 initializeexithandler();
350 raw_test_pass(0xee05);
352 /* Create table for failed tasks */
354 if(corenum > NUMCORES - 1) {
358 raw_test_pass(0xee01);
359 raw_test_pass_reg(taskInfoIndex);
360 raw_test_pass_reg(taskInfoOverflow);
361 if(!taskInfoOverflow) {
362 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
363 taskInfoArray[taskInfoIndex] = taskInfo;
364 taskInfo->taskName = "msg handling";
365 taskInfo->startTime = raw_get_cycle();
366 taskInfo->endTime = -1;
370 //isInterrupt = false;
377 raw_test_pass(0xee06);
380 /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
381 (int (*)(void *,void *)) &comparetpd);*/
384 raw_test_pass(0xee07);
386 /* Create queue of active tasks */
387 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
388 (int(*) (void *,void *)) &comparetpd);
390 raw_test_pass(0xee08);
393 /* Process task information */
396 raw_test_pass(0xee09);
399 if(STARTUPCORE == corenum) {
400 /* Create startup object */
401 createstartupobject(argc, argv);
404 raw_test_pass(0xee0a);
409 raw_test_pass(0xee0b);
413 // check if there are new active tasks can be executed
417 while(receiveObject() != -1) {
422 raw_test_pass(0xee0c);
425 // check if there are some pending objects, if yes, enqueue them and executetasks again
428 raw_test_pass(0xee0d);
432 bool isChecking = false;
433 if(!isEmpty(&objqueue)) {
434 if(!taskInfoOverflow) {
435 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
436 taskInfoArray[taskInfoIndex] = taskInfo;
437 taskInfo->taskName = "objqueue checking";
438 taskInfo->startTime = raw_get_cycle();
439 taskInfo->endTime = -1;
440 taskInfo->exitIndex = -1;
441 taskInfo->newObjs = NULL;
446 while(!isEmpty(&objqueue)) {
451 raw_user_interrupts_off();
454 //isInterrupt = false;
457 raw_test_pass(0xeee1);
461 objitem = getTail(&objqueue);
462 objInfo = (struct transObjInfo *)objitem->objectptr;
463 obj = objInfo->objptr;
465 raw_test_pass_reg((int)obj);
467 // grab lock and flush the obj
469 if(((struct ___Object___ *)obj)->numlocks == 0) {
473 locks = ((struct ___Object___ *)obj)->locks;
474 numlocks = ((struct ___Object___ *)obj)->numlocks;
476 for(; numlocks > 0; numlocks--) {
477 getreadlock_I(locks);
481 grount = grount || lockresult;
483 raw_test_pass_reg(grount);
497 locks = (int*)(*locks);
503 raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
504 // enqueue the object
505 for(k = 0; k < objInfo->length; ++k) {
506 int taskindex = objInfo->queues[2 * k];
507 int paramindex = objInfo->queues[2 * k + 1];
508 struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
510 raw_test_pass_reg(taskindex);
511 raw_test_pass_reg(paramindex);
513 enqueueObject_I(obj, queues, 1);
515 removeItem(&objqueue, objitem);
516 if(((struct ___Object___ *)obj)->numlocks == 0) {
520 locks = ((struct ___Object___ *)obj)->locks;
521 numlocks = ((struct ___Object___ *)obj)->numlocks;
523 for(; numlocks > 0; numlocks--) {
524 releasereadlock_I(locks);
525 locks = (int *)(*locks);
527 RUNFREE(objInfo->queues);
532 // put it at the end of the queue
533 // and try to execute active tasks already enqueued first
534 removeItem(&objqueue, objitem);
535 addNewItem_I(&objqueue, objInfo);
536 if(((struct ___Object___ *)obj)->numlocks > 0) {
537 //release grabbed locks
538 numlocks = ((struct ___Object___ *)obj)->numlocks - numlocks;
539 locks = ((struct ___Object___ *)obj)->locks;
540 for(; numlocks > 0; numlocks--) {
541 releasereadlock_I(locks);
542 locks = (int *)(*locks);
546 //isInterrupt = true;
549 raw_user_interrupts_on();
554 raw_user_interrupts_on();
557 raw_test_pass(0xee0e);
561 if(isChecking && (!taskInfoOverflow)) {
562 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
564 if(taskInfoIndex == TASKINFOLENGTH) {
565 taskInfoOverflow = true;
571 raw_test_pass(0xee0f);
576 if(STARTUPCORE == corenum) {
579 raw_test_pass(0xee10);
584 raw_user_interrupts_off();
586 corestatus[corenum] = 0;
587 numsendobjs[corenum] = self_numsendobjs;
588 numreceiveobjs[corenum] = self_numreceiveobjs;
589 // check the status of all cores
592 raw_test_pass_reg(NUMCORES);
594 for(i = 0; i < NUMCORES; ++i) {
596 raw_test_pass(0xe000 + corestatus[i]);
598 if(corestatus[i] != 0) {
604 // check if the sum of send objs and receive obj are the same
605 // yes->terminate; for profiling mode, yes->send request to all
606 // other cores to pour out profiling data
607 // no->go on executing
609 for(i = 0; i < NUMCORES; ++i) {
610 sumsendobj += numsendobjs[i];
612 raw_test_pass(0xf000 + numsendobjs[i]);
615 for(i = 0; i < NUMCORES; ++i) {
616 sumsendobj -= numreceiveobjs[i];
618 raw_test_pass(0xf000 + numreceiveobjs[i]);
621 if(0 == sumsendobj) {
624 raw_test_pass(0xee11);
627 totalexetime = raw_get_cycle();
629 raw_test_pass(0xbbbbbbbb);
630 raw_test_pass(raw_get_cycle());
633 // profile mode, send msgs to other cores to request pouring
634 // out progiling data
637 // reopen gdn_avail interrupts
638 raw_user_interrupts_on();
640 for(i = 1; i < NUMCORES; ++i) {
641 transProfileRequestMsg(i);
643 // pour profiling data on startup core
647 raw_user_interrupts_off();
649 profilestatus[corenum] = 0;
650 // check the status of all cores
653 raw_test_pass_reg(NUMCORES);
655 for(i = 0; i < NUMCORES; ++i) {
657 raw_test_pass(0xe000 + profilestatus[i]);
659 if(profilestatus[i] != 0) {
667 raw_user_interrupts_on();
677 raw_test_done(1); // All done.
681 raw_user_interrupts_on();
686 raw_test_pass(0xee12);
692 // wait for some time
695 raw_test_pass(0xee13);
701 raw_test_pass(0xee14);
704 // send StallMsg to startup core
706 raw_test_pass(0xee15);
708 sendStall = transStallMsg(STARTUPCORE);
717 raw_test_pass(0xee16);
724 #elif defined THREADSIMULATE
725 /* Start executing the tasks */
729 // check if there are new objects coming
730 bool sendStall = false;
732 int numofcore = pthread_getspecific(key);
734 switch(receiveObject()) {
736 //printf("[run, %d] receive an object\n", numofcore);
738 // received an object
739 // check if there are new active tasks can be executed
745 //printf("[run, %d] no msg\n", numofcore);
747 if(STARTUPCORE == numofcore) {
748 corestatus[numofcore] = 0;
749 // check the status of all cores
750 bool allStall = true;
751 for(i = 0; i < NUMCORES; ++i) {
752 if(corestatus[i] != 0) {
758 // check if the sum of send objs and receive obj are the same
760 // no->go on executing
762 for(i = 0; i < NUMCORES; ++i) {
763 sumsendobj += numsendobjs[i];
765 for(i = 0; i < NUMCORES; ++i) {
766 sumsendobj -= numreceiveobjs[i];
768 if(0 == sumsendobj) {
772 int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
773 printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
774 struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
775 while(0 != RunhasNext(it_lock)) {
776 int key = Runkey(it_lock);
777 pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
778 int rc_des = pthread_rwlock_destroy(rwlock_obj);
779 printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
782 freeRuntimeHash(locktbl);
786 // destroy all message queues
787 char * pathhead = "/msgqueue_";
788 int targetlen = strlen(pathhead);
789 for(i = 0; i < NUMCORES; ++i) {
793 corenumstr[0] = i + '0';
794 corenumstr[1] = '\0';
797 corenumstr[1] = i %10 + '0';
798 corenumstr[0] = (i / 10) + '0';
799 corenumstr[2] = '\0';
802 printf("Error: i >= 100\n");
806 char path[targetlen + sourcelen + 1];
807 strcpy(path, pathhead);
808 strncat(path, corenumstr, sourcelen);
812 printf("[run, %d] terminate!\n", numofcore);
819 // send StallMsg to startup core
820 sendStall = transStallMsg(STARTUPCORE);
827 printf("[run, %d] receive a stall msg\n", numofcore);
828 // receive a Stall Msg, do nothing
829 assert(STARTUPCORE == numofcore); // only startup core can receive such msg
835 printf("[run, %d] Error: invalid message type.\n", numofcore);
845 void createstartupobject(int argc, char ** argv) {
848 /* Allocate startup object */
850 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
851 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
853 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
854 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
856 /* Build array of strings */
857 startupobject->___parameters___=stringarray;
858 for(i=1; i<argc; i++) {
859 int length=strlen(argv[i]);
861 struct ___String___ *newstring=NewString(NULL, argv[i],length);
863 struct ___String___ *newstring=NewString(argv[i],length);
865 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
868 startupobject->isolate = 1;
869 startupobject->version = 0;
870 startupobject->numlocks = 0;
871 startupobject->locks = NULL;
873 /* Set initialized flag for startup object */
874 flagorandinit(startupobject,1,0xFFFFFFFF);
875 enqueueObject(startupobject, NULL, 0);
877 raw_flush_entire_cache();
881 int hashCodetpd(struct taskparamdescriptor *ftd) {
882 int hash=(int)ftd->task;
884 for(i=0; i<ftd->numParameters; i++) {
885 hash^=(int)ftd->parameterArray[i];
890 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
892 if (ftd1->task!=ftd2->task)
894 for(i=0; i<ftd1->numParameters; i++)
895 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
900 /* This function sets a tag. */
902 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
904 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
906 struct ArrayObject * ao=NULL;
907 struct ___Object___ * tagptr=obj->___tags___;
909 raw_test_pass(0xebb0);
913 raw_test_pass(0xebb1);
915 obj->___tags___=(struct ___Object___ *)tagd;
917 /* Have to check if it is already set */
918 if (tagptr->type==TAGTYPE) {
919 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
921 raw_test_pass(0xebb2);
925 raw_test_pass(0xebb3);
930 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
931 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
932 obj=(struct ___Object___ *)ptrarray[2];
933 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
934 td=(struct ___TagDescriptor___ *) obj->___tags___;
937 raw_test_pass(0xebb4);
939 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
942 raw_test_pass(0xebb5);
944 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
945 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
946 obj->___tags___=(struct ___Object___ *) ao;
947 ao->___cachedCode___=2;
949 raw_test_pass(0xebb6);
954 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
956 raw_test_pass(0xebb7);
958 for(i=0; i<ao->___cachedCode___; i++) {
959 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
961 raw_test_pass(0xebb8);
965 raw_test_pass(0xebb9);
970 if (ao->___cachedCode___<ao->___length___) {
972 raw_test_pass(0xebba);
974 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
975 ao->___cachedCode___++;
977 raw_test_pass(0xebbb);
981 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
982 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
983 obj=(struct ___Object___ *)ptrarray[2];
984 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
985 ao=(struct ArrayObject *)obj->___tags___;
987 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
990 raw_test_pass(0xebbc);
992 aonew->___cachedCode___=ao->___length___+1;
993 for(i=0; i<ao->___length___; i++) {
995 raw_test_pass(0xebbd);
997 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
1000 raw_test_pass(0xebbe);
1002 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
1004 raw_test_pass(0xebbf);
1011 struct ___Object___ * tagset=tagd->flagptr;
1013 raw_test_pass(0xb008);
1017 raw_test_pass(0xb009);
1020 } else if (tagset->type!=OBJECTARRAYTYPE) {
1022 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1023 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1024 obj=(struct ___Object___ *)ptrarray[2];
1025 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1027 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1029 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
1030 ARRAYSET(ao, struct ___Object___ *, 1, obj);
1031 ao->___cachedCode___=2;
1032 tagd->flagptr=(struct ___Object___ *)ao;
1034 raw_test_pass(0xb00a);
1037 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1038 if (ao->___cachedCode___<ao->___length___) {
1040 raw_test_pass(0xb00b);
1042 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
1046 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1047 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
1048 obj=(struct ___Object___ *)ptrarray[2];
1049 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1050 ao=(struct ArrayObject *)tagd->flagptr;
1052 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1054 aonew->___cachedCode___=ao->___cachedCode___+1;
1055 for(i=0; i<ao->___length___; i++) {
1056 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
1058 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
1059 tagd->flagptr=(struct ___Object___ *) aonew;
1061 raw_test_pass(0xb00c);
1068 /* This function clears a tag. */
1070 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1072 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1074 /* We'll assume that tag is alway there.
1075 Need to statically check for this of course. */
1076 struct ___Object___ * tagptr=obj->___tags___;
1078 if (tagptr->type==TAGTYPE) {
1079 if ((struct ___TagDescriptor___ *)tagptr==tagd)
1080 obj->___tags___=NULL;
1083 printf("ERROR 1 in tagclear\n");
1087 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1089 for(i=0; i<ao->___cachedCode___; i++) {
1090 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
1092 ao->___cachedCode___--;
1093 if (i<ao->___cachedCode___)
1094 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
1095 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
1096 if (ao->___cachedCode___==0)
1097 obj->___tags___=NULL;
1102 printf("ERROR 2 in tagclear\n");
1108 struct ___Object___ *tagset=tagd->flagptr;
1109 if (tagset->type!=OBJECTARRAYTYPE) {
1114 printf("ERROR 3 in tagclear\n");
1118 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1120 for(i=0; i<ao->___cachedCode___; i++) {
1121 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
1123 ao->___cachedCode___--;
1124 if (i<ao->___cachedCode___)
1125 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
1126 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
1127 if (ao->___cachedCode___==0)
1133 printf("ERROR 4 in tagclear\n");
1141 /* This function allocates a new tag. */
1143 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
1144 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
1146 struct ___TagDescriptor___ * allocate_tag(int index) {
1147 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
1156 /* This function updates the flag for object ptr. It or's the flag
1157 with the or mask and and's it with the andmask. */
1159 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
1161 int flagcomp(const int *val1, const int *val2) {
1162 return (*val1)-(*val2);
1165 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
1167 int oldflag=((int *)ptr)[1];
1168 int flag=ormask|oldflag;
1171 raw_test_pass_reg((int)ptr);
1172 raw_test_pass(0xaa000000 + oldflag);
1173 raw_test_pass(0xaa000000 + flag);
1175 flagbody(ptr, flag, queues, length, false);
1179 bool intflagorand(void * ptr, int ormask, int andmask) {
1181 int oldflag=((int *)ptr)[1];
1182 int flag=ormask|oldflag;
1184 if (flag==oldflag) /* Don't do anything */
1187 flagbody(ptr, flag, NULL, 0, false);
1193 void flagorandinit(void * ptr, int ormask, int andmask) {
1194 int oldflag=((int *)ptr)[1];
1195 int flag=ormask|oldflag;
1198 raw_test_pass(0xaa100000 + oldflag);
1199 raw_test_pass(0xaa100000 + flag);
1201 flagbody(ptr,flag,NULL,0,true);
1204 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1205 struct parameterwrapper * flagptr = NULL;
1207 struct parameterwrapper ** queues = vqueues;
1208 int length = vlength;
1210 int UNUSED, UNUSED2;
1211 int * enterflags = NULL;
1212 if((!isnew) && (queues == NULL)) {
1213 #ifdef THREADSIMULATE
1214 int numofcore = pthread_getspecific(key);
1215 queues = objectqueues[numofcore][ptr->type];
1216 length = numqueues[numofcore][ptr->type];
1219 if(corenum < NUMCORES) {
1221 queues = objectqueues[corenum][ptr->type];
1222 length = numqueues[corenum][ptr->type];
1232 raw_test_pass(0xbb000000 + ptr->flag);
1235 /*Remove object from all queues */
1236 for(i = 0; i < length; ++i) {
1237 flagptr = queues[i];
1238 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1239 ObjectHashremove(flagptr->objectset, (int)ptr);
1240 if (enterflags!=NULL)
1241 RUNFREE(enterflags);
1245 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1246 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1249 struct QueueItem *tmpptr;
1250 struct parameterwrapper * parameter=NULL;
1253 struct parameterwrapper * prevptr=NULL;
1254 struct ___Object___ *tagptr=NULL;
1255 struct parameterwrapper ** queues = vqueues;
1256 int length = vlength;
1258 if(corenum > NUMCORES - 1) {
1262 if(queues == NULL) {
1263 #ifdef THREADSIMULATE
1264 int numofcore = pthread_getspecific(key);
1265 queues = objectqueues[numofcore][ptr->type];
1266 length = numqueues[numofcore][ptr->type];
1268 queues = objectqueues[corenum][ptr->type];
1269 length = numqueues[corenum][ptr->type];
1272 tagptr=ptr->___tags___;
1274 /* Outer loop iterates through all parameter queues an object of
1275 this type could be in. */
1276 for(j = 0; j < length; ++j) {
1277 parameter = queues[j];
1279 if (parameter->numbertags>0) {
1281 goto nextloop; //that means the object has no tag but that param needs tag
1282 else if(tagptr->type==TAGTYPE) { //one tag
1283 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1284 for(i=0; i<parameter->numbertags; i++) {
1285 //slotid is parameter->tagarray[2*i];
1286 int tagid=parameter->tagarray[2*i+1];
1287 if (tagid!=tagptr->flag)
1288 goto nextloop; /*We don't have this tag */
1290 } else { //multiple tags
1291 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1292 for(i=0; i<parameter->numbertags; i++) {
1293 //slotid is parameter->tagarray[2*i];
1294 int tagid=parameter->tagarray[2*i+1];
1296 for(j=0; j<ao->___cachedCode___; j++) {
1297 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1308 for(i=0; i<parameter->numberofterms; i++) {
1309 int andmask=parameter->intarray[i*2];
1310 int checkmask=parameter->intarray[i*2+1];
1311 if ((ptr->flag&andmask)==checkmask) {
1313 raw_test_pass(0xcc000000 + andmask);
1314 raw_test_pass_reg((int)ptr);
1315 raw_test_pass(0xcc000000 + ptr->flag);
1316 raw_test_pass(0xcc000000 + checkmask);
1318 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1330 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1331 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1334 struct QueueItem *tmpptr;
1335 struct parameterwrapper * parameter=NULL;
1338 struct parameterwrapper * prevptr=NULL;
1339 struct ___Object___ *tagptr=NULL;
1340 struct parameterwrapper ** queues = vqueues;
1341 int length = vlength;
1343 if(corenum > NUMCORES - 1) {
1347 if(queues == NULL) {
1348 #ifdef THREADSIMULATE
1349 int numofcore = pthread_getspecific(key);
1350 queues = objectqueues[numofcore][ptr->type];
1351 length = numqueues[numofcore][ptr->type];
1353 queues = objectqueues[corenum][ptr->type];
1354 length = numqueues[corenum][ptr->type];
1358 raw_test_pass(0xeaa1);
1359 raw_test_pass_reg(queues);
1360 raw_test_pass_reg(length);
1362 tagptr=ptr->___tags___;
1364 /* Outer loop iterates through all parameter queues an object of
1365 this type could be in. */
1366 for(j = 0; j < length; ++j) {
1367 parameter = queues[j];
1369 if (parameter->numbertags>0) {
1371 raw_test_pass(0xeaa2);
1372 raw_test_pass_reg(tagptr);
1375 goto nextloop; //that means the object has no tag but that param needs tag
1376 else if(tagptr->type==TAGTYPE) { //one tag
1377 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1379 raw_test_pass(0xeaa3);
1381 for(i=0; i<parameter->numbertags; i++) {
1382 //slotid is parameter->tagarray[2*i];
1383 int tagid=parameter->tagarray[2*i+1];
1384 if (tagid!=tagptr->flag) {
1386 raw_test_pass(0xeaa4);
1388 goto nextloop; /*We don't have this tag */
1391 } else { //multiple tags
1392 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1394 raw_test_pass(0xeaa5);
1396 for(i=0; i<parameter->numbertags; i++) {
1397 //slotid is parameter->tagarray[2*i];
1398 int tagid=parameter->tagarray[2*i+1];
1400 for(j=0; j<ao->___cachedCode___; j++) {
1401 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1406 raw_test_pass(0xeaa6);
1416 for(i=0; i<parameter->numberofterms; i++) {
1417 int andmask=parameter->intarray[i*2];
1418 int checkmask=parameter->intarray[i*2+1];
1420 raw_test_pass(0xeaa7);
1421 raw_test_pass(0xcc000000 + andmask);
1422 raw_test_pass_reg(ptr);
1423 raw_test_pass(0xcc000000 + ptr->flag);
1424 raw_test_pass(0xcc000000 + checkmask);
1426 if ((ptr->flag&andmask)==checkmask) {
1428 raw_test_pass(0xeaa8);
1430 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1441 // helper function to compute the coordinates of a core from the core number
1442 void calCoords(int core_num, int* coordY, int* coordX) {
1443 *coordX = core_num % 4;
1444 *coordY = core_num / 4;
1448 void addAliasLock(void * ptr, int lock) {
1449 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1450 if(obj->numlocks == 0) {
1451 // originally no alias locks associated
1452 obj->locks = (int *)lock;
1456 // already have some alias locks
1457 // insert the new lock into the sorted lock linklist
1459 prev = next = (int)obj->locks;
1462 // next is less than lock, move to next node
1464 next = *((int *)next);
1465 } else if(next == lock) {
1466 // already have this lock, do nothing
1469 // insert the lock between prev and next
1473 *(int *)prev = lock;
1474 *(int *)lock = next;
1479 /* Message format for RAW version:
1481 * type: 0 -- transfer object
1482 * 1 -- transfer stall msg
1487 * 6 -- transfer profile output msg
1488 * 7 -- transfer profile output finish msg
1490 * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1491 * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1492 * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
1493 * 3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
1494 * lock type: 0 -- read; 1 -- write
1495 * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
1496 * 7 + corenum (size is always 2 * sizeof(int))
1499 // transfer an object to targetcore
1501 void transferObject(struct transObjInfo * transObj) {
1502 void * obj = transObj->objptr;
1503 int type=((int *)obj)[0];
1504 int size=classsize[type];
1505 int targetcore = transObj->targetcore;
1509 int self_y, self_x, target_y, target_x;
1510 // for 32 bit machine, the size of fixed part is always 3 words
1511 int msgsize = 3 + transObj->length * 2;
1514 struct ___Object___ * newobj = (struct ___Object___ *)obj;
1516 calCoords(corenum, &self_y, &self_x);
1517 calCoords(targetcore, &target_y, &target_x);
1518 // Build the message header
1519 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1521 target_y, target_x);
1522 // start sending msg, set sand msg flag
1523 isMsgSending = true;
1524 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1526 raw_test_pass(0xbbbb);
1527 raw_test_pass(0xb000 + targetcore); // targetcore
1535 raw_test_pass_reg(msgsize);
1539 raw_test_pass_reg(obj);
1541 for(i = 0; i < transObj->length; ++i) {
1542 int taskindex = transObj->queues[2*i];
1543 int paramindex = transObj->queues[2*i+1];
1544 gdn_send(taskindex);
1546 raw_test_pass_reg(taskindex);
1548 gdn_send(paramindex);
1550 raw_test_pass_reg(paramindex);
1554 raw_test_pass(0xffff);
1556 ++(self_numsendobjs);
1557 // end of sending this msg, set sand msg flag false
1558 isMsgSending = false;
1559 // check if there are pending msgs
1560 while(isMsgHanging) {
1561 // get the msg from outmsgdata[]
1562 // length + target + msg
1563 outmsgleft = outmsgdata[outmsgindex++];
1564 targetcore = outmsgdata[outmsgindex++];
1565 calCoords(targetcore, &target_y, &target_x);
1566 // Build the message header
1567 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1569 target_y, target_x);
1570 isMsgSending = true;
1571 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1573 raw_test_pass(0xbbbb);
1574 raw_test_pass(0xb000 + targetcore); // targetcore
1576 while(outmsgleft-- > 0) {
1577 gdn_send(outmsgdata[outmsgindex++]);
1579 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1583 raw_test_pass(0xffff);
1585 isMsgSending = false;
1587 raw_user_interrupts_off();
1589 // check if there are still msg hanging
1590 if(outmsgindex == outmsglast) {
1592 outmsgindex = outmsglast = 0;
1593 isMsgHanging = false;
1596 raw_user_interrupts_on();
1599 #elif defined THREADSIMULATE
1600 int numofcore = pthread_getspecific(key);
1602 // use POSIX message queue to transfer objects between cores
1606 if(targetcore < 10) {
1607 corenumstr[0] = targetcore + '0';
1608 corenumstr[1] = '\0';
1610 } else if(targetcore < 100) {
1611 corenumstr[1] = targetcore % 10 + '0';
1612 corenumstr[0] = (targetcore / 10) + '0';
1613 corenumstr[2] = '\0';
1616 printf("Error: targetcore >= 100\n");
1620 char * pathhead = "/msgqueue_";
1621 int targetlen = strlen(pathhead);
1622 char path[targetlen + sourcelen + 1];
1623 strcpy(path, pathhead);
1624 strncat(path, corenumstr, sourcelen);
1625 int oflags = O_WRONLY|O_NONBLOCK;
1626 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1627 mqdnum = mq_open(path, oflags, omodes, NULL);
1629 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1633 struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1634 memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1635 int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1636 memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1637 tmptransObj->queues = tmpqueue;
1638 struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1639 newobj->type = ((struct ___Object___ *)obj)->type;
1640 newobj->original = (struct ___Object___ *)tmptransObj;
1643 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1645 printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1649 if(numofcore == STARTUPCORE) {
1650 ++numsendobjs[numofcore];
1652 ++(thread_data_array[numofcore].numsendobjs);
1654 printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1658 // send terminate message to targetcore
1660 bool transStallMsg(int targetcore) {
1663 int self_y, self_x, target_y, target_x;
1664 // for 32 bit machine, the size is always 4 words
1665 //int msgsize = sizeof(int) * 4;
1668 calCoords(corenum, &self_y, &self_x);
1669 calCoords(targetcore, &target_y, &target_x);
1670 // Build the message header
1671 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1673 target_y, target_x);
1674 // start sending msgs, set msg sending flag
1675 isMsgSending = true;
1676 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1678 raw_test_pass(0xbbbb);
1679 raw_test_pass(0xb000 + targetcore); // targetcore
1687 raw_test_pass_reg(corenum);
1689 gdn_send(self_numsendobjs);
1691 raw_test_pass_reg(self_numsendobjs);
1693 gdn_send(self_numreceiveobjs);
1695 raw_test_pass_reg(self_numreceiveobjs);
1696 raw_test_pass(0xffff);
1698 // end of sending this msg, set sand msg flag false
1699 isMsgSending = false;
1700 // check if there are pending msgs
1701 while(isMsgHanging) {
1702 // get the msg from outmsgdata[]
1703 // length + target + msg
1704 outmsgleft = outmsgdata[outmsgindex++];
1705 targetcore = outmsgdata[outmsgindex++];
1706 calCoords(targetcore, &target_y, &target_x);
1707 // Build the message header
1708 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1710 target_y, target_x);
1711 isMsgSending = true;
1712 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1714 raw_test_pass(0xbbbb);
1715 raw_test_pass(0xb000 + targetcore); // targetcore
1717 while(outmsgleft-- > 0) {
1718 gdn_send(outmsgdata[outmsgindex++]);
1720 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1724 raw_test_pass(0xffff);
1726 isMsgSending = false;
1728 raw_user_interrupts_off();
1730 // check if there are still msg hanging
1731 if(outmsgindex == outmsglast) {
1733 outmsgindex = outmsglast = 0;
1734 isMsgHanging = false;
1737 raw_user_interrupts_on();
1741 #elif defined THREADSIMULATE
1742 struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1743 // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1745 int numofcore = pthread_getspecific(key);
1746 newobj->flag = numofcore;
1747 newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1748 newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1750 // use POSIX message queue to send stall msg to startup core
1751 assert(targetcore == STARTUPCORE);
1755 if(targetcore < 10) {
1756 corenumstr[0] = targetcore + '0';
1757 corenumstr[1] = '\0';
1759 } else if(targetcore < 100) {
1760 corenumstr[1] = targetcore % 10 + '0';
1761 corenumstr[0] = (targetcore / 10) + '0';
1762 corenumstr[2] = '\0';
1765 printf("Error: targetcore >= 100\n");
1769 char * pathhead = "/msgqueue_";
1770 int targetlen = strlen(pathhead);
1771 char path[targetlen + sourcelen + 1];
1772 strcpy(path, pathhead);
1773 strncat(path, corenumstr, sourcelen);
1774 int oflags = O_WRONLY|O_NONBLOCK;
1775 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1776 mqdnum = mq_open(path, oflags, omodes, NULL);
1778 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1783 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1785 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1789 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1790 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1798 // send profile request message to targetcore
1800 bool transProfileRequestMsg(int targetcore) {
1802 int self_y, self_x, target_y, target_x;
1803 // for 32 bit machine, the size is always 4 words
1806 calCoords(corenum, &self_y, &self_x);
1807 calCoords(targetcore, &target_y, &target_x);
1808 // Build the message header
1809 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1811 target_y, target_x);
1812 // start sending msgs, set msg sending flag
1813 isMsgSending = true;
1814 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1816 raw_test_pass(0xbbbb);
1817 raw_test_pass(0xb000 + targetcore); // targetcore
1823 gdn_send(totalexetime);
1825 raw_test_pass_reg(totalexetime);
1826 raw_test_pass(0xffff);
1828 // end of sending this msg, set sand msg flag false
1829 isMsgSending = false;
1830 // check if there are pending msgs
1831 while(isMsgHanging) {
1832 // get the msg from outmsgdata[]
1833 // length + target + msg
1834 outmsgleft = outmsgdata[outmsgindex++];
1835 targetcore = outmsgdata[outmsgindex++];
1836 calCoords(targetcore, &target_y, &target_x);
1837 // Build the message header
1838 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1840 target_y, target_x);
1841 isMsgSending = true;
1844 raw_test_pass(0xbbbb);
1845 raw_test_pass(0xb000 + targetcore); // targetcore
1847 while(outmsgleft-- > 0) {
1848 gdn_send(outmsgdata[outmsgindex++]);
1850 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1854 raw_test_pass(0xffff);
1856 isMsgSending = false;
1858 raw_user_interrupts_off();
1860 // check if there are still msg hanging
1861 if(outmsgindex == outmsglast) {
1863 outmsgindex = outmsglast = 0;
1864 isMsgHanging = false;
1867 raw_user_interrupts_on();
1873 // output the profiling data
1874 void outputProfileData() {
1881 int totaltasktime = 0;
1882 int preprocessingtime = 0;
1883 int objqueuecheckingtime = 0;
1884 int postprocessingtime = 0;
1885 //int interruptiontime = 0;
1887 int averagetasktime = 0;
1890 for(i = 0; i < 50; i++) {
1894 calCoords(corenum, &self_y, &self_x);
1895 c_y = (char)self_y + '0';
1896 c_x = (char)self_x + '0';
1897 strcat(fn, "profile_");
1903 if((fp = fopen(fn, "w+")) == NULL) {
1904 fprintf(stderr, "fopen error\n");
1908 fprintf(fp, "Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
1909 // output task related info
1910 for(i = 0; i < taskInfoIndex; i++) {
1911 TaskInfo* tmpTInfo = taskInfoArray[i];
1912 int duration = tmpTInfo->endTime - tmpTInfo->startTime;
1913 fprintf(fp, "%s, %d, %d, %d, %d", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration, tmpTInfo->exitIndex);
1914 // summarize new obj info
1915 if(tmpTInfo->newObjs != NULL) {
1916 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
1917 struct RuntimeIterator * iter = NULL;
1918 while(0 == isEmpty(tmpTInfo->newObjs)) {
1919 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
1920 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
1922 RuntimeHashget(nobjtbl, (int)objtype, &num);
1923 RuntimeHashremovekey(nobjtbl, (int)objtype);
1925 RuntimeHashadd(nobjtbl, (int)objtype, num);
1927 RuntimeHashadd(nobjtbl, (int)objtype, 1);
1929 //fprintf(stderr, "new obj!\n");
1932 // output all new obj info
1933 iter = RuntimeHashcreateiterator(nobjtbl);
1934 while(RunhasNext(iter)) {
1935 char * objtype = (char *)Runkey(iter);
1936 int num = Runnext(iter);
1937 fprintf(fp, ", %s, %d", objtype, num);
1941 if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
1942 preprocessingtime += duration;
1943 } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
1944 postprocessingtime += duration;
1945 } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
1946 objqueuecheckingtime += duration;
1948 totaltasktime += duration;
1949 averagetasktime += duration;
1954 if(taskInfoOverflow) {
1955 fprintf(stderr, "Caution: task info overflow!\n");
1958 other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
1959 averagetasktime /= tasknum;
1961 fprintf(fp, "\nTotal time: %d\n", totalexetime);
1962 fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
1963 fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
1964 fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
1965 fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
1966 fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
1968 fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
1975 raw_test_pass(0xdddd);
1976 // output task related info
1977 for(i= 0; i < taskInfoIndex; i++) {
1978 TaskInfo* tmpTInfo = taskInfoArray[i];
1979 char* tmpName = tmpTInfo->taskName;
1980 int nameLen = strlen(tmpName);
1981 raw_test_pass(0xddda);
1982 for(j = 0; j < nameLen; j++) {
1983 raw_test_pass_reg(tmpName[j]);
1985 raw_test_pass(0xdddb);
1986 raw_test_pass_reg(tmpTInfo->startTime);
1987 raw_test_pass_reg(tmpTInfo->endTime);
1988 raw_test_pass_reg(tmpTInfo->exitIndex);
1989 if(tmpTInfo->newObjs != NULL) {
1990 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
1991 struct RuntimeIterator * iter = NULL;
1992 while(0 == isEmpty(tmpTInfo->newObjs)) {
1993 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
1994 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
1996 RuntimeHashget(nobjtbl, (int)objtype, &num);
1997 RuntimeHashremovekey(nobjtbl, (int)objtype);
1999 RuntimeHashadd(nobjtbl, (int)objtype, num);
2001 RuntimeHashadd(nobjtbl, (int)objtype, 1);
2005 // ouput all new obj info
2006 iter = RuntimeHashcreateiterator(nobjtbl);
2007 while(RunhasNext(iter)) {
2008 char * objtype = (char *)Runkey(iter);
2009 int num = Runnext(iter);
2010 int nameLen = strlen(objtype);
2011 raw_test_pass(0xddda);
2012 for(j = 0; j < nameLen; j++) {
2013 raw_test_pass_reg(objtype[j]);
2015 raw_test_pass(0xdddb);
2016 raw_test_pass_reg(num);
2019 raw_test_pass(0xdddc);
2022 if(taskInfoOverflow) {
2023 raw_test_pass(0xefee);
2026 // output interrupt related info
2027 /*for(i = 0; i < interruptInfoIndex; i++) {
2028 InterruptInfo* tmpIInfo = interruptInfoArray[i];
2029 raw_test_pass(0xddde);
2030 raw_test_pass_reg(tmpIInfo->startTime);
2031 raw_test_pass_reg(tmpIInfo->endTime);
2032 raw_test_pass(0xdddf);
2035 if(interruptInfoOverflow) {
2036 raw_test_pass(0xefef);
2039 raw_test_pass(0xeeee);
2043 inline void setTaskExitIndex(int index) {
2044 taskInfoArray[taskInfoIndex]->exitIndex = index;
2047 inline void addNewObjInfo(void * nobj) {
2048 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
2049 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
2051 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
2055 // receive object transferred from other cores
2056 // or the terminate message from other cores
2057 // NOTICE: following format is for threadsimulate version only
2058 // RAW version please see previous description
2059 // format: type + object
2060 // type: -1--stall msg
2062 // return value: 0--received an object
2063 // 1--received nothing
2064 // 2--received a Stall Msg
2065 // 3--received a lock Msg
2066 // RAW version: -1 -- received nothing
2067 // otherwise -- received msg type
2068 int receiveObject() {
2072 int self_y, self_x, target_y, target_x;
2074 if(gdn_input_avail() == 0) {
2076 if(corenum < NUMCORES) {
2077 raw_test_pass(0xd001);
2083 /*if(isInterrupt && (!interruptInfoOverflow)) {
2084 // raw_test_pass(0xffff);
2085 interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
2086 interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
2087 interruptInfoArray[interruptInfoIndex]->endTime = -1;
2092 raw_test_pass(0xcccc);
2094 while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
2095 msgdata[msgdataindex] = gdn_receive();
2096 if(msgdataindex == 0) {
2097 if(msgdata[0] == 7) {
2099 } else if(msgdata[0] == 6) {
2101 } else if(msgdata[0] > 2) {
2103 } else if(msgdata[0] > 0) {
2106 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
2107 msglength = msgdata[msgdataindex];
2110 raw_test_pass_reg(msgdata[msgdataindex]);
2115 raw_test_pass(0xffff);
2117 if(msgdataindex == msglength) {
2118 // received a whole msg
2119 int type, data1, data2; // will receive at least 3 words including type
2125 // receive a object transfer msg
2126 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
2128 if(corenum > NUMCORES - 1) {
2129 raw_test_done(0xa00a);
2131 // store the object and its corresponding queue info, enqueue it later
2132 transObj->objptr = (void *)data2; // data1 is now size of the msg
2133 transObj->length = (msglength - 3) / 2;
2134 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
2135 for(k = 0; k < transObj->length; ++k) {
2136 transObj->queues[2*k] = msgdata[3+2*k];
2138 raw_test_pass_reg(transObj->queues[2*k]);
2140 transObj->queues[2*k+1] = msgdata[3+2*k+1];
2142 raw_test_pass_reg(transObj->queues[2*k+1]);
2145 // check if there is an existing duplicate item
2147 struct QueueItem * qitem = getTail(&objqueue);
2148 struct QueueItem * prev = NULL;
2149 while(qitem != NULL) {
2150 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
2151 if(tmpinfo->objptr == transObj->objptr) {
2152 // the same object, remove outdate one
2153 removeItem(&objqueue, qitem);
2158 qitem = getTail(&objqueue);
2160 qitem = getNextQueueItem(prev);
2163 addNewItem_I(&objqueue, (void *)transObj);
2165 ++(self_numreceiveobjs);
2167 raw_test_pass(0xe881);
2173 // receive a stall msg
2174 if(corenum != STARTUPCORE) {
2175 // non startup core can not receive stall msg
2177 raw_test_done(0xa001);
2179 if(data1 < NUMCORES) {
2181 raw_test_pass(0xe882);
2183 corestatus[data1] = 0;
2184 numsendobjs[data1] = data2;
2185 numreceiveobjs[data1] = msgdata[3];
2191 // receive lock request msg
2192 // for 32 bit machine, the size is always 3 words
2193 //int msgsize = sizeof(int) * 3;
2195 // lock request msg, handle it right now
2196 // check to see if there is a lock exist in locktbl for the required obj
2197 int data3 = msgdata[3];
2199 if(!RuntimeHashcontainskey(locktbl, data2)) {
2200 // no locks for this object
2201 // first time to operate on this shared object
2202 // create a lock for it
2203 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2205 raw_test_pass(0xe883);
2208 RuntimeHashadd_I(locktbl, data2, 1);
2210 RuntimeHashadd_I(locktbl, data2, -1);
2215 raw_test_pass(0xe884);
2217 RuntimeHashget(locktbl, data2, &rwlock_obj);
2219 raw_test_pass_reg(rwlock_obj);
2221 if(0 == rwlock_obj) {
2227 RuntimeHashremovekey(locktbl, data2);
2228 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2229 } else if((rwlock_obj > 0) && (data1 == 0)) {
2230 // read lock request and there are only read locks
2232 RuntimeHashremovekey(locktbl, data2);
2233 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2238 raw_test_pass_reg(rwlock_obj);
2242 // check if there is still some msg on sending
2245 raw_test_pass(0xe885);
2247 isMsgHanging = true;
2248 // cache the msg in outmsgdata and send it later
2249 // msglength + target core + msg
2250 outmsgdata[outmsglast++] = msgsize;
2251 outmsgdata[outmsglast++] = targetcore;
2253 outmsgdata[outmsglast++] = 4;
2255 outmsgdata[outmsglast++] = 3;
2257 outmsgdata[outmsglast++] = data1;
2258 outmsgdata[outmsglast++] = data2;
2261 raw_test_pass(0xe886);
2263 // no msg on sending, send it out
2264 calCoords(corenum, &self_y, &self_x);
2265 calCoords(targetcore, &target_y, &target_x);
2266 // Build the message header
2267 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2269 target_y, target_x);
2270 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2272 raw_test_pass(0xbbbb);
2273 raw_test_pass(0xb000 + targetcore); // targetcore
2276 // deny the lock request
2277 gdn_send(4); // lock request
2282 // grount the lock request
2283 gdn_send(3); // lock request
2288 gdn_send(data1); // lock type
2290 raw_test_pass_reg(data1);
2292 gdn_send(data2); // lock target
2294 raw_test_pass_reg(data2);
2295 raw_test_pass(0xffff);
2302 // receive lock grount msg
2303 if(corenum > NUMCORES - 1) {
2304 raw_test_done(0xa00b);
2306 if(lockobj == data2) {
2313 // conflicts on lockresults
2314 raw_test_done(0xa002);
2320 // receive lock grount/deny msg
2321 if(corenum > NUMCORES - 1) {
2322 raw_test_done(0xa00c);
2324 if(lockobj == data2) {
2331 // conflicts on lockresults
2332 raw_test_done(0xa003);
2338 // receive lock release msg
2339 if(!RuntimeHashcontainskey(locktbl, data2)) {
2340 // no locks for this object, something is wrong
2341 //raw_test_pass_reg(data2);
2342 raw_test_done(0xa004);
2345 RuntimeHashget(locktbl, data2, &rwlock_obj);
2347 raw_test_pass(0xe887);
2348 raw_test_pass_reg(rwlock_obj);
2355 RuntimeHashremovekey(locktbl, data2);
2356 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2358 raw_test_pass_reg(rwlock_obj);
2366 // receive an output request msg
2367 if(corenum == STARTUPCORE) {
2368 // startup core can not receive profile output finish msg
2369 raw_test_done(0xa00a);
2374 totalexetime = data1;
2375 outputProfileData();
2376 /*if(data1 >= NUMCORES) {
2377 raw_test_pass(0xee04);
2378 raw_test_pass_reg(taskInfoIndex);
2379 raw_test_pass_reg(taskInfoOverflow);
2380 if(!taskInfoOverflow) {
2381 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
2383 if(taskInfoIndex == TASKINFOLENGTH) {
2384 taskInfoOverflow = true;
2388 // no msg on sending, send it out
2389 targetcore = STARTUPCORE;
2390 calCoords(corenum, &self_y, &self_x);
2391 calCoords(targetcore, &target_y, &target_x);
2392 // Build the message header
2393 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2395 target_y, target_x);
2398 raw_test_pass(0xbbbb);
2399 raw_test_pass(0xb000 + targetcore); // targetcore
2407 raw_test_pass_reg(corenum);
2408 raw_test_pass(0xffff);
2415 // receive a profile output finish msg
2416 if(corenum != STARTUPCORE) {
2417 // non startup core can not receive profile output finish msg
2418 raw_test_done(0xa00b);
2420 profilestatus[data1] = 0;
2428 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
2429 msgdata[msgdataindex] = -1;
2434 raw_test_pass(0xe888);
2436 if(gdn_input_avail() != 0) {
2440 /* if(isInterrupt && (!interruptInfoOverflow)) {
2441 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2442 interruptInfoIndex++;
2443 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2444 interruptInfoOverflow = true;
2452 raw_test_pass(0xe889);
2455 /* if(isInterrupt && (!interruptInfoOverflow)) {
2456 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2457 interruptInfoIndex++;
2458 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2459 interruptInfoOverflow = true;
2465 #elif defined THREADSIMULATE
2466 int numofcore = pthread_getspecific(key);
2467 // use POSIX message queue to transfer object
2469 struct mq_attr mqattr;
2470 mq_getattr(mqd[numofcore], &mqattr);
2471 void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
2472 msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
2478 //printf("msg: %s\n",msgptr);
2479 if(((int*)msgptr)[0] == -1) {
2481 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2482 int index = tmpptr->flag;
2483 corestatus[index] = 0;
2484 numsendobjs[index] = tmpptr->___cachedHash___;
2485 numreceiveobjs[index] = tmpptr->___cachedCode___;
2486 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
2491 if(numofcore == STARTUPCORE) {
2492 ++(numreceiveobjs[numofcore]);
2494 ++(thread_data_array[numofcore].numreceiveobjs);
2496 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2497 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
2498 tmpptr = (struct ___Object___ *)(transObj->objptr);
2499 int type = tmpptr->type;
2500 int size=classsize[type];
2501 struct ___Object___ * newobj=RUNMALLOC(size);
2502 memcpy(newobj, tmpptr, size);
2503 if(0 == newobj->isolate) {
2504 newobj->original=tmpptr;
2509 for(k = 0; k < transObj->length; ++k) {
2510 int taskindex = transObj->queues[2 * k];
2511 int paramindex = transObj->queues[2 * k + 1];
2512 struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2513 enqueueObject(newobj, queues, 1);
2515 RUNFREE(transObj->queues);
2522 bool getreadlock(void * ptr) {
2525 int self_y, self_x, target_y, target_x;
2526 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2527 // for 32 bit machine, the size is always 4 words
2531 raw_user_interrupts_off();
2533 targetcore = ((int)ptr >> 5) % tc;
2535 raw_user_interrupts_on();
2545 if(targetcore == corenum) {
2546 // reside on this core
2549 raw_user_interrupts_off();
2551 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2552 // no locks for this object
2553 // first time to operate on this shared object
2554 // create a lock for it
2555 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2556 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2559 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2560 if(-1 != rwlock_obj) {
2562 RuntimeHashremovekey(locktbl, (int)ptr);
2563 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2569 raw_user_interrupts_on();
2571 if(lockobj == (int)ptr) {
2582 // conflicts on lockresults
2583 raw_test_done(0xa005);
2588 calCoords(corenum, &self_y, &self_x);
2589 calCoords(targetcore, &target_y, &target_x);
2590 // Build the message header
2591 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2593 target_y, target_x);
2594 // start sending the msg, set send msg flag
2595 isMsgSending = true;
2596 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2598 raw_test_pass(0xbbbb);
2599 raw_test_pass(0xb000 + targetcore); // targetcore
2601 gdn_send(2); // lock request
2605 gdn_send(0); // read lock
2611 raw_test_pass_reg(ptr);
2615 raw_test_pass_reg(corenum);
2616 raw_test_pass(0xffff);
2618 // end of sending this msg, set sand msg flag false
2619 isMsgSending = false;
2620 // check if there are pending msgs
2621 while(isMsgHanging) {
2622 // get the msg from outmsgdata[]
2623 // length + target + msg
2624 outmsgleft = outmsgdata[outmsgindex++];
2625 targetcore = outmsgdata[outmsgindex++];
2626 calCoords(targetcore, &target_y, &target_x);
2627 // Build the message header
2628 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2630 target_y, target_x);
2631 isMsgSending = true;
2632 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2634 raw_test_pass(0xbbbb);
2635 raw_test_pass(0xb000 + targetcore); // targetcore
2637 while(outmsgleft-- > 0) {
2638 gdn_send(outmsgdata[outmsgindex++]);
2640 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2644 raw_test_pass(0xffff);
2646 isMsgSending = false;
2648 raw_user_interrupts_off();
2650 // check if there are still msg hanging
2651 if(outmsgindex == outmsglast) {
2653 outmsgindex = outmsglast = 0;
2654 isMsgHanging = false;
2657 raw_user_interrupts_on();
2661 #elif defined THREADSIMULATE
2662 int numofcore = pthread_getspecific(key);
2664 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2665 printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2669 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2670 // no locks for this object
2671 // first time to operate on this shared object
2672 // create a lock for it
2673 rc = pthread_rwlock_unlock(&rwlock_tbl);
2674 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2675 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2676 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2677 rc = pthread_rwlock_init(rwlock, NULL);
2678 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2679 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2680 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2685 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2687 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2690 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2692 rc = pthread_rwlock_unlock(&rwlock_tbl);
2693 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2695 rc = pthread_rwlock_tryrdlock(rwlock);
2696 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2703 pthread_rwlock_t* rwlock_obj = NULL;
2704 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2705 rc = pthread_rwlock_unlock(&rwlock_tbl);
2706 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2707 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
2708 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2718 void releasereadlock(void * ptr) {
2721 int self_y, self_x, target_y, target_x;
2722 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2723 // for 32 bit machine, the size is always 3 words
2727 raw_user_interrupts_off();
2729 targetcore = ((int)ptr >> 5) % tc;
2731 raw_user_interrupts_on();
2734 if(targetcore == corenum) {
2736 raw_user_interrupts_off();
2738 // reside on this core
2739 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2740 // no locks for this object, something is wrong
2741 raw_test_done(0xa006);
2744 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2746 RuntimeHashremovekey(locktbl, (int)ptr);
2747 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2750 raw_user_interrupts_on();
2755 calCoords(corenum, &self_y, &self_x);
2756 calCoords(targetcore, &target_y, &target_x);
2757 // Build the message header
2758 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2760 target_y, target_x);
2761 // start sending the msg, set send msg flag
2762 isMsgSending = true;
2763 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2765 raw_test_pass(0xbbbb);
2766 raw_test_pass(0xb000 + targetcore); // targetcore
2768 gdn_send(5); // lock release
2772 gdn_send(0); // read lock
2778 raw_test_pass_reg(ptr);
2779 raw_test_pass(0xffff);
2781 // end of sending this msg, set sand msg flag false
2782 isMsgSending = false;
2783 // check if there are pending msgs
2784 while(isMsgHanging) {
2785 // get the msg from outmsgdata[]
2786 // length + target + msg
2787 outmsgleft = outmsgdata[outmsgindex++];
2788 targetcore = outmsgdata[outmsgindex++];
2789 calCoords(targetcore, &target_y, &target_x);
2790 // Build the message header
2791 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2793 target_y, target_x);
2794 isMsgSending = true;
2795 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2797 raw_test_pass(0xbbbb);
2798 raw_test_pass(0xb000 + targetcore); // targetcore
2800 while(outmsgleft-- > 0) {
2801 gdn_send(outmsgdata[outmsgindex++]);
2803 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2807 raw_test_pass(0xffff);
2809 isMsgSending = false;
2811 raw_user_interrupts_off();
2813 // check if there are still msg hanging
2814 if(outmsgindex == outmsglast) {
2816 outmsgindex = outmsglast = 0;
2817 isMsgHanging = false;
2820 raw_user_interrupts_on();
2823 #elif defined THREADSIMULATE
2824 int numofcore = pthread_getspecific(key);
2825 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2826 printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2827 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2828 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2831 pthread_rwlock_t* rwlock_obj = NULL;
2832 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2833 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2834 printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2835 rc = pthread_rwlock_unlock(&rwlock_tbl);
2836 printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2841 bool getreadlock_I(void * ptr) {
2843 int self_y, self_x, target_y, target_x;
2844 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2845 // for 32 bit machine, the size is always 4 words
2855 if(targetcore == corenum) {
2856 // reside on this core
2858 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2859 // no locks for this object
2860 // first time to operate on this shared object
2861 // create a lock for it
2862 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2863 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2866 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2867 if(-1 != rwlock_obj) {
2869 RuntimeHashremovekey(locktbl, (int)ptr);
2870 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2875 if(lockobj == (int)ptr) {
2886 // conflicts on lockresults
2887 raw_test_done(0xa005);
2892 calCoords(corenum, &self_y, &self_x);
2893 calCoords(targetcore, &target_y, &target_x);
2894 // Build the message header
2895 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2897 target_y, target_x);
2898 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2900 raw_test_pass(0xbbbb);
2901 raw_test_pass(0xb000 + targetcore); // targetcore
2903 gdn_send(2); // lock request
2907 gdn_send(0); // read lock
2913 raw_test_pass_reg(ptr);
2917 raw_test_pass_reg(corenum);
2918 raw_test_pass(0xffff);
2923 void releasereadlock_I(void * ptr) {
2925 int self_y, self_x, target_y, target_x;
2926 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2927 // for 32 bit machine, the size is always 3 words
2930 if(targetcore == corenum) {
2931 // reside on this core
2932 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2933 // no locks for this object, something is wrong
2934 raw_test_done(0xa006);
2937 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2939 RuntimeHashremovekey(locktbl, (int)ptr);
2940 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2945 calCoords(corenum, &self_y, &self_x);
2946 calCoords(targetcore, &target_y, &target_x);
2947 // Build the message header
2948 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2950 target_y, target_x);
2951 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2953 raw_test_pass(0xbbbb);
2954 raw_test_pass(0xb000 + targetcore); // targetcore
2956 gdn_send(5); // lock release
2960 gdn_send(0); // read lock
2966 raw_test_pass_reg(ptr);
2967 raw_test_pass(0xffff);
2973 bool getwritelock(void * ptr) {
2976 int self_y, self_x, target_y, target_x;
2977 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2978 // for 32 bit machine, the size is always 4 words
2982 raw_user_interrupts_off();
2984 targetcore = ((int)ptr >> 5) % tc;
2986 raw_user_interrupts_on();
2990 raw_test_pass(0xe551);
2991 raw_test_pass_reg(ptr);
2992 raw_test_pass_reg(targetcore);
2993 raw_test_pass_reg(tc);
3003 if(targetcore == corenum) {
3004 // reside on this core
3007 raw_user_interrupts_off();
3009 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3010 // no locks for this object
3011 // first time to operate on this shared object
3012 // create a lock for it
3013 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3015 raw_test_pass(0xe552);
3017 RuntimeHashadd_I(locktbl, (int)ptr, -1);
3020 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3022 raw_test_pass(0xe553);
3023 raw_test_pass_reg(rwlock_obj);
3025 if(0 == rwlock_obj) {
3027 RuntimeHashremovekey(locktbl, (int)ptr);
3028 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
3034 raw_user_interrupts_on();
3037 raw_test_pass(0xe554);
3038 raw_test_pass_reg(lockresult);
3040 if(lockobj == (int)ptr) {
3057 // conflicts on lockresults
3058 raw_test_done(0xa007);
3064 raw_test_pass(0xe555);
3066 calCoords(corenum, &self_y, &self_x);
3067 calCoords(targetcore, &target_y, &target_x);
3068 // Build the message header
3069 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3071 target_y, target_x);
3072 // start sending the msg, set send msg flag
3073 isMsgSending = true;
3074 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3076 raw_test_pass(0xbbbb);
3077 raw_test_pass(0xb000 + targetcore); // targetcore
3079 gdn_send(2); // lock request
3083 gdn_send(1); // write lock
3089 raw_test_pass_reg(ptr);
3093 raw_test_pass_reg(corenum);
3094 raw_test_pass(0xffff);
3096 // end of sending this msg, set sand msg flag false
3097 isMsgSending = false;
3098 // check if there are pending msgs
3099 while(isMsgHanging) {
3100 // get the msg from outmsgdata[]
3101 // length + target + msg
3102 outmsgleft = outmsgdata[outmsgindex++];
3103 targetcore = outmsgdata[outmsgindex++];
3104 calCoords(targetcore, &target_y, &target_x);
3105 // Build the message header
3106 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3108 target_y, target_x);
3109 isMsgSending = true;
3110 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3112 raw_test_pass(0xbbbb);
3113 raw_test_pass(0xb000 + targetcore); // targetcore
3115 while(outmsgleft-- > 0) {
3116 gdn_send(outmsgdata[outmsgindex++]);
3118 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3122 raw_test_pass(0xffff);
3124 isMsgSending = false;
3126 raw_user_interrupts_off();
3128 // check if there are still msg hanging
3129 if(outmsgindex == outmsglast) {
3131 outmsgindex = outmsglast = 0;
3132 isMsgHanging = false;
3135 raw_user_interrupts_on();
3139 #elif defined THREADSIMULATE
3140 int numofcore = pthread_getspecific(key);
3142 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3143 printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3147 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3148 // no locks for this object
3149 // first time to operate on this shared object
3150 // create a lock for it
3151 rc = pthread_rwlock_unlock(&rwlock_tbl);
3152 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3153 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3154 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3155 rc = pthread_rwlock_init(rwlock, NULL);
3156 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3157 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3158 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3160 pthread_rwlock_destroy(rwlock);
3164 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3166 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3168 pthread_rwlock_destroy(rwlock);
3170 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3172 rc = pthread_rwlock_unlock(&rwlock_tbl);
3173 printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3175 rc = pthread_rwlock_trywrlock(rwlock);
3176 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3183 pthread_rwlock_t* rwlock_obj = NULL;
3184 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3185 rc = pthread_rwlock_unlock(&rwlock_tbl);
3186 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3187 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
3188 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3199 void releasewritelock(void * ptr) {
3202 int self_y, self_x, target_y, target_x;
3203 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
3204 // for 32 bit machine, the size is always 3 words
3208 raw_user_interrupts_off();
3210 targetcore = ((int)ptr >> 5) % tc;
3212 raw_user_interrupts_on();
3215 if(targetcore == corenum) {
3217 raw_user_interrupts_off();
3219 // reside on this core
3220 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3221 // no locks for this object, something is wrong
3222 raw_test_done(0xa008);
3226 raw_test_pass(0xe662);
3228 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3230 raw_test_pass_reg(rwlock_obj);
3233 RuntimeHashremovekey(locktbl, (int)ptr);
3234 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
3236 raw_test_pass_reg(rwlock_obj);
3240 raw_user_interrupts_on();
3246 raw_test_pass(0xe663);
3248 calCoords(corenum, &self_y, &self_x);
3249 calCoords(targetcore, &target_y, &target_x);
3250 // Build the message header
3251 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3253 target_y, target_x);
3254 // start sending the msg, set send msg flag
3255 isMsgSending = true;
3256 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3258 raw_test_pass(0xbbbb);
3259 raw_test_pass(0xb000 + targetcore);
3261 gdn_send(5); // lock release
3265 gdn_send(1); // write lock
3271 raw_test_pass_reg(ptr);
3272 raw_test_pass(0xffff);
3274 // end of sending this msg, set sand msg flag false
3275 isMsgSending = false;
3276 // check if there are pending msgs
3277 while(isMsgHanging) {
3278 // get the msg from outmsgdata[]
3279 // length + target + msg
3280 outmsgleft = outmsgdata[outmsgindex++];
3281 targetcore = outmsgdata[outmsgindex++];
3282 calCoords(targetcore, &target_y, &target_x);
3283 // Build the message header
3284 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3286 target_y, target_x);
3287 isMsgSending = true;
3288 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3290 raw_test_pass(0xbbbb);
3291 raw_test_pass(0xb000 + targetcore); // targetcore
3293 while(outmsgleft-- > 0) {
3294 gdn_send(outmsgdata[outmsgindex++]);
3296 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3300 raw_test_pass(0xffff);
3302 isMsgSending = false;
3304 raw_user_interrupts_off();
3306 // check if there are still msg hanging
3307 if(outmsgindex == outmsglast) {
3309 outmsgindex = outmsglast = 0;
3310 isMsgHanging = false;
3313 raw_user_interrupts_on();
3316 #elif defined THREADSIMULATE
3317 int numofcore = pthread_getspecific(key);
3318 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3319 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3320 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3321 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3324 pthread_rwlock_t* rwlock_obj = NULL;
3325 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3326 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3327 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3328 rc = pthread_rwlock_unlock(&rwlock_tbl);
3329 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3333 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3334 void * taskpointerarray[MAXTASKPARAMS];
3336 int numparams=parameter->task->numParameters;
3337 int numiterators=parameter->task->numTotal-1;
3342 struct taskdescriptor * task=parameter->task;
3344 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
3346 /* Add enqueued object to parameter vector */
3347 taskpointerarray[parameter->slot]=ptr;
3349 /* Reset iterators */
3350 for(j=0; j<numiterators; j++) {
3351 toiReset(¶meter->iterators[j]);
3354 /* Find initial state */
3355 for(j=0; j<numiterators; j++) {
3357 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3358 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3360 /* Need to backtrack */
3361 toiReset(¶meter->iterators[j]);
3365 /* Nothing to enqueue */
3372 /* Enqueue current state */
3374 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
3376 tpd->numParameters=numiterators+1;
3377 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
3378 for(j=0; j<=numiterators; j++) {
3379 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3382 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3383 genputtable(activetasks, tpd, tpd);
3385 RUNFREE(tpd->parameterArray);
3389 /* This loop iterates to the next parameter combination */
3390 if (numiterators==0)
3393 for(j=numiterators-1; j<numiterators; j++) {
3395 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3396 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3398 /* Need to backtrack */
3399 toiReset(¶meter->iterators[j]);
3403 /* Nothing more to enqueue */
3412 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3413 void * taskpointerarray[MAXTASKPARAMS];
3415 int numparams=parameter->task->numParameters;
3416 int numiterators=parameter->task->numTotal-1;
3421 struct taskdescriptor * task=parameter->task;
3423 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
3425 /* Add enqueued object to parameter vector */
3426 taskpointerarray[parameter->slot]=ptr;
3428 /* Reset iterators */
3429 for(j=0; j<numiterators; j++) {
3430 toiReset(¶meter->iterators[j]);
3433 /* Find initial state */
3434 for(j=0; j<numiterators; j++) {
3436 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3437 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3439 /* Need to backtrack */
3440 toiReset(¶meter->iterators[j]);
3444 /* Nothing to enqueue */
3450 /* Enqueue current state */
3452 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
3454 tpd->numParameters=numiterators+1;
3455 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
3456 for(j=0; j<=numiterators; j++) {
3457 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3460 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3461 genputtable_I(activetasks, tpd, tpd);
3463 RUNFREE(tpd->parameterArray);
3467 /* This loop iterates to the next parameter combination */
3468 if (numiterators==0)
3471 for(j=numiterators-1; j<numiterators; j++) {
3473 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3474 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3476 /* Need to backtrack */
3477 toiReset(¶meter->iterators[j]);
3481 /* Nothing more to enqueue */
3490 /* Handler for signals. The signals catch null pointer errors and
3491 arithmatic errors. */
3493 void myhandler(int sig, siginfo_t *info, void *uap) {
3496 printf("sig=%d\n",sig);
3499 sigemptyset(&toclear);
3500 sigaddset(&toclear, sig);
3501 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
3502 longjmp(error_handler,1);
3508 struct RuntimeHash *fdtoobject;
3510 void addreadfd(int fd) {
3513 FD_SET(fd, &readfds);
3516 void removereadfd(int fd) {
3517 FD_CLR(fd, &readfds);
3518 if (maxreadfd==(fd+1)) {
3520 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
3531 void executetasks() {
3532 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
3535 struct ___Object___ * tmpparam = NULL;
3536 struct parameterdescriptor * pd=NULL;
3537 struct parameterwrapper *pw=NULL;
3547 raw_test_pass(0xe991);
3552 /* Set up signal handlers */
3553 struct sigaction sig;
3554 sig.sa_sigaction=&myhandler;
3555 sig.sa_flags=SA_SIGINFO;
3556 sigemptyset(&sig.sa_mask);
3558 /* Catch bus errors, segmentation faults, and floating point exceptions*/
3559 sigaction(SIGBUS,&sig,0);
3560 sigaction(SIGSEGV,&sig,0);
3561 sigaction(SIGFPE,&sig,0);
3562 sigaction(SIGPIPE,&sig,0);
3571 fdtoobject=allocateRuntimeHash(100);
3575 /* Map first block of memory to protected, anonymous page */
3576 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
3580 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
3584 raw_test_pass(0xe992);
3587 /* Check if any filedescriptors have IO pending */
3590 struct timeval timeout={0,0};
3594 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
3596 /* Process ready fd's */
3598 for(fd=0; fd<maxreadfd; fd++) {
3599 if (FD_ISSET(fd, &tmpreadfds)) {
3600 /* Set ready flag on object */
3602 // printf("Setting fd %d\n",fd);
3603 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
3604 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
3605 enqueueObject(objptr, NULL, 0);
3614 /* See if there are any active tasks */
3615 if (hashsize(activetasks)>0) {
3618 if(!taskInfoOverflow) {
3619 TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
3620 taskInfoArray[taskInfoIndex] = checkTaskInfo;
3621 checkTaskInfo->taskName = "tpd checking";
3622 checkTaskInfo->startTime = raw_get_cycle();
3623 checkTaskInfo->endTime = -1;
3624 checkTaskInfo->exitIndex = -1;
3625 checkTaskInfo->newObjs = NULL;
3628 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
3629 genfreekey(activetasks, currtpd);
3631 numparams=currtpd->task->numParameters;
3632 numtotal=currtpd->task->numTotal;
3634 #ifdef THREADSIMULATE
3635 int isolateflags[numparams];
3637 /* Make sure that the parameters are still in the queues */
3638 for(i=0; i<numparams; i++) {
3639 void * parameter=currtpd->parameterArray[i];
3644 raw_test_pass(0xe993);
3647 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3649 taskpointerarray[i+OFFSET]=parameter;
3653 // require locks for this parameter if it is not a startup object
3654 if(((struct ___Object___ *)parameter)->numlocks == 0) {
3658 numlocks = ((struct ___Object___ *)parameter)->numlocks;
3659 locks = ((struct ___Object___ *)parameter)->locks;
3663 for(; numlocks > 0; numlocks--) {
3664 getwritelock(locks);
3667 raw_user_interrupts_off();
3670 //isInterrupt = false;
3677 while(receiveObject() != -1) {
3681 grount = grount || lockresult;
3690 //isInterrupt = true;
3693 raw_user_interrupts_on();
3699 locks = (int *)(*locks);
3705 raw_test_pass(0xe994);
3707 // can not get the lock, try later
3708 // first release all grabbed locks for this parameter
3709 numlocks = ((struct ___Object___ *)parameter)->numlocks - numlocks;
3710 locks = ((struct ___Object___ *)parameter)->locks;
3711 for(; numlocks > 0; numlocks--) {
3712 releasewritelock(locks);
3713 locks = (int *)(*locks);
3715 // then releas all grabbed locks for previous parameters
3716 for(j = 0; j < i; ++j) {
3717 if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
3718 locks = taskpointerarray[j+OFFSET];
3721 locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
3722 numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
3724 for(; numlocks > 0; numlocks--) {
3725 releasewritelock(locks);
3726 locks = (int *)(*locks);
3729 genputtable(activetasks, currtpd, currtpd);
3730 if(hashsize(activetasks) == 1) {
3731 // only one task right now, wait a little while before next try
3737 // fail, set the end of the checkTaskInfo
3738 if(!taskInfoOverflow) {
3739 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3741 if(taskInfoIndex == TASKINFOLENGTH) {
3742 taskInfoOverflow = true;
3750 raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
3753 tmpparam = (struct ___Object___ *)parameter;
3754 #ifdef THREADSIMULATE
3755 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3757 taskpointerarray[i+OFFSET]=parameter;
3761 if(0 == tmpparam->isolate) {
3762 isolateflags[i] = 0;
3763 // shared object, need to flush with current value
3764 // TODO: need modification according to added alias locks
3765 if(!getwritelock(tmpparam->original)) {
3766 // fail to get write lock, release all obtained locks and try this task later
3768 for(j = 0; j < i; ++j) {
3769 if(0 == isolateflags[j]) {
3770 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3773 genputtable(activetasks, currtpd, currtpd);
3776 if(tmpparam->version != tmpparam->original->version) {
3777 // release all obtained locks
3779 for(j = 0; j < i; ++j) {
3780 if(0 == isolateflags[j]) {
3781 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3784 releasewritelock(tmpparam->original);
3786 // dequeue this object
3787 int numofcore = pthread_getspecific(key);
3788 struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
3789 int length = numqueues[numofcore][tmpparam->type];
3790 for(j = 0; j < length; ++j) {
3791 struct parameterwrapper * pw = queues[j];
3792 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
3794 int UNUSED, UNUSED2;
3796 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3797 ObjectHashremove(pw->objectset, (int)tmpparam);
3798 if (enterflags!=NULL)
3802 // Free up task parameter descriptor
3803 RUNFREE(currtpd->parameterArray);
3808 isolateflags[i] = 1;
3811 pd=currtpd->task->descriptorarray[i];
3812 pw=(struct parameterwrapper *) pd->queue;
3813 /* Check that object is still in queue */
3815 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
3817 raw_test_pass(0xe995);
3819 // release grabbed locks
3820 for(j = 0; j < i; ++j) {
3821 if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
3823 locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
3825 numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
3826 locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
3828 for(; numlocks > 0; numlocks--) {
3829 releasewritelock(locks);
3830 locks = (int *)(*locks);
3833 if(((struct ___Object___ *)parameter)->numlocks == 0) {
3837 numlocks = ((struct ___Object___ *)parameter)->numlocks;
3838 locks = ((struct ___Object___ *)parameter)->locks;
3840 for(; numlocks > 0; numlocks--) {
3841 releasewritelock(locks);
3842 locks = (int *)(*locks);
3844 RUNFREE(currtpd->parameterArray);
3850 /* Check if the object's flags still meets requirements */
3854 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
3855 andmask=pw->intarray[tmpi*2];
3856 checkmask=pw->intarray[tmpi*2+1];
3858 raw_test_pass(0xdd000000 + andmask);
3859 raw_test_pass_reg((int)parameter);
3860 raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
3861 raw_test_pass(0xdd000000 + checkmask);
3863 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
3869 // flags are never suitable
3870 // remove this obj from the queue
3872 int UNUSED, UNUSED2;
3875 raw_test_pass(0xe996);
3877 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3878 ObjectHashremove(pw->objectset, (int)parameter);
3879 if (enterflags!=NULL)
3881 // release grabbed locks
3882 for(j = 0; j < i; ++j) {
3883 if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
3885 locks = taskpointerarray[j+OFFSET];
3887 numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
3888 locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
3890 for(; numlocks > 0; numlocks--) {
3891 releasewritelock(locks);
3892 locks = (int *)(*locks);
3895 if(((struct ___Object___ *)parameter)->numlocks == 0) {
3899 numlocks = ((struct ___Object___ *)parameter)->numlocks;
3900 locks = ((struct ___Object___ *)parameter)->locks;
3902 for(; numlocks > 0; numlocks--) {
3903 releasewritelock(locks);
3904 locks = (int *)(*locks);
3906 RUNFREE(currtpd->parameterArray);
3909 // fail, set the end of the checkTaskInfo
3910 if(!taskInfoOverflow) {
3911 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3913 if(taskInfoIndex == TASKINFOLENGTH) {
3914 taskInfoOverflow = true;
3924 /* Check that object still has necessary tags */
3925 for(j=0; j<pd->numbertags; j++) {
3926 int slotid=pd->tagarray[2*j]+numparams;
3927 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
3928 if (!containstag(parameter, tagd)) {
3930 raw_test_pass(0xe997);
3932 RUNFREE(currtpd->parameterArray);
3938 taskpointerarray[i+OFFSET]=parameter;
3941 for(; i<numtotal; i++) {
3942 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
3945 #ifdef THREADSIMULATE
3946 for(i = 0; i < numparams; ++i) {
3947 if(0 == isolateflags[i]) {
3948 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3949 if(tmpparam != tmpparam->original) {
3950 taskpointerarray[i+OFFSET] = tmpparam->original;
3959 /* Checkpoint the state */
3960 forward=allocateRuntimeHash(100);
3961 reverse=allocateRuntimeHash(100);
3962 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
3965 if (x=setjmp(error_handler)) {
3970 printf("Fatal Error=%d, Recovering!\n",x);
3974 genputtable(failedtasks,currtpd,currtpd);
3975 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
3977 freeRuntimeHash(forward);
3978 freeRuntimeHash(reverse);
3986 raw_test_pass_reg(x);
3988 raw_test_done(0xa009);
3993 /*if (injectfailures) {
3994 if ((((double)random())/RAND_MAX)<failurechance) {
3995 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
3996 longjmp(error_handler,10);
3999 /* Actually call task */
4001 ((int *)taskpointerarray)[0]=currtpd->numParameters;
4002 taskpointerarray[1]=NULL;
4007 // check finish, set the end of the checkTaskInfo
4008 if(!taskInfoOverflow) {
4009 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4011 if(taskInfoIndex == TASKINFOLENGTH) {
4012 taskInfoOverflow = true;
4016 if(!taskInfoOverflow) {
4017 // new a taskInfo for the task execution
4018 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
4019 taskInfoArray[taskInfoIndex] = taskInfo;
4020 taskInfo->taskName = currtpd->task->name;
4021 taskInfo->startTime = raw_get_cycle();
4022 taskInfo->endTime = -1;
4023 taskInfo->exitIndex = -1;
4024 taskInfo->newObjs = NULL;
4030 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
4032 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
4034 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
4037 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
4040 // task finish, set the end of the checkTaskInfo
4041 if(!taskInfoOverflow) {
4042 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4044 if(taskInfoIndex == TASKINFOLENGTH) {
4045 taskInfoOverflow = true;
4048 // new a PostTaskInfo for the post-task execution
4049 if(!taskInfoOverflow) {
4050 TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
4051 taskInfoArray[taskInfoIndex] = postTaskInfo;
4052 postTaskInfo->taskName = "post task execution";
4053 postTaskInfo->startTime = raw_get_cycle();
4054 postTaskInfo->endTime = -1;
4055 postTaskInfo->exitIndex = -1;
4056 postTaskInfo->newObjs = NULL;
4060 raw_test_pass(0xe998);
4061 raw_test_pass_reg(lock);
4066 for(i = 0; i < numparams; ++i) {
4068 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
4072 raw_test_pass(0xe999);
4073 raw_test_pass(0xdd100000 + tmpparam->flag);
4075 if(tmpparam->numlocks == 0) {
4077 locks = (int*)tmpparam;
4079 numlocks = tmpparam->numlocks;
4080 locks = tmpparam->locks;
4082 for(; numlocks > 0; numlocks--) {
4083 releasewritelock(locks);
4084 locks = (int *)(*locks);
4087 #elif defined THREADSIMULATE
4088 for(i = 0; i < numparams; ++i) {
4089 if(0 == isolateflags[i]) {
4090 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
4091 if(tmpparam->numlocks == 0) {
4093 locks = (int*)tmpparam;
4095 numlocks = tmpparam->numlocks;
4096 locks = tmpparam->locks;
4098 for(; numlocks > 0; numlocks--) {
4099 releasewritelock(locks);
4100 locks = (int *)(*locks);
4108 // post task execution finish, set the end of the postTaskInfo
4109 if(!taskInfoOverflow) {
4110 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4112 if(taskInfoIndex == TASKINFOLENGTH) {
4113 taskInfoOverflow = true;
4120 freeRuntimeHash(forward);
4121 freeRuntimeHash(reverse);
4125 // Free up task parameter descriptor
4126 RUNFREE(currtpd->parameterArray);
4135 raw_test_pass(0xe99a);
4138 raw_test_pass(0xe99a);
4146 raw_test_pass(0xe999);
4150 /* This function processes an objects tags */
4151 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
4154 for(i=0; i<pd->numbertags; i++) {
4155 int slotid=pd->tagarray[2*i];
4156 int tagid=pd->tagarray[2*i+1];
4158 if (statusarray[slotid+numparams]==0) {
4159 parameter->iterators[*iteratorcount].istag=1;
4160 parameter->iterators[*iteratorcount].tagid=tagid;
4161 parameter->iterators[*iteratorcount].slot=slotid+numparams;
4162 parameter->iterators[*iteratorcount].tagobjectslot=index;
4163 statusarray[slotid+numparams]=1;
4170 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
4173 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
4175 parameter->iterators[*iteratorcount].istag=0;
4176 parameter->iterators[*iteratorcount].slot=index;
4177 parameter->iterators[*iteratorcount].objectset=objectset;
4178 statusarray[index]=1;
4180 for(i=0; i<pd->numbertags; i++) {
4181 int slotid=pd->tagarray[2*i];
4182 int tagid=pd->tagarray[2*i+1];
4183 if (statusarray[slotid+numparams]!=0) {
4184 /* This tag has already been enqueued, use it to narrow search */
4185 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
4189 parameter->iterators[*iteratorcount].numtags=tagcount;
4194 /* This function builds the iterators for a task & parameter */
4196 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
4197 int statusarray[MAXTASKPARAMS];
4199 int numparams=task->numParameters;
4200 int iteratorcount=0;
4201 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
4203 statusarray[index]=1; /* Initial parameter */
4204 /* Process tags for initial iterator */
4206 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
4210 /* Check for objects with existing tags */
4211 for(i=0; i<numparams; i++) {
4212 if (statusarray[i]==0) {
4213 struct parameterdescriptor *pd=task->descriptorarray[i];
4215 for(j=0; j<pd->numbertags; j++) {
4216 int slotid=pd->tagarray[2*j];
4217 if(statusarray[slotid+numparams]!=0) {
4218 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4219 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4226 /* Next do objects w/ unbound tags*/
4228 for(i=0; i<numparams; i++) {
4229 if (statusarray[i]==0) {
4230 struct parameterdescriptor *pd=task->descriptorarray[i];
4231 if (pd->numbertags>0) {
4232 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4233 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4239 /* Nothing with a tag enqueued */
4241 for(i=0; i<numparams; i++) {
4242 if (statusarray[i]==0) {
4243 struct parameterdescriptor *pd=task->descriptorarray[i];
4244 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4245 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4258 #ifdef THREADSIMULATE
4259 int numofcore = pthread_getspecific(key);
4260 for(i=0; i<numtasks[numofcore]; i++) {
4261 struct taskdescriptor * task=taskarray[numofcore][i];
4264 if(corenum > NUMCORES - 1) {
4268 for(i=0; i<numtasks[corenum]; i++) {
4269 struct taskdescriptor * task=taskarray[corenum][i];
4272 printf("%s\n", task->name);
4274 for(j=0; j<task->numParameters; j++) {
4275 struct parameterdescriptor *param=task->descriptorarray[j];
4276 struct parameterwrapper *parameter=param->queue;
4277 struct ObjectHash * set=parameter->objectset;
4278 struct ObjectIterator objit;
4280 printf(" Parameter %d\n", j);
4282 ObjectHashiterator(set, &objit);
4283 while(ObjhasNext(&objit)) {
4284 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
4285 struct ___Object___ * tagptr=obj->___tags___;
4286 int nonfailed=Objdata4(&objit);
4287 int numflags=Objdata3(&objit);
4288 int flags=Objdata2(&objit);
4291 printf(" Contains %lx\n", obj);
4292 printf(" flag=%d\n", obj->flag);
4295 } else if (tagptr->type==TAGTYPE) {
4297 printf(" tag=%lx\n",tagptr);
4302 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
4303 for(; tagindex<ao->___cachedCode___; tagindex++) {
4305 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
4315 /* This function processes the task information to create queues for
4316 each parameter type. */
4318 void processtasks() {
4321 if(corenum > NUMCORES - 1) {
4325 #ifdef THREADSIMULATE
4326 int numofcore = pthread_getspecific(key);
4327 for(i=0; i<numtasks[numofcore]; i++) {
4328 struct taskdescriptor *task=taskarray[numofcore][i];
4330 for(i=0; i<numtasks[corenum]; i++) {
4331 struct taskdescriptor * task=taskarray[corenum][i];
4335 /* Build objectsets */
4336 for(j=0; j<task->numParameters; j++) {
4337 struct parameterdescriptor *param=task->descriptorarray[j];
4338 struct parameterwrapper *parameter=param->queue;
4339 parameter->objectset=allocateObjectHash(10);
4340 parameter->task=task;
4343 /* Build iterators for parameters */
4344 for(j=0; j<task->numParameters; j++) {
4345 struct parameterdescriptor *param=task->descriptorarray[j];
4346 struct parameterwrapper *parameter=param->queue;
4347 builditerators(task, j, parameter);
4352 void toiReset(struct tagobjectiterator * it) {
4355 } else if (it->numtags>0) {
4358 ObjectHashiterator(it->objectset, &it->it);
4362 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4365 /* Get object with tags */
4366 struct ___Object___ *obj=objectarray[it->tagobjectslot];
4367 struct ___Object___ *tagptr=obj->___tags___;
4368 if (tagptr->type==TAGTYPE) {
4369 if ((it->tagobjindex==0)&& /* First object */
4370 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
4375 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4376 int tagindex=it->tagobjindex;
4377 for(; tagindex<ao->___cachedCode___; tagindex++) {
4378 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
4379 if (td->flag==it->tagid) {
4380 it->tagobjindex=tagindex; /* Found right type of tag */
4386 } else if (it->numtags>0) {
4387 /* Use tags to locate appropriate objects */
4388 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4389 struct ___Object___ *objptr=tag->flagptr;
4391 if (objptr->type!=OBJECTARRAYTYPE) {
4392 if (it->tagobjindex>0)
4394 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4396 for(i=1; i<it->numtags; i++) {
4397 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4398 if (!containstag(objptr,tag2))
4403 struct ArrayObject *ao=(struct ArrayObject *) objptr;
4406 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
4407 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
4408 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4410 for(i=1; i<it->numtags; i++) {
4411 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4412 if (!containstag(objptr,tag2))
4415 it->tagobjindex=tagindex;
4420 it->tagobjindex=tagindex;
4424 return ObjhasNext(&it->it);
4428 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
4430 struct ___Object___ * objptr=tag->flagptr;
4431 if (objptr->type==OBJECTARRAYTYPE) {
4432 struct ArrayObject *ao=(struct ArrayObject *)objptr;
4433 for(j=0; j<ao->___cachedCode___; j++) {
4434 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
4442 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4443 /* hasNext has all of the intelligence */
4446 /* Get object with tags */
4447 struct ___Object___ *obj=objectarray[it->tagobjectslot];
4448 struct ___Object___ *tagptr=obj->___tags___;
4449 if (tagptr->type==TAGTYPE) {
4451 objectarray[it->slot]=tagptr;
4453 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4454 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
4456 } else if (it->numtags>0) {
4457 /* Use tags to locate appropriate objects */
4458 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4459 struct ___Object___ *objptr=tag->flagptr;
4460 if (objptr->type!=OBJECTARRAYTYPE) {
4462 objectarray[it->slot]=objptr;
4464 struct ArrayObject *ao=(struct ArrayObject *) objptr;
4465 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
4468 /* Iterate object */
4469 objectarray[it->slot]=(void *)Objkey(&it->it);