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 150
121 //#define INTERRUPTINFOLENGTH 500
127 typedef struct task_info {
133 /*typedef struct interrupt_info {
138 TaskInfo * taskInfoArray[TASKINFOLENGTH];
140 bool taskInfoOverflow;
141 /*InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
142 int interruptInfoIndex;
143 bool interruptInfoOverflow;*/
144 int profilestatus[NUMCORES]; // records status of each core
147 bool transProfileRequestMsg(int targetcore);
148 void outputProfileData();
159 int main(int argc, char **argv) {
165 bool sendStall = false;
167 bool tocontinue = false;
168 struct QueueItem * objitem = NULL;
169 struct transObjInfo * objInfo = NULL;
171 bool allStall = true;
175 raw_test_pass(0xee01);
177 corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
179 // initialize the arrays
180 if(STARTUPCORE == corenum) {
181 // startup core to initialize corestatus[]
182 for(i = 0; i < NUMCORES; ++i) {
184 numsendobjs[i] = 0; // assume all variables in RAW are local variables! MAY BE WRONG!!!
185 numreceiveobjs[i] = 0;
188 for(i = 0; i < NUMCORES; ++i) {
189 profilestatus[i] = 1;
193 self_numsendobjs = 0;
194 self_numreceiveobjs = 0;
195 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]);
325 //pthread_exit(NULL);
330 void run(void* arg) {
331 struct thread_data * my_tdata = (struct thread_data *)arg;
332 pthread_setspecific(key, (void *)my_tdata->corenum);
333 int argc = my_tdata->argc;
334 char** argv = my_tdata->argv;
335 printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
341 GC_init(); // Initialize the garbage collector
349 initializeexithandler();
351 raw_test_pass(0xee05);
353 /* Create table for failed tasks */
355 if(corenum > NUMCORES - 1) {
359 raw_test_pass(0xee01);
360 raw_test_pass_reg(taskInfoIndex);
361 raw_test_pass_reg(taskInfoOverflow);
362 if(!taskInfoOverflow) {
363 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
364 taskInfoArray[taskInfoIndex] = taskInfo;
365 taskInfo->taskName = "msg handling";
366 taskInfo->startTime = raw_get_cycle();
367 taskInfo->endTime = -1;
371 //isInterrupt = false;
378 raw_test_pass(0xee06);
381 /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
382 (int (*)(void *,void *)) &comparetpd);*/
385 raw_test_pass(0xee07);
387 /* Create queue of active tasks */
388 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
389 (int(*) (void *,void *)) &comparetpd);
391 raw_test_pass(0xee08);
394 /* Process task information */
397 raw_test_pass(0xee09);
400 if(STARTUPCORE == corenum) {
401 /* Create startup object */
402 createstartupobject(argc, argv);
405 raw_test_pass(0xee0a);
410 raw_test_pass(0xee0b);
415 while(receiveObject() != -1) {
419 // check if there are new active tasks can be executed
423 while(receiveObject() != -1) {
428 raw_test_pass(0xee0c);
431 // check if there are some pending objects, if yes, enqueue them and executetasks again
434 raw_test_pass(0xee0d);
438 bool isChecking = false;
439 if(!isEmpty(&objqueue)) {
440 if(!taskInfoOverflow) {
441 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
442 taskInfoArray[taskInfoIndex] = taskInfo;
443 taskInfo->taskName = "objqueue checking";
444 taskInfo->startTime = raw_get_cycle();
445 taskInfo->endTime = -1;
450 while(!isEmpty(&objqueue)) {
453 raw_user_interrupts_off();
456 //isInterrupt = false;
459 raw_test_pass(0xeee1);
463 objitem = getTail(&objqueue);
464 //obj = objitem->objectptr;
465 objInfo = (struct transObjInfo *)objitem->objectptr;
466 obj = objInfo->objptr;
468 raw_test_pass_reg((int)obj);
470 // grab lock and flush the obj
477 raw_test_pass_reg(grount);
489 raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
491 /*for(k = 0; k < classsize[((struct ___Object___ *)obj)->type]; ++k) {
492 invalidateAddr(obj + k);
494 // enqueue the object
495 for(k = 0; k < objInfo->length; ++k) {
496 int taskindex = objInfo->queues[2 * k];
497 int paramindex = objInfo->queues[2 * k + 1];
498 struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
500 raw_test_pass_reg(taskindex);
501 raw_test_pass_reg(paramindex);
503 enqueueObject_I(obj, queues, 1);
505 removeItem(&objqueue, objitem);
506 releasereadlock_I(obj);
507 RUNFREE(objInfo->queues);
509 /*enqueueObject_I(obj, NULL, 0);
510 removeItem(&objqueue, objitem);
511 releasereadlock_I(obj);*/
514 // put it at the end of the queue
515 // and try to execute active tasks already enqueued first
516 removeItem(&objqueue, objitem);
517 addNewItem_I(&objqueue, objInfo);
519 //isInterrupt = true;
522 raw_user_interrupts_on();
527 raw_user_interrupts_on();
530 raw_test_pass(0xee0e);
534 if(isChecking && (!taskInfoOverflow)) {
535 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
537 if(taskInfoIndex == TASKINFOLENGTH) {
538 taskInfoOverflow = true;
544 raw_test_pass(0xee0f);
549 if(STARTUPCORE == corenum) {
552 raw_test_pass(0xee10);
557 raw_user_interrupts_off();
559 corestatus[corenum] = 0;
560 numsendobjs[corenum] = self_numsendobjs;
561 numreceiveobjs[corenum] = self_numreceiveobjs;
562 // check the status of all cores
565 raw_test_pass_reg(NUMCORES);
567 for(i = 0; i < NUMCORES; ++i) {
569 raw_test_pass(0xe000 + corestatus[i]);
571 if(corestatus[i] != 0) {
577 // check if the sum of send objs and receive obj are the same
578 // yes->terminate; for profiling mode, yes->send request to all
579 // other cores to pour out profiling data
580 // no->go on executing
582 for(i = 0; i < NUMCORES; ++i) {
583 sumsendobj += numsendobjs[i];
585 raw_test_pass(0xf000 + numsendobjs[i]);
588 for(i = 0; i < NUMCORES; ++i) {
589 sumsendobj -= numreceiveobjs[i];
591 raw_test_pass(0xf000 + numreceiveobjs[i]);
594 if(0 == sumsendobj) {
597 raw_test_pass(0xee11);
601 totalexetime = raw_get_cycle();
603 raw_test_pass(0xbbbbbbbb);
604 raw_test_pass(raw_get_cycle());
607 // profile mode, send msgs to other cores to request pouring
608 // out progiling data
611 // reopen gdn_avail interrupts
612 raw_user_interrupts_on();
614 for(i = 1; i < NUMCORES; ++i) {
615 transProfileRequestMsg(i);
617 // pour profiling data on startup core
621 raw_user_interrupts_off();
623 profilestatus[corenum] = 0;
624 // check the status of all cores
627 raw_test_pass_reg(NUMCORES);
629 for(i = 0; i < NUMCORES; ++i) {
631 raw_test_pass(0xe000 + profilestatus[i]);
633 if(profilestatus[i] != 0) {
641 raw_user_interrupts_on();
651 raw_test_done(1); // All done.
655 raw_user_interrupts_on();
660 raw_test_pass(0xee12);
666 // wait for some time
669 raw_test_pass(0xee13);
675 raw_test_pass(0xee14);
678 // send StallMsg to startup core
680 raw_test_pass(0xee15);
682 sendStall = transStallMsg(STARTUPCORE);
691 raw_test_pass(0xee16);
698 #elif defined THREADSIMULATE
699 /* Start executing the tasks */
703 // check if there are new objects coming
704 bool sendStall = false;
706 int numofcore = pthread_getspecific(key);
708 switch(receiveObject()) {
710 printf("[run, %d] receive an object\n", numofcore);
712 // received an object
713 // check if there are new active tasks can be executed
719 //printf("[run, %d] no msg\n", numofcore);
721 if(STARTUPCORE == numofcore) {
722 corestatus[numofcore] = 0;
723 // check the status of all cores
724 bool allStall = true;
725 for(i = 0; i < NUMCORES; ++i) {
726 if(corestatus[i] != 0) {
732 // check if the sum of send objs and receive obj are the same
734 // no->go on executing
736 for(i = 0; i < NUMCORES; ++i) {
737 sumsendobj += numsendobjs[i];
739 for(i = 0; i < NUMCORES; ++i) {
740 sumsendobj -= numreceiveobjs[i];
742 if(0 == sumsendobj) {
746 int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
747 printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
748 struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
749 while(0 != RunhasNext(it_lock)) {
750 int key = Runkey(it_lock);
751 pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
752 int rc_des = pthread_rwlock_destroy(rwlock_obj);
753 printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
756 freeRuntimeHash(locktbl);
760 // destroy all message queues
761 char * pathhead = "/msgqueue_";
762 int targetlen = strlen(pathhead);
763 for(i = 0; i < NUMCORES; ++i) {
767 corenumstr[0] = i + '0';
768 corenumstr[1] = '\0';
771 corenumstr[1] = i %10 + '0';
772 corenumstr[0] = (i / 10) + '0';
773 corenumstr[2] = '\0';
776 printf("Error: i >= 100\n");
780 char path[targetlen + sourcelen + 1];
781 strcpy(path, pathhead);
782 strncat(path, corenumstr, sourcelen);
786 printf("[run, %d] terminate!\n", numofcore);
793 // send StallMsg to startup core
794 sendStall = transStallMsg(STARTUPCORE);
801 printf("[run, %d] receive a stall msg\n", numofcore);
802 // receive a Stall Msg, do nothing
803 assert(STARTUPCORE == numofcore); // only startup core can receive such msg
809 printf("[run, %d] receive a terminate msg\n", numofcore);
810 // receive a terminate Msg
811 assert(STARTUPCORE != corenum); // only non-startup core can receive such msg
812 mq_close(mqd[corenum]);
818 printf("[run, %d] Error: invalid message type.\n", numofcore);
828 void createstartupobject(int argc, char ** argv) {
831 /* Allocate startup object */
833 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
834 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
836 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
837 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
839 /* Build array of strings */
840 startupobject->___parameters___=stringarray;
841 for(i=1; i<argc; i++) {
842 int length=strlen(argv[i]);
844 struct ___String___ *newstring=NewString(NULL, argv[i],length);
846 struct ___String___ *newstring=NewString(argv[i],length);
848 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
851 startupobject->isolate = 1;
852 startupobject->version = 0;
854 /* Set initialized flag for startup object */
855 flagorandinit(startupobject,1,0xFFFFFFFF);
856 enqueueObject(startupobject, NULL, 0);
859 raw_flush_entire_cache();
863 int hashCodetpd(struct taskparamdescriptor *ftd) {
864 int hash=(int)ftd->task;
866 for(i=0; i<ftd->numParameters; i++) {
867 hash^=(int)ftd->parameterArray[i];
872 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
874 if (ftd1->task!=ftd2->task)
876 for(i=0; i<ftd1->numParameters; i++)
877 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
882 /* This function sets a tag. */
884 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
886 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
888 struct ArrayObject * ao=NULL;
889 struct ___Object___ * tagptr=obj->___tags___;
891 raw_test_pass(0xebb0);
895 raw_test_pass(0xebb1);
897 obj->___tags___=(struct ___Object___ *)tagd;
899 /* Have to check if it is already set */
900 if (tagptr->type==TAGTYPE) {
901 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
903 raw_test_pass(0xebb2);
907 raw_test_pass(0xebb3);
912 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
913 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
914 obj=(struct ___Object___ *)ptrarray[2];
915 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
916 td=(struct ___TagDescriptor___ *) obj->___tags___;
919 raw_test_pass(0xebb4);
921 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
924 raw_test_pass(0xebb5);
926 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
927 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
928 obj->___tags___=(struct ___Object___ *) ao;
929 ao->___cachedCode___=2;
931 raw_test_pass(0xebb6);
936 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
938 raw_test_pass(0xebb7);
940 for(i=0; i<ao->___cachedCode___; i++) {
941 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
943 raw_test_pass(0xebb8);
947 raw_test_pass(0xebb9);
952 if (ao->___cachedCode___<ao->___length___) {
954 raw_test_pass(0xebba);
956 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
957 ao->___cachedCode___++;
959 raw_test_pass(0xebbb);
963 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
964 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
965 obj=(struct ___Object___ *)ptrarray[2];
966 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
967 ao=(struct ArrayObject *)obj->___tags___;
969 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
972 raw_test_pass(0xebbc);
974 aonew->___cachedCode___=ao->___length___+1;
975 for(i=0; i<ao->___length___; i++) {
977 raw_test_pass(0xebbd);
979 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
982 raw_test_pass(0xebbe);
984 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
986 raw_test_pass(0xebbf);
993 struct ___Object___ * tagset=tagd->flagptr;
995 raw_test_pass(0xb008);
999 raw_test_pass(0xb009);
1002 } else if (tagset->type!=OBJECTARRAYTYPE) {
1004 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1005 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1006 obj=(struct ___Object___ *)ptrarray[2];
1007 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1009 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1011 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
1012 ARRAYSET(ao, struct ___Object___ *, 1, obj);
1013 ao->___cachedCode___=2;
1014 tagd->flagptr=(struct ___Object___ *)ao;
1016 raw_test_pass(0xb00a);
1019 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1020 if (ao->___cachedCode___<ao->___length___) {
1022 raw_test_pass(0xb00b);
1024 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
1028 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1029 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
1030 obj=(struct ___Object___ *)ptrarray[2];
1031 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1032 ao=(struct ArrayObject *)tagd->flagptr;
1034 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1036 aonew->___cachedCode___=ao->___cachedCode___+1;
1037 for(i=0; i<ao->___length___; i++) {
1038 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
1040 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
1041 tagd->flagptr=(struct ___Object___ *) aonew;
1043 raw_test_pass(0xb00c);
1050 /* This function clears a tag. */
1052 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1054 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1056 /* We'll assume that tag is alway there.
1057 Need to statically check for this of course. */
1058 struct ___Object___ * tagptr=obj->___tags___;
1060 if (tagptr->type==TAGTYPE) {
1061 if ((struct ___TagDescriptor___ *)tagptr==tagd)
1062 obj->___tags___=NULL;
1065 printf("ERROR 1 in tagclear\n");
1069 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1071 for(i=0; i<ao->___cachedCode___; i++) {
1072 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
1074 ao->___cachedCode___--;
1075 if (i<ao->___cachedCode___)
1076 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
1077 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
1078 if (ao->___cachedCode___==0)
1079 obj->___tags___=NULL;
1084 printf("ERROR 2 in tagclear\n");
1090 struct ___Object___ *tagset=tagd->flagptr;
1091 if (tagset->type!=OBJECTARRAYTYPE) {
1096 printf("ERROR 3 in tagclear\n");
1100 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1102 for(i=0; i<ao->___cachedCode___; i++) {
1103 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
1105 ao->___cachedCode___--;
1106 if (i<ao->___cachedCode___)
1107 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
1108 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
1109 if (ao->___cachedCode___==0)
1115 printf("ERROR 4 in tagclear\n");
1123 /* This function allocates a new tag. */
1125 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
1126 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
1128 struct ___TagDescriptor___ * allocate_tag(int index) {
1129 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
1138 /* This function updates the flag for object ptr. It or's the flag
1139 with the or mask and and's it with the andmask. */
1141 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
1143 int flagcomp(const int *val1, const int *val2) {
1144 return (*val1)-(*val2);
1147 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
1149 int oldflag=((int *)ptr)[1];
1150 int flag=ormask|oldflag;
1153 raw_test_pass_reg((int)ptr);
1154 raw_test_pass(0xaa000000 + oldflag);
1155 raw_test_pass(0xaa000000 + flag);
1157 flagbody(ptr, flag, queues, length, false);
1161 bool intflagorand(void * ptr, int ormask, int andmask) {
1163 int oldflag=((int *)ptr)[1];
1164 int flag=ormask|oldflag;
1166 if (flag==oldflag) /* Don't do anything */
1169 flagbody(ptr, flag, NULL, 0, false);
1175 void flagorandinit(void * ptr, int ormask, int andmask) {
1176 int oldflag=((int *)ptr)[1];
1177 int flag=ormask|oldflag;
1180 raw_test_pass(0xaa100000 + oldflag);
1181 raw_test_pass(0xaa100000 + flag);
1183 flagbody(ptr,flag,NULL,0,true);
1186 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1187 struct parameterwrapper * flagptr = NULL;
1189 struct parameterwrapper ** queues = vqueues;
1190 int length = vlength;
1192 int UNUSED, UNUSED2;
1193 int * enterflags = NULL;
1194 if((!isnew) && (queues == NULL)) {
1195 #ifdef THREADSIMULATE
1196 int numofcore = pthread_getspecific(key);
1197 queues = objectqueues[numofcore][ptr->type];
1198 length = numqueues[numofcore][ptr->type];
1201 if(corenum < NUMCORES) {
1203 queues = objectqueues[corenum][ptr->type];
1204 length = numqueues[corenum][ptr->type];
1214 raw_test_pass(0xbb000000 + ptr->flag);
1217 /*Remove object from all queues */
1218 for(i = 0; i < length; ++i) {
1219 flagptr = queues[i];
1220 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1221 ObjectHashremove(flagptr->objectset, (int)ptr);
1222 if (enterflags!=NULL)
1223 RUNFREE(enterflags);
1227 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1228 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1231 struct QueueItem *tmpptr;
1232 struct parameterwrapper * parameter=NULL;
1235 struct parameterwrapper * prevptr=NULL;
1236 struct ___Object___ *tagptr=NULL;
1237 struct parameterwrapper ** queues = vqueues;
1238 int length = vlength;
1240 if(corenum > NUMCORES - 1) {
1244 if(queues == NULL) {
1245 #ifdef THREADSIMULATE
1246 int numofcore = pthread_getspecific(key);
1247 queues = objectqueues[numofcore][ptr->type];
1248 length = numqueues[numofcore][ptr->type];
1250 queues = objectqueues[corenum][ptr->type];
1251 length = numqueues[corenum][ptr->type];
1254 tagptr=ptr->___tags___;
1256 /* Outer loop iterates through all parameter queues an object of
1257 this type could be in. */
1258 for(j = 0; j < length; ++j) {
1259 parameter = queues[j];
1261 if (parameter->numbertags>0) {
1263 goto nextloop; //that means the object has no tag but that param needs tag
1264 else if(tagptr->type==TAGTYPE) { //one tag
1265 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1266 for(i=0; i<parameter->numbertags; i++) {
1267 //slotid is parameter->tagarray[2*i];
1268 int tagid=parameter->tagarray[2*i+1];
1269 if (tagid!=tagptr->flag)
1270 goto nextloop; /*We don't have this tag */
1272 } else { //multiple tags
1273 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1274 for(i=0; i<parameter->numbertags; i++) {
1275 //slotid is parameter->tagarray[2*i];
1276 int tagid=parameter->tagarray[2*i+1];
1278 for(j=0; j<ao->___cachedCode___; j++) {
1279 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1290 for(i=0; i<parameter->numberofterms; i++) {
1291 int andmask=parameter->intarray[i*2];
1292 int checkmask=parameter->intarray[i*2+1];
1293 if ((ptr->flag&andmask)==checkmask) {
1295 raw_test_pass(0xcc000000 + andmask);
1296 raw_test_pass_reg((int)ptr);
1297 raw_test_pass(0xcc000000 + ptr->flag);
1298 raw_test_pass(0xcc000000 + checkmask);
1300 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1312 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1313 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1316 struct QueueItem *tmpptr;
1317 struct parameterwrapper * parameter=NULL;
1320 struct parameterwrapper * prevptr=NULL;
1321 struct ___Object___ *tagptr=NULL;
1322 struct parameterwrapper ** queues = vqueues;
1323 int length = vlength;
1325 if(corenum > NUMCORES - 1) {
1329 if(queues == NULL) {
1330 #ifdef THREADSIMULATE
1331 int numofcore = pthread_getspecific(key);
1332 queues = objectqueues[numofcore][ptr->type];
1333 length = numqueues[numofcore][ptr->type];
1335 queues = objectqueues[corenum][ptr->type];
1336 length = numqueues[corenum][ptr->type];
1340 raw_test_pass(0xeaa1);
1341 raw_test_pass_reg(queues);
1342 raw_test_pass_reg(length);
1344 tagptr=ptr->___tags___;
1346 /* Outer loop iterates through all parameter queues an object of
1347 this type could be in. */
1348 for(j = 0; j < length; ++j) {
1349 parameter = queues[j];
1351 if (parameter->numbertags>0) {
1353 raw_test_pass(0xeaa2);
1354 raw_test_pass_reg(tagptr);
1357 goto nextloop; //that means the object has no tag but that param needs tag
1358 else if(tagptr->type==TAGTYPE) { //one tag
1359 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1361 raw_test_pass(0xeaa3);
1363 for(i=0; i<parameter->numbertags; i++) {
1364 //slotid is parameter->tagarray[2*i];
1365 int tagid=parameter->tagarray[2*i+1];
1366 if (tagid!=tagptr->flag) {
1368 raw_test_pass(0xeaa4);
1370 goto nextloop; /*We don't have this tag */
1373 } else { //multiple tags
1374 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1376 raw_test_pass(0xeaa5);
1378 for(i=0; i<parameter->numbertags; i++) {
1379 //slotid is parameter->tagarray[2*i];
1380 int tagid=parameter->tagarray[2*i+1];
1382 for(j=0; j<ao->___cachedCode___; j++) {
1383 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1388 raw_test_pass(0xeaa6);
1398 for(i=0; i<parameter->numberofterms; i++) {
1399 int andmask=parameter->intarray[i*2];
1400 int checkmask=parameter->intarray[i*2+1];
1402 raw_test_pass(0xeaa7);
1403 raw_test_pass(0xcc000000 + andmask);
1404 raw_test_pass_reg(ptr);
1405 raw_test_pass(0xcc000000 + ptr->flag);
1406 raw_test_pass(0xcc000000 + checkmask);
1408 if ((ptr->flag&andmask)==checkmask) {
1410 raw_test_pass(0xeaa8);
1412 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1423 // helper function to compute the coordinates of a core from the core number
1424 void calCoords(int core_num, int* coordY, int* coordX) {
1425 *coordX = core_num % 4;
1426 *coordY = core_num / 4;
1430 /* Message format for RAW version:
1432 * type: 0 -- transfer object
1433 * 1 -- transfer stall msg
1438 * 6 -- transfer profile output msg
1439 * 7 -- transfer profile ouput finish msg
1441 * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1442 * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1443 * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
1444 * 3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
1445 * lock type: 0 -- read; 1 -- write
1446 * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
1447 * 7 + corenum (size is always 2 * sizeof(int))
1450 // transfer an object to targetcore
1452 void transferObject(struct transObjInfo * transObj) {
1453 void * obj = transObj->objptr;
1454 int type=((int *)obj)[0];
1455 int size=classsize[type];
1456 int targetcore = transObj->targetcore;
1457 //assert(type < NUMCLASSES); // can only transfer normal object
1461 int self_y, self_x, target_y, target_x;
1463 // for 32 bit machine, the size of fixed part is always 3 words
1464 //int msgsize = sizeof(int) * 2 + sizeof(void *);
1465 int msgsize = 3 + transObj->length * 2;
1468 struct ___Object___ * newobj = (struct ___Object___ *)obj;
1469 /*if(0 == newobj->isolate) {
1473 calCoords(corenum, &self_y, &self_x);
1474 calCoords(targetcore, &target_y, &target_x);
1475 // Build the message header
1476 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1478 target_y, target_x);
1479 // start sending msg, set sand msg flag
1480 isMsgSending = true;
1481 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1483 raw_test_pass(0xbbbb);
1484 raw_test_pass(0xb000 + targetcore); // targetcore
1492 raw_test_pass_reg(msgsize);
1496 raw_test_pass_reg(obj);
1498 for(i = 0; i < transObj->length; ++i) {
1499 int taskindex = transObj->queues[2*i];
1500 int paramindex = transObj->queues[2*i+1];
1501 gdn_send(taskindex);
1503 raw_test_pass_reg(taskindex);
1505 gdn_send(paramindex);
1507 raw_test_pass_reg(paramindex);
1511 raw_test_pass(0xffff);
1513 ++(self_numsendobjs);
1514 // end of sending this msg, set sand msg flag false
1515 isMsgSending = false;
1516 // check if there are pending msgs
1517 while(isMsgHanging) {
1518 // get the msg from outmsgdata[]
1519 // length + target + msg
1520 outmsgleft = outmsgdata[outmsgindex++];
1521 targetcore = outmsgdata[outmsgindex++];
1522 calCoords(targetcore, &target_y, &target_x);
1523 // Build the message header
1524 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1526 target_y, target_x);
1527 isMsgSending = true;
1528 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1530 raw_test_pass(0xbbbb);
1531 raw_test_pass(0xb000 + targetcore); // targetcore
1533 while(outmsgleft-- > 0) {
1534 gdn_send(outmsgdata[outmsgindex++]);
1536 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1540 raw_test_pass(0xffff);
1542 isMsgSending = false;
1544 raw_user_interrupts_off();
1546 // check if there are still msg hanging
1547 if(outmsgindex == outmsglast) {
1549 outmsgindex = outmsglast = 0;
1550 isMsgHanging = false;
1553 raw_user_interrupts_on();
1556 #elif defined THREADSIMULATE
1557 int numofcore = pthread_getspecific(key);
1559 // use POSIX message queue to transfer objects between cores
1563 if(targetcore < 10) {
1564 corenumstr[0] = targetcore + '0';
1565 corenumstr[1] = '\0';
1567 } else if(targetcore < 100) {
1568 corenumstr[1] = targetcore % 10 + '0';
1569 corenumstr[0] = (targetcore / 10) + '0';
1570 corenumstr[2] = '\0';
1573 printf("Error: targetcore >= 100\n");
1577 char * pathhead = "/msgqueue_";
1578 int targetlen = strlen(pathhead);
1579 char path[targetlen + sourcelen + 1];
1580 strcpy(path, pathhead);
1581 strncat(path, corenumstr, sourcelen);
1582 int oflags = O_WRONLY|O_NONBLOCK;
1583 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1584 mqdnum = mq_open(path, oflags, omodes, NULL);
1586 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1590 /*struct ___Object___ * newobj = (struct ___Object___ *)obj;
1591 if(0 == newobj->isolate) {
1592 newobj = RUNMALLOC(size);
1593 memcpy(newobj, obj, size);
1594 newobj->original=obj;
1596 struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1597 memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1598 int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1599 memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1600 tmptransObj->queues = tmpqueue;
1601 struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1602 newobj->type = ((struct ___Object___ *)obj)->type;
1603 newobj->original = (struct ___Object___ *)tmptransObj;
1606 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1608 printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1612 if(numofcore == STARTUPCORE) {
1613 ++numsendobjs[numofcore];
1615 ++(thread_data_array[numofcore].numsendobjs);
1617 printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1621 // send terminate message to targetcore
1623 bool transStallMsg(int targetcore) {
1626 int self_y, self_x, target_y, target_x;
1627 // for 32 bit machine, the size is always 4 words
1628 //int msgsize = sizeof(int) * 4;
1631 calCoords(corenum, &self_y, &self_x);
1632 calCoords(targetcore, &target_y, &target_x);
1633 // Build the message header
1634 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1636 target_y, target_x);
1637 // start sending msgs, set msg sending flag
1638 isMsgSending = true;
1639 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1641 raw_test_pass(0xbbbb);
1642 raw_test_pass(0xb000 + targetcore); // targetcore
1650 raw_test_pass_reg(corenum);
1652 gdn_send(self_numsendobjs);
1654 raw_test_pass_reg(self_numsendobjs);
1656 gdn_send(self_numreceiveobjs);
1658 raw_test_pass_reg(self_numreceiveobjs);
1659 raw_test_pass(0xffff);
1661 // end of sending this msg, set sand msg flag false
1662 isMsgSending = false;
1663 // check if there are pending msgs
1664 while(isMsgHanging) {
1665 // get the msg from outmsgdata[]
1666 // length + target + msg
1667 outmsgleft = outmsgdata[outmsgindex++];
1668 targetcore = outmsgdata[outmsgindex++];
1669 calCoords(targetcore, &target_y, &target_x);
1670 // Build the message header
1671 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1673 target_y, target_x);
1674 isMsgSending = true;
1675 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1677 raw_test_pass(0xbbbb);
1678 raw_test_pass(0xb000 + targetcore); // targetcore
1680 while(outmsgleft-- > 0) {
1681 gdn_send(outmsgdata[outmsgindex++]);
1683 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1687 raw_test_pass(0xffff);
1689 isMsgSending = false;
1691 raw_user_interrupts_off();
1693 // check if there are still msg hanging
1694 if(outmsgindex == outmsglast) {
1696 outmsgindex = outmsglast = 0;
1697 isMsgHanging = false;
1700 raw_user_interrupts_on();
1704 #elif defined THREADSIMULATE
1705 struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1706 // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1708 int numofcore = pthread_getspecific(key);
1709 newobj->flag = numofcore;
1710 newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1711 newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1713 // use POSIX message queue to send stall msg to startup core
1714 assert(targetcore == STARTUPCORE);
1718 if(targetcore < 10) {
1719 corenumstr[0] = targetcore + '0';
1720 corenumstr[1] = '\0';
1722 } else if(targetcore < 100) {
1723 corenumstr[1] = targetcore % 10 + '0';
1724 corenumstr[0] = (targetcore / 10) + '0';
1725 corenumstr[2] = '\0';
1728 printf("Error: targetcore >= 100\n");
1732 char * pathhead = "/msgqueue_";
1733 int targetlen = strlen(pathhead);
1734 char path[targetlen + sourcelen + 1];
1735 strcpy(path, pathhead);
1736 strncat(path, corenumstr, sourcelen);
1737 int oflags = O_WRONLY|O_NONBLOCK;
1738 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1739 mqdnum = mq_open(path, oflags, omodes, NULL);
1741 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1746 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1748 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1752 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1753 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1761 // send profile request message to targetcore
1763 bool transProfileRequestMsg(int targetcore) {
1765 int self_y, self_x, target_y, target_x;
1766 // for 32 bit machine, the size is always 4 words
1767 //int msgsize = sizeof(int) * 4;
1770 calCoords(corenum, &self_y, &self_x);
1771 calCoords(targetcore, &target_y, &target_x);
1772 // Build the message header
1773 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1775 target_y, target_x);
1776 // start sending msgs, set msg sending flag
1777 isMsgSending = true;
1778 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1780 raw_test_pass(0xbbbb);
1781 raw_test_pass(0xb000 + targetcore); // targetcore
1787 gdn_send(totalexetime);
1789 raw_test_pass_reg(totalexetime);
1790 raw_test_pass(0xffff);
1792 // end of sending this msg, set sand msg flag false
1793 isMsgSending = false;
1794 // check if there are pending msgs
1795 while(isMsgHanging) {
1796 // get the msg from outmsgdata[]
1797 // length + target + msg
1798 outmsgleft = outmsgdata[outmsgindex++];
1799 targetcore = outmsgdata[outmsgindex++];
1800 calCoords(targetcore, &target_y, &target_x);
1801 // Build the message header
1802 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1804 target_y, target_x);
1805 isMsgSending = true;
1808 raw_test_pass(0xbbbb);
1809 raw_test_pass(0xb000 + targetcore); // targetcore
1811 while(outmsgleft-- > 0) {
1812 gdn_send(outmsgdata[outmsgindex++]);
1814 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1818 raw_test_pass(0xffff);
1820 isMsgSending = false;
1822 raw_user_interrupts_off();
1824 // check if there are still msg hanging
1825 if(outmsgindex == outmsglast) {
1827 outmsgindex = outmsglast = 0;
1828 isMsgHanging = false;
1831 raw_user_interrupts_on();
1837 // output the profiling data
1838 void outputProfileData() {
1845 int totaltasktime = 0;
1846 int preprocessingtime = 0;
1847 int objqueuecheckingtime = 0;
1848 int postprocessingtime = 0;
1849 //int interruptiontime = 0;
1851 int averagetasktime = 0;
1854 for(i = 0; i < 50; i++) {
1858 calCoords(corenum, &self_y, &self_x);
1859 c_y = (char)self_y + '0';
1860 c_x = (char)self_x + '0';
1861 strcat(fn, "profile_");
1867 if((fp = fopen(fn, "w+")) == NULL) {
1868 fprintf(stderr, "fopen error\n");
1872 fprintf(fp, "Task Name, Start Time, End Time, Duration\n");
1873 // output task related info
1874 for(i = 0; i < taskInfoIndex; i++) {
1875 TaskInfo* tmpTInfo = taskInfoArray[i];
1876 int duration = tmpTInfo->endTime - tmpTInfo->startTime;
1877 fprintf(fp, "%s, %d, %d, %d\n", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration);
1878 if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
1879 preprocessingtime += duration;
1880 } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
1881 postprocessingtime += duration;
1882 } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
1883 objqueuecheckingtime += duration;
1885 totaltasktime += duration;
1886 averagetasktime += duration;
1891 if(taskInfoOverflow) {
1892 fprintf(stderr, "Caution: task info overflow!\n");
1895 other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
1896 averagetasktime /= tasknum;
1898 fprintf(fp, "\nTotal time: %d\n", totalexetime);
1899 fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
1900 fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
1901 fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
1902 fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
1903 fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
1905 fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
1912 raw_test_pass(0xdddd);
1913 // output task related info
1914 for(i= 0; i < taskInfoIndex; i++) {
1915 TaskInfo* tmpTInfo = taskInfoArray[i];
1916 char* tmpName = tmpTInfo->taskName;
1917 int nameLen = strlen(tmpName);
1918 raw_test_pass(0xddda);
1919 for(j = 0; j < nameLen; j++) {
1920 raw_test_pass_reg(tmpName[j]);
1922 raw_test_pass(0xdddb);
1923 raw_test_pass_reg(tmpTInfo->startTime);
1924 raw_test_pass_reg(tmpTInfo->endTime);
1925 raw_test_pass(0xdddc);
1928 if(taskInfoOverflow) {
1929 raw_test_pass(0xefee);
1932 // output interrupt related info
1933 /*for(i = 0; i < interruptInfoIndex; i++) {
1934 InterruptInfo* tmpIInfo = interruptInfoArray[i];
1935 raw_test_pass(0xddde);
1936 raw_test_pass_reg(tmpIInfo->startTime);
1937 raw_test_pass_reg(tmpIInfo->endTime);
1938 raw_test_pass(0xdddf);
1941 if(interruptInfoOverflow) {
1942 raw_test_pass(0xefef);
1945 raw_test_pass(0xeeee);
1950 // receive object transferred from other cores
1951 // or the terminate message from other cores
1952 // NOTICE: following format is for threadsimulate version only
1953 // RAW version please see previous description
1954 // format: type + object
1955 // type: -1--stall msg
1957 // return value: 0--received an object
1958 // 1--received nothing
1959 // 2--received a Stall Msg
1960 // 3--received a lock Msg
1961 // RAW version: -1 -- received nothing
1962 // otherwise -- received msg type
1963 int receiveObject() {
1967 int self_y, self_x, target_y, target_x;
1969 if(gdn_input_avail() == 0) {
1971 if(corenum < NUMCORES) {
1972 raw_test_pass(0xd001);
1978 /*if(isInterrupt && (!interruptInfoOverflow)) {
1979 // raw_test_pass(0xffff);
1980 interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
1981 interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
1982 interruptInfoArray[interruptInfoIndex]->endTime = -1;
1987 raw_test_pass(0xcccc);
1989 while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
1990 msgdata[msgdataindex] = gdn_receive();
1991 if(msgdataindex == 0) {
1992 if(msgdata[0] == 7) {
1994 } else if(msgdata[0] == 6) {
1996 } else if(msgdata[0] > 2) {
1998 } else if(msgdata[0] > 0) {
2001 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
2002 msglength = msgdata[msgdataindex];
2005 raw_test_pass_reg(msgdata[msgdataindex]);
2009 /*if(msgdataindex == 0) {
2011 msgtype = gdn_receive();
2018 msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
2019 msgdata[msgdataindex] = msgtype;
2022 raw_test_pass_reg(msgtype);
2024 } else if((msgdataindex == 1) && (msgtype == 0)) {
2025 // object transfer msg
2026 msglength = gdn_receive();
2027 msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
2028 msgdata[0] = msgtype;
2029 msgdata[msgdataindex] = msglength;
2031 raw_test_pass_reg(msgdata[msgdataindex]);
2034 msgdata[msgdataindex] = gdn_receive();
2036 raw_test_pass_reg(msgdata[msgdataindex]);
2042 raw_test_pass(0xffff);
2044 if(msgdataindex == msglength) {
2045 // received a whole msg
2046 int type, data1, data2; // will receive at least 3 words including type
2052 // receive a object transfer msg
2053 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
2055 if(corenum > NUMCORES - 1) {
2056 raw_test_done(0xa00a);
2058 // store the object and its corresponding queue info, enqueue it later
2059 transObj->objptr = (void *)data2; // data1 is now size of the msg
2060 transObj->length = (msglength - 3) / 2;
2061 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
2062 for(k = 0; k < transObj->length; ++k) {
2063 transObj->queues[2*k] = msgdata[3+2*k];
2065 raw_test_pass_reg(transObj->queues[2*k]);
2067 transObj->queues[2*k+1] = msgdata[3+2*k+1];
2069 raw_test_pass_reg(transObj->queues[2*k+1]);
2072 // check if there is an existing duplicate item
2074 struct QueueItem * qitem = getTail(&objqueue);
2075 struct QueueItem * prev = NULL;
2076 while(qitem != NULL) {
2077 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
2078 if(tmpinfo->objptr == transObj->objptr) {
2079 // the same object, remove outdate one
2080 removeItem(&objqueue, qitem);
2085 qitem = getTail(&objqueue);
2087 qitem = getNext(prev);
2090 //memcpy(transObj->queues, msgdata[3], sizeof(int)*(msglength - 3));
2091 addNewItem_I(&objqueue, (void *)transObj);
2093 ++(self_numreceiveobjs);
2095 raw_test_pass(0xe881);
2098 addNewItem_I(&objqueue, (void *)data2);
2099 ++(self_numreceiveobjs);
2101 raw_test_pass(0xe881);
2108 // receive a stall msg
2109 if(corenum != STARTUPCORE) {
2110 // non startup core can not receive stall msg
2112 raw_test_done(0xa001);
2114 if(data1 < NUMCORES) {
2116 raw_test_pass(0xe882);
2118 corestatus[data1] = 0;
2119 numsendobjs[data1] = data2;
2120 numreceiveobjs[data1] = msgdata[3];
2126 // receive lock request msg
2127 // for 32 bit machine, the size is always 3 words
2128 //int msgsize = sizeof(int) * 3;
2130 // lock request msg, handle it right now
2131 // check to see if there is a lock exist in locktbl for the required obj
2132 int data3 = msgdata[3];
2134 if(!RuntimeHashcontainskey(locktbl, data2)) {
2135 // no locks for this object
2136 // first time to operate on this shared object
2137 // create a lock for it
2138 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2140 raw_test_pass(0xe883);
2143 RuntimeHashadd_I(locktbl, data2, 1);
2145 RuntimeHashadd_I(locktbl, data2, -1);
2150 raw_test_pass(0xe884);
2152 RuntimeHashget(locktbl, data2, &rwlock_obj);
2154 raw_test_pass_reg(rwlock_obj);
2156 if(0 == rwlock_obj) {
2162 RuntimeHashremovekey(locktbl, data2);
2163 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2164 } else if((rwlock_obj > 0) && (data1 == 0)) {
2165 // read lock request and there are only read locks
2167 RuntimeHashremovekey(locktbl, data2);
2168 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2173 raw_test_pass_reg(rwlock_obj);
2177 // check if there is still some msg on sending
2180 raw_test_pass(0xe885);
2182 isMsgHanging = true;
2183 // cache the msg in outmsgdata and send it later
2184 // msglength + target core + msg
2185 outmsgdata[outmsglast++] = msgsize;
2186 outmsgdata[outmsglast++] = targetcore;
2188 outmsgdata[outmsglast++] = 4;
2190 outmsgdata[outmsglast++] = 3;
2192 outmsgdata[outmsglast++] = data1;
2193 outmsgdata[outmsglast++] = data2;
2196 raw_test_pass(0xe886);
2198 // no msg on sending, send it out
2199 calCoords(corenum, &self_y, &self_x);
2200 calCoords(targetcore, &target_y, &target_x);
2201 // Build the message header
2202 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2204 target_y, target_x);
2205 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2207 raw_test_pass(0xbbbb);
2208 raw_test_pass(0xb000 + targetcore); // targetcore
2211 // deny the lock request
2212 gdn_send(4); // lock request
2217 // grount the lock request
2218 gdn_send(3); // lock request
2223 gdn_send(data1); // lock type
2225 raw_test_pass_reg(data1);
2227 gdn_send(data2); // lock target
2229 raw_test_pass_reg(data2);
2230 raw_test_pass(0xffff);
2237 // receive lock grount msg
2238 if(corenum > NUMCORES - 1) {
2239 raw_test_done(0xa00b);
2241 if(lockobj == data2) {
2248 // conflicts on lockresults
2249 raw_test_done(0xa002);
2255 // receive lock grount/deny msg
2256 if(corenum > NUMCORES - 1) {
2257 raw_test_done(0xa00c);
2259 if(lockobj == data2) {
2266 // conflicts on lockresults
2267 raw_test_done(0xa003);
2273 // receive lock release msg
2274 if(!RuntimeHashcontainskey(locktbl, data2)) {
2275 // no locks for this object, something is wrong
2276 raw_test_done(0xa004);
2279 RuntimeHashget(locktbl, data2, &rwlock_obj);
2281 raw_test_pass(0xe887);
2282 raw_test_pass_reg(rwlock_obj);
2289 RuntimeHashremovekey(locktbl, data2);
2290 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2292 raw_test_pass_reg(rwlock_obj);
2300 // receive an output request msg
2301 if(corenum == STARTUPCORE) {
2302 // startup core can not receive profile output finish msg
2304 raw_test_done(0xa00a);
2309 totalexetime = data1;
2310 outputProfileData();
2311 /*if(data1 >= NUMCORES) {
2312 raw_test_pass(0xee04);
2313 raw_test_pass_reg(taskInfoIndex);
2314 raw_test_pass_reg(taskInfoOverflow);
2315 if(!taskInfoOverflow) {
2316 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
2318 if(taskInfoIndex == TASKINFOLENGTH) {
2319 taskInfoOverflow = true;
2323 // no msg on sending, send it out
2324 targetcore = STARTUPCORE;
2325 calCoords(corenum, &self_y, &self_x);
2326 calCoords(targetcore, &target_y, &target_x);
2327 // Build the message header
2328 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2330 target_y, target_x);
2333 raw_test_pass(0xbbbb);
2334 raw_test_pass(0xb000 + targetcore); // targetcore
2342 raw_test_pass_reg(corenum);
2343 raw_test_pass(0xffff);
2350 // receive a profile output finish msg
2351 if(corenum != STARTUPCORE) {
2352 // non startup core can not receive profile output finish msg
2354 raw_test_done(0xa00b);
2356 profilestatus[data1] = 0;
2366 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
2367 msgdata[msgdataindex] = -1;
2373 raw_test_pass(0xe888);
2375 if(gdn_input_avail() != 0) {
2379 /* if(isInterrupt && (!interruptInfoOverflow)) {
2380 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2381 interruptInfoIndex++;
2382 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2383 interruptInfoOverflow = true;
2391 raw_test_pass(0xe889);
2394 /* if(isInterrupt && (!interruptInfoOverflow)) {
2395 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2396 interruptInfoIndex++;
2397 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2398 interruptInfoOverflow = true;
2404 #elif defined THREADSIMULATE
2405 int numofcore = pthread_getspecific(key);
2406 // use POSIX message queue to transfer object
2408 struct mq_attr mqattr;
2409 mq_getattr(mqd[numofcore], &mqattr);
2410 void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
2411 msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
2417 //printf("msg: %s\n",msgptr);
2418 if(((int*)msgptr)[0] == -1) {
2420 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2421 int index = tmpptr->flag;
2422 corestatus[index] = 0;
2423 numsendobjs[index] = tmpptr->___cachedHash___;
2424 numreceiveobjs[index] = tmpptr->___cachedCode___;
2425 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
2428 } /*else if(((int*)msgptr)[0] == -2) {
2434 if(numofcore == STARTUPCORE) {
2435 ++(numreceiveobjs[numofcore]);
2437 ++(thread_data_array[numofcore].numreceiveobjs);
2439 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2440 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
2441 tmpptr = (struct ___Object___ *)(transObj->objptr);
2442 int type = tmpptr->type;
2443 int size=classsize[type];
2444 struct ___Object___ * newobj=RUNMALLOC(size);
2445 memcpy(newobj, tmpptr, size);
2446 if(0 == newobj->isolate) {
2447 newobj->original=tmpptr;
2452 for(k = 0; k < transObj->length; ++k) {
2453 int taskindex = transObj->queues[2 * k];
2454 int paramindex = transObj->queues[2 * k + 1];
2455 struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2456 enqueueObject(newobj, queues, 1);
2458 RUNFREE(transObj->queues);
2465 bool getreadlock(void * ptr) {
2468 int self_y, self_x, target_y, target_x;
2469 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2470 // for 32 bit machine, the size is always 4 words
2471 //int msgsize = sizeof(int) * 4;
2475 raw_user_interrupts_off();
2477 targetcore = ((int)ptr >> 5) % tc;
2479 raw_user_interrupts_on();
2489 if(targetcore == corenum) {
2490 // reside on this core
2493 raw_user_interrupts_off();
2495 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2496 // no locks for this object
2497 // first time to operate on this shared object
2498 // create a lock for it
2499 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2500 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2503 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2504 if(-1 != rwlock_obj) {
2506 RuntimeHashremovekey(locktbl, (int)ptr);
2507 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2513 raw_user_interrupts_on();
2515 if(lockobj == (int)ptr) {
2526 // conflicts on lockresults
2527 raw_test_done(0xa005);
2532 calCoords(corenum, &self_y, &self_x);
2533 calCoords(targetcore, &target_y, &target_x);
2534 // Build the message header
2535 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2537 target_y, target_x);
2538 // start sending the msg, set send msg flag
2539 isMsgSending = true;
2540 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2542 raw_test_pass(0xbbbb);
2543 raw_test_pass(0xb000 + targetcore); // targetcore
2545 gdn_send(2); // lock request
2549 gdn_send(0); // read lock
2555 raw_test_pass_reg(ptr);
2559 raw_test_pass_reg(corenum);
2560 raw_test_pass(0xffff);
2562 // end of sending this msg, set sand msg flag false
2563 isMsgSending = false;
2564 // check if there are pending msgs
2565 while(isMsgHanging) {
2566 // get the msg from outmsgdata[]
2567 // length + target + msg
2568 outmsgleft = outmsgdata[outmsgindex++];
2569 targetcore = outmsgdata[outmsgindex++];
2570 calCoords(targetcore, &target_y, &target_x);
2571 // Build the message header
2572 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2574 target_y, target_x);
2575 isMsgSending = true;
2576 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2578 raw_test_pass(0xbbbb);
2579 raw_test_pass(0xb000 + targetcore); // targetcore
2581 while(outmsgleft-- > 0) {
2582 gdn_send(outmsgdata[outmsgindex++]);
2584 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2588 raw_test_pass(0xffff);
2590 isMsgSending = false;
2592 raw_user_interrupts_off();
2594 // check if there are still msg hanging
2595 if(outmsgindex == outmsglast) {
2597 outmsgindex = outmsglast = 0;
2598 isMsgHanging = false;
2601 raw_user_interrupts_on();
2605 #elif defined THREADSIMULATE
2606 int numofcore = pthread_getspecific(key);
2608 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2609 printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2613 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2614 // no locks for this object
2615 // first time to operate on this shared object
2616 // create a lock for it
2617 rc = pthread_rwlock_unlock(&rwlock_tbl);
2618 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2619 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2620 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2621 rc = pthread_rwlock_init(rwlock, NULL);
2622 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2623 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2624 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2629 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2631 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2634 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2636 rc = pthread_rwlock_unlock(&rwlock_tbl);
2637 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2639 rc = pthread_rwlock_tryrdlock(rwlock);
2640 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2647 pthread_rwlock_t* rwlock_obj = NULL;
2648 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2649 rc = pthread_rwlock_unlock(&rwlock_tbl);
2650 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2651 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
2652 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2662 void releasereadlock(void * ptr) {
2665 int self_y, self_x, target_y, target_x;
2666 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2667 // for 32 bit machine, the size is always 3 words
2668 //int msgsize = sizeof(int) * 3;
2672 raw_user_interrupts_off();
2674 targetcore = ((int)ptr >> 5) % tc;
2676 raw_user_interrupts_on();
2679 if(targetcore == corenum) {
2681 raw_user_interrupts_off();
2683 // reside on this core
2684 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2685 // no locks for this object, something is wrong
2686 raw_test_done(0xa006);
2689 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2691 RuntimeHashremovekey(locktbl, (int)ptr);
2692 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2695 raw_user_interrupts_on();
2700 calCoords(corenum, &self_y, &self_x);
2701 calCoords(targetcore, &target_y, &target_x);
2702 // Build the message header
2703 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2705 target_y, target_x);
2706 // start sending the msg, set send msg flag
2707 isMsgSending = true;
2708 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2710 raw_test_pass(0xbbbb);
2711 raw_test_pass(0xb000 + targetcore); // targetcore
2713 gdn_send(5); // lock release
2717 gdn_send(0); // read lock
2723 raw_test_pass_reg(ptr);
2724 raw_test_pass(0xffff);
2726 // end of sending this msg, set sand msg flag false
2727 isMsgSending = false;
2728 // check if there are pending msgs
2729 while(isMsgHanging) {
2730 // get the msg from outmsgdata[]
2731 // length + target + msg
2732 outmsgleft = outmsgdata[outmsgindex++];
2733 targetcore = outmsgdata[outmsgindex++];
2734 calCoords(targetcore, &target_y, &target_x);
2735 // Build the message header
2736 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2738 target_y, target_x);
2739 isMsgSending = true;
2740 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2742 raw_test_pass(0xbbbb);
2743 raw_test_pass(0xb000 + targetcore); // targetcore
2745 while(outmsgleft-- > 0) {
2746 gdn_send(outmsgdata[outmsgindex++]);
2748 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2752 raw_test_pass(0xffff);
2754 isMsgSending = false;
2756 raw_user_interrupts_off();
2758 // check if there are still msg hanging
2759 if(outmsgindex == outmsglast) {
2761 outmsgindex = outmsglast = 0;
2762 isMsgHanging = false;
2765 raw_user_interrupts_on();
2768 #elif defined THREADSIMULATE
2769 int numofcore = pthread_getspecific(key);
2770 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2771 printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2772 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2773 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2776 pthread_rwlock_t* rwlock_obj = NULL;
2777 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2778 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2779 printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2780 rc = pthread_rwlock_unlock(&rwlock_tbl);
2781 printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2786 bool getreadlock_I(void * ptr) {
2788 int self_y, self_x, target_y, target_x;
2789 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2790 // for 32 bit machine, the size is always 4 words
2791 //int msgsize = sizeof(int) * 4;
2801 if(targetcore == corenum) {
2802 // reside on this core
2804 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2805 // no locks for this object
2806 // first time to operate on this shared object
2807 // create a lock for it
2808 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2809 RuntimeHashadd_I(locktbl, (int)ptr, 1);
2812 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2813 if(-1 != rwlock_obj) {
2815 RuntimeHashremovekey(locktbl, (int)ptr);
2816 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2821 if(lockobj == (int)ptr) {
2832 // conflicts on lockresults
2833 raw_test_done(0xa005);
2838 calCoords(corenum, &self_y, &self_x);
2839 calCoords(targetcore, &target_y, &target_x);
2840 // Build the message header
2841 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2843 target_y, target_x);
2844 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2846 raw_test_pass(0xbbbb);
2847 raw_test_pass(0xb000 + targetcore); // targetcore
2849 gdn_send(2); // lock request
2853 gdn_send(0); // read lock
2859 raw_test_pass_reg(ptr);
2863 raw_test_pass_reg(corenum);
2864 raw_test_pass(0xffff);
2869 void releasereadlock_I(void * ptr) {
2871 int self_y, self_x, target_y, target_x;
2872 int targetcore = ((int)ptr >> 5) % TOTALCORE;
2873 // for 32 bit machine, the size is always 3 words
2874 //int msgsize = sizeof(int) * 3;
2877 if(targetcore == corenum) {
2878 // reside on this core
2879 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2880 // no locks for this object, something is wrong
2881 raw_test_done(0xa006);
2884 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2886 RuntimeHashremovekey(locktbl, (int)ptr);
2887 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
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(5); // lock release
2907 gdn_send(0); // read lock
2913 raw_test_pass_reg(ptr);
2914 raw_test_pass(0xffff);
2920 bool getwritelock(void * ptr) {
2923 int self_y, self_x, target_y, target_x;
2924 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
2925 // for 32 bit machine, the size is always 4 words
2926 //int msgsize = sizeof(int) * 4;
2930 raw_user_interrupts_off();
2932 targetcore = ((int)ptr >> 5) % tc;
2934 raw_user_interrupts_on();
2938 raw_test_pass(0xe551);
2939 raw_test_pass_reg(ptr);
2940 raw_test_pass_reg(targetcore);
2941 raw_test_pass_reg(tc);
2951 if(targetcore == corenum) {
2952 // reside on this core
2955 raw_user_interrupts_off();
2957 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2958 // no locks for this object
2959 // first time to operate on this shared object
2960 // create a lock for it
2961 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2963 raw_test_pass(0xe552);
2965 RuntimeHashadd_I(locktbl, (int)ptr, -1);
2968 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2970 raw_test_pass(0xe553);
2971 raw_test_pass_reg(rwlock_obj);
2973 if(0 == rwlock_obj) {
2975 RuntimeHashremovekey(locktbl, (int)ptr);
2976 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2982 raw_user_interrupts_on();
2985 raw_test_pass(0xe554);
2986 raw_test_pass_reg(lockresult);
2988 if(lockobj == (int)ptr) {
3005 // conflicts on lockresults
3006 raw_test_done(0xa007);
3012 raw_test_pass(0xe555);
3014 calCoords(corenum, &self_y, &self_x);
3015 calCoords(targetcore, &target_y, &target_x);
3016 // Build the message header
3017 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3019 target_y, target_x);
3020 // start sending the msg, set send msg flag
3021 isMsgSending = true;
3022 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3024 raw_test_pass(0xbbbb);
3025 raw_test_pass(0xb000 + targetcore); // targetcore
3027 gdn_send(2); // lock request
3031 gdn_send(1); // write lock
3037 raw_test_pass_reg(ptr);
3041 raw_test_pass_reg(corenum);
3042 raw_test_pass(0xffff);
3044 // end of sending this msg, set sand msg flag false
3045 isMsgSending = false;
3046 // check if there are pending msgs
3047 while(isMsgHanging) {
3048 // get the msg from outmsgdata[]
3049 // length + target + msg
3050 outmsgleft = outmsgdata[outmsgindex++];
3051 targetcore = outmsgdata[outmsgindex++];
3052 calCoords(targetcore, &target_y, &target_x);
3053 // Build the message header
3054 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3056 target_y, target_x);
3057 isMsgSending = true;
3058 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3060 raw_test_pass(0xbbbb);
3061 raw_test_pass(0xb000 + targetcore); // targetcore
3063 while(outmsgleft-- > 0) {
3064 gdn_send(outmsgdata[outmsgindex++]);
3066 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3070 raw_test_pass(0xffff);
3072 isMsgSending = false;
3074 raw_user_interrupts_off();
3076 // check if there are still msg hanging
3077 if(outmsgindex == outmsglast) {
3079 outmsgindex = outmsglast = 0;
3080 isMsgHanging = false;
3083 raw_user_interrupts_on();
3087 #elif defined THREADSIMULATE
3088 int numofcore = pthread_getspecific(key);
3090 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3091 printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3095 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3096 // no locks for this object
3097 // first time to operate on this shared object
3098 // create a lock for it
3099 rc = pthread_rwlock_unlock(&rwlock_tbl);
3100 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3101 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3102 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3103 rc = pthread_rwlock_init(rwlock, NULL);
3104 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3105 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3106 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3108 pthread_rwlock_destroy(rwlock);
3112 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3114 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3116 pthread_rwlock_destroy(rwlock);
3118 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3120 rc = pthread_rwlock_unlock(&rwlock_tbl);
3121 printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3123 rc = pthread_rwlock_trywrlock(rwlock);
3124 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3131 pthread_rwlock_t* rwlock_obj = NULL;
3132 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3133 rc = pthread_rwlock_unlock(&rwlock_tbl);
3134 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3135 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
3136 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3147 void releasewritelock(void * ptr) {
3150 int self_y, self_x, target_y, target_x;
3151 int targetcore = 0; //((int)ptr >> 5) % TOTALCORE;
3152 // for 32 bit machine, the size is always 3 words
3153 //int msgsize = sizeof(int) * 3;
3157 raw_user_interrupts_off();
3159 targetcore = ((int)ptr >> 5) % tc;
3161 raw_user_interrupts_on();
3164 if(targetcore == corenum) {
3166 raw_user_interrupts_off();
3168 // reside on this core
3169 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3170 // no locks for this object, something is wrong
3171 raw_test_done(0xa008);
3175 raw_test_pass(0xe662);
3177 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3179 raw_test_pass_reg(rwlock_obj);
3182 RuntimeHashremovekey(locktbl, (int)ptr);
3183 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
3185 raw_test_pass_reg(rwlock_obj);
3189 raw_user_interrupts_on();
3195 raw_test_pass(0xe663);
3197 calCoords(corenum, &self_y, &self_x);
3198 calCoords(targetcore, &target_y, &target_x);
3199 // Build the message header
3200 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3202 target_y, target_x);
3203 // start sending the msg, set send msg flag
3204 isMsgSending = true;
3205 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3207 raw_test_pass(0xbbbb);
3208 raw_test_pass(0xb000 + targetcore);
3210 gdn_send(5); // lock release
3214 gdn_send(1); // write lock
3220 raw_test_pass_reg(ptr);
3221 raw_test_pass(0xffff);
3223 // end of sending this msg, set sand msg flag false
3224 isMsgSending = false;
3225 // check if there are pending msgs
3226 while(isMsgHanging) {
3227 // get the msg from outmsgdata[]
3228 // length + target + msg
3229 outmsgleft = outmsgdata[outmsgindex++];
3230 targetcore = outmsgdata[outmsgindex++];
3231 calCoords(targetcore, &target_y, &target_x);
3232 // Build the message header
3233 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3235 target_y, target_x);
3236 isMsgSending = true;
3237 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3239 raw_test_pass(0xbbbb);
3240 raw_test_pass(0xb000 + targetcore); // targetcore
3242 while(outmsgleft-- > 0) {
3243 gdn_send(outmsgdata[outmsgindex++]);
3245 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3249 raw_test_pass(0xffff);
3251 isMsgSending = false;
3253 raw_user_interrupts_off();
3255 // check if there are still msg hanging
3256 if(outmsgindex == outmsglast) {
3258 outmsgindex = outmsglast = 0;
3259 isMsgHanging = false;
3262 raw_user_interrupts_on();
3265 #elif defined THREADSIMULATE
3266 int numofcore = pthread_getspecific(key);
3267 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3268 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3269 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3270 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3273 pthread_rwlock_t* rwlock_obj = NULL;
3274 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3275 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3276 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3277 rc = pthread_rwlock_unlock(&rwlock_tbl);
3278 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3282 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3283 void * taskpointerarray[MAXTASKPARAMS];
3285 int numparams=parameter->task->numParameters;
3286 int numiterators=parameter->task->numTotal-1;
3291 struct taskdescriptor * task=parameter->task;
3293 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
3295 /* Add enqueued object to parameter vector */
3296 taskpointerarray[parameter->slot]=ptr;
3298 /* Reset iterators */
3299 for(j=0; j<numiterators; j++) {
3300 toiReset(¶meter->iterators[j]);
3303 /* Find initial state */
3304 for(j=0; j<numiterators; j++) {
3306 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3307 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3309 /* Need to backtrack */
3310 toiReset(¶meter->iterators[j]);
3314 /* Nothing to enqueue */
3321 /* Enqueue current state */
3323 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
3325 tpd->numParameters=numiterators+1;
3326 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
3327 for(j=0; j<=numiterators; j++) {
3328 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3331 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3332 genputtable(activetasks, tpd, tpd);
3334 RUNFREE(tpd->parameterArray);
3338 /* This loop iterates to the next parameter combination */
3339 if (numiterators==0)
3342 for(j=numiterators-1; j<numiterators; j++) {
3344 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3345 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3347 /* Need to backtrack */
3348 toiReset(¶meter->iterators[j]);
3352 /* Nothing more to enqueue */
3361 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3362 void * taskpointerarray[MAXTASKPARAMS];
3364 int numparams=parameter->task->numParameters;
3365 int numiterators=parameter->task->numTotal-1;
3370 struct taskdescriptor * task=parameter->task;
3372 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
3374 /* Add enqueued object to parameter vector */
3375 taskpointerarray[parameter->slot]=ptr;
3377 /* Reset iterators */
3378 for(j=0; j<numiterators; j++) {
3379 toiReset(¶meter->iterators[j]);
3382 /* Find initial state */
3383 for(j=0; j<numiterators; j++) {
3385 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3386 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3388 /* Need to backtrack */
3389 toiReset(¶meter->iterators[j]);
3393 /* Nothing to enqueue */
3399 /* Enqueue current state */
3401 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
3403 tpd->numParameters=numiterators+1;
3404 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
3405 for(j=0; j<=numiterators; j++) {
3406 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3409 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3410 genputtable_I(activetasks, tpd, tpd);
3412 RUNFREE(tpd->parameterArray);
3416 /* This loop iterates to the next parameter combination */
3417 if (numiterators==0)
3420 for(j=numiterators-1; j<numiterators; j++) {
3422 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
3423 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
3425 /* Need to backtrack */
3426 toiReset(¶meter->iterators[j]);
3430 /* Nothing more to enqueue */
3439 /* Handler for signals. The signals catch null pointer errors and
3440 arithmatic errors. */
3442 void myhandler(int sig, siginfo_t *info, void *uap) {
3445 printf("sig=%d\n",sig);
3448 sigemptyset(&toclear);
3449 sigaddset(&toclear, sig);
3450 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
3451 longjmp(error_handler,1);
3457 struct RuntimeHash *fdtoobject;
3459 void addreadfd(int fd) {
3462 FD_SET(fd, &readfds);
3465 void removereadfd(int fd) {
3466 FD_CLR(fd, &readfds);
3467 if (maxreadfd==(fd+1)) {
3469 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
3480 void executetasks() {
3481 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
3484 struct ___Object___ * tmpparam = NULL;
3485 struct parameterdescriptor * pd=NULL;
3486 struct parameterwrapper *pw=NULL;
3496 raw_test_pass(0xe991);
3501 /* Set up signal handlers */
3502 struct sigaction sig;
3503 sig.sa_sigaction=&myhandler;
3504 sig.sa_flags=SA_SIGINFO;
3505 sigemptyset(&sig.sa_mask);
3507 /* Catch bus errors, segmentation faults, and floating point exceptions*/
3508 sigaction(SIGBUS,&sig,0);
3509 sigaction(SIGSEGV,&sig,0);
3510 sigaction(SIGFPE,&sig,0);
3511 sigaction(SIGPIPE,&sig,0);
3520 fdtoobject=allocateRuntimeHash(100);
3524 /* Map first block of memory to protected, anonymous page */
3525 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
3529 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
3533 raw_test_pass(0xe992);
3536 /* Check if any filedescriptors have IO pending */
3539 struct timeval timeout={0,0};
3543 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
3545 /* Process ready fd's */
3547 for(fd=0; fd<maxreadfd; fd++) {
3548 if (FD_ISSET(fd, &tmpreadfds)) {
3549 /* Set ready flag on object */
3551 // printf("Setting fd %d\n",fd);
3552 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
3553 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
3554 enqueueObject(objptr, NULL, 0);
3563 /* See if there are any active tasks */
3564 if (hashsize(activetasks)>0) {
3567 if(!taskInfoOverflow) {
3568 TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
3569 taskInfoArray[taskInfoIndex] = checkTaskInfo;
3570 checkTaskInfo->taskName = "tpd checking";
3571 checkTaskInfo->startTime = raw_get_cycle();
3572 checkTaskInfo->endTime = -1;
3575 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
3576 genfreekey(activetasks, currtpd);
3578 /* Check if this task has failed, allow a task that contains optional objects to fire */
3579 /*if (gencontains(failedtasks, currtpd)) {
3580 // Free up task parameter descriptor
3581 RUNFREE(currtpd->parameterArray);
3585 numparams=currtpd->task->numParameters;
3586 numtotal=currtpd->task->numTotal;
3588 #ifdef THREADSIMULATE
3589 int isolateflags[numparams];
3591 /* Make sure that the parameters are still in the queues */
3592 for(i=0; i<numparams; i++) {
3593 void * parameter=currtpd->parameterArray[i];
3596 raw_test_pass(0xe993);
3599 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3601 taskpointerarray[i+OFFSET]=parameter;
3605 // require locks for this parameter if it is not a startup object
3606 getwritelock(parameter);
3610 raw_user_interrupts_off();
3613 //isInterrupt = false;
3620 while(receiveObject() != -1) {
3624 grount = lockresult;
3633 //isInterrupt = true;
3636 raw_user_interrupts_on();
3641 raw_test_pass(0xe994);
3643 // can not get the lock, try later
3644 for(j = 0; j < i; ++j) {
3645 releasewritelock(taskpointerarray[j+OFFSET]);
3647 genputtable(activetasks, currtpd, currtpd);
3648 if(hashsize(activetasks) == 1) {
3649 // only one task right now, wait a little while before next try
3655 // fail, set the end of the checkTaskInfo
3656 if(!taskInfoOverflow) {
3657 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3659 if(taskInfoIndex == TASKINFOLENGTH) {
3660 taskInfoOverflow = true;
3668 raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
3670 for(tmp = 0; tmp < classsize[((struct ___Object___ *)parameter)->type]; ++tmp) {
3671 invalidateAddr(parameter + tmp);
3675 tmpparam = (struct ___Object___ *)parameter;
3676 #ifdef THREADSIMULATE
3677 if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3679 taskpointerarray[i+OFFSET]=parameter;
3683 if(0 == tmpparam->isolate) {
3684 isolateflags[i] = 0;
3685 // shared object, need to flush with current value
3686 //if(!getreadlock(tmpparam->original)) {
3687 // // fail to get read lock of the original object, try this task later
3688 if(!getwritelock(tmpparam->original)) {
3689 // fail to get write lock, release all obtained locks and try this task later
3691 for(j = 0; j < i; ++j) {
3692 if(0 == isolateflags[j]) {
3693 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3696 genputtable(activetasks, currtpd, currtpd);
3699 if(tmpparam->version != tmpparam->original->version) {
3700 // some task on another core has changed this object
3701 // flush this object
3702 //memcpy(tmpparam, tmpparam->original, classsize[tmpparam->type]);
3703 // release all obtained locks
3705 for(j = 0; j < i; ++j) {
3706 if(0 == isolateflags[j]) {
3707 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3710 releasewritelock(tmpparam->original);
3712 // dequeue this object
3713 int numofcore = pthread_getspecific(key);
3714 struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
3715 int length = numqueues[numofcore][tmpparam->type];
3716 for(j = 0; j < length; ++j) {
3717 struct parameterwrapper * pw = queues[j];
3718 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
3720 int UNUSED, UNUSED2;
3722 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3723 ObjectHashremove(pw->objectset, (int)tmpparam);
3724 if (enterflags!=NULL)
3728 // try to enqueue it again to check if it feeds other tasks;
3729 //enqueueObject(tmpparam, NULL, 0);
3730 // Free up task parameter descriptor
3731 RUNFREE(currtpd->parameterArray);
3736 isolateflags[i] = 1;
3739 pd=currtpd->task->descriptorarray[i];
3740 pw=(struct parameterwrapper *) pd->queue;
3741 /* Check that object is still in queue */
3743 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
3745 raw_test_pass(0xe995);
3747 // release grabbed locks
3748 for(j = 0; j < i; ++j) {
3749 releasewritelock(taskpointerarray[j+OFFSET]);
3751 releasewritelock(parameter);
3752 RUNFREE(currtpd->parameterArray);
3758 /* Check if the object's flags still meets requirements */
3762 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
3763 andmask=pw->intarray[tmpi*2];
3764 checkmask=pw->intarray[tmpi*2+1];
3766 raw_test_pass(0xdd000000 + andmask);
3767 raw_test_pass_reg((int)parameter);
3768 raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
3769 raw_test_pass(0xdd000000 + checkmask);
3771 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
3777 // flags are never suitable
3778 // remove this obj from the queue
3780 int UNUSED, UNUSED2;
3783 raw_test_pass(0xe996);
3785 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3786 ObjectHashremove(pw->objectset, (int)parameter);
3787 if (enterflags!=NULL)
3789 // release grabbed locks
3790 for(j = 0; j < i; ++j) {
3791 releasewritelock(taskpointerarray[j+OFFSET]);
3793 releasewritelock(parameter);
3794 RUNFREE(currtpd->parameterArray);
3797 // fail, set the end of the checkTaskInfo
3798 if(!taskInfoOverflow) {
3799 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3801 if(taskInfoIndex == TASKINFOLENGTH) {
3802 taskInfoOverflow = true;
3812 /* Check that object still has necessary tags */
3813 for(j=0; j<pd->numbertags; j++) {
3814 int slotid=pd->tagarray[2*j]+numparams;
3815 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
3816 if (!containstag(parameter, tagd)) {
3818 raw_test_pass(0xe997);
3820 RUNFREE(currtpd->parameterArray);
3826 taskpointerarray[i+OFFSET]=parameter;
3829 for(; i<numtotal; i++) {
3830 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
3833 #ifdef THREADSIMULATE
3834 for(i = 0; i < numparams; ++i) {
3835 if(0 == isolateflags[i]) {
3836 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3837 if(tmpparam != tmpparam->original) {
3838 taskpointerarray[i+OFFSET] = tmpparam->original;
3847 /* Checkpoint the state */
3848 forward=allocateRuntimeHash(100);
3849 reverse=allocateRuntimeHash(100);
3850 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
3853 if (x=setjmp(error_handler)) {
3858 printf("Fatal Error=%d, Recovering!\n",x);
3862 genputtable(failedtasks,currtpd,currtpd);
3863 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
3865 freeRuntimeHash(forward);
3866 freeRuntimeHash(reverse);
3874 raw_test_pass_reg(x);
3876 raw_test_done(0xa009);
3881 /*if (injectfailures) {
3882 if ((((double)random())/RAND_MAX)<failurechance) {
3883 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
3884 longjmp(error_handler,10);
3887 /* Actually call task */
3889 ((int *)taskpointerarray)[0]=currtpd->numParameters;
3890 taskpointerarray[1]=NULL;
3895 // check finish, set the end of the checkTaskInfo
3896 if(!taskInfoOverflow) {
3897 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3899 if(taskInfoIndex == TASKINFOLENGTH) {
3900 taskInfoOverflow = true;
3904 if(!taskInfoOverflow) {
3905 // new a taskInfo for the task execution
3906 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
3907 taskInfoArray[taskInfoIndex] = taskInfo;
3908 taskInfo->taskName = currtpd->task->name;
3909 taskInfo->startTime = raw_get_cycle();
3910 taskInfo->endTime = -1;
3916 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3918 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3920 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3923 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3926 // task finish, set the end of the checkTaskInfo
3927 if(!taskInfoOverflow) {
3928 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3930 if(taskInfoIndex == TASKINFOLENGTH) {
3931 taskInfoOverflow = true;
3934 // new a PostTaskInfo for the post-task execution
3935 if(!taskInfoOverflow) {
3936 TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
3937 taskInfoArray[taskInfoIndex] = postTaskInfo;
3938 postTaskInfo->taskName = "post task execution";
3939 postTaskInfo->startTime = raw_get_cycle();
3940 postTaskInfo->endTime = -1;
3944 raw_test_pass(0xe998);
3945 raw_test_pass_reg(lock);
3950 for(i = 0; i < numparams; ++i) {
3952 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3954 raw_test_pass(0xe999);
3955 raw_test_pass(0xdd100000 + tmpparam->flag);
3957 releasewritelock(tmpparam);
3959 #elif defined THREADSIMULATE
3960 for(i = 0; i < numparams; ++i) {
3961 if(0 == isolateflags[i]) {
3962 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3963 releasewritelock(tmpparam);
3970 // post task execution finish, set the end of the postTaskInfo
3971 if(!taskInfoOverflow) {
3972 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3974 if(taskInfoIndex == TASKINFOLENGTH) {
3975 taskInfoOverflow = true;
3982 freeRuntimeHash(forward);
3983 freeRuntimeHash(reverse);
3987 // Free up task parameter descriptor
3988 RUNFREE(currtpd->parameterArray);
3997 raw_test_pass(0xe99a);
4000 raw_test_pass(0xe99a);
4008 raw_test_pass(0xe999);
4012 /* This function processes an objects tags */
4013 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
4016 for(i=0; i<pd->numbertags; i++) {
4017 int slotid=pd->tagarray[2*i];
4018 int tagid=pd->tagarray[2*i+1];
4020 if (statusarray[slotid+numparams]==0) {
4021 parameter->iterators[*iteratorcount].istag=1;
4022 parameter->iterators[*iteratorcount].tagid=tagid;
4023 parameter->iterators[*iteratorcount].slot=slotid+numparams;
4024 parameter->iterators[*iteratorcount].tagobjectslot=index;
4025 statusarray[slotid+numparams]=1;
4032 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
4035 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
4037 parameter->iterators[*iteratorcount].istag=0;
4038 parameter->iterators[*iteratorcount].slot=index;
4039 parameter->iterators[*iteratorcount].objectset=objectset;
4040 statusarray[index]=1;
4042 for(i=0; i<pd->numbertags; i++) {
4043 int slotid=pd->tagarray[2*i];
4044 int tagid=pd->tagarray[2*i+1];
4045 if (statusarray[slotid+numparams]!=0) {
4046 /* This tag has already been enqueued, use it to narrow search */
4047 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
4051 parameter->iterators[*iteratorcount].numtags=tagcount;
4056 /* This function builds the iterators for a task & parameter */
4058 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
4059 int statusarray[MAXTASKPARAMS];
4061 int numparams=task->numParameters;
4062 int iteratorcount=0;
4063 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
4065 statusarray[index]=1; /* Initial parameter */
4066 /* Process tags for initial iterator */
4068 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
4072 /* Check for objects with existing tags */
4073 for(i=0; i<numparams; i++) {
4074 if (statusarray[i]==0) {
4075 struct parameterdescriptor *pd=task->descriptorarray[i];
4077 for(j=0; j<pd->numbertags; j++) {
4078 int slotid=pd->tagarray[2*j];
4079 if(statusarray[slotid+numparams]!=0) {
4080 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4081 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4088 /* Next do objects w/ unbound tags*/
4090 for(i=0; i<numparams; i++) {
4091 if (statusarray[i]==0) {
4092 struct parameterdescriptor *pd=task->descriptorarray[i];
4093 if (pd->numbertags>0) {
4094 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4095 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4101 /* Nothing with a tag enqueued */
4103 for(i=0; i<numparams; i++) {
4104 if (statusarray[i]==0) {
4105 struct parameterdescriptor *pd=task->descriptorarray[i];
4106 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4107 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4120 #ifdef THREADSIMULATE
4121 int numofcore = pthread_getspecific(key);
4122 for(i=0; i<numtasks[numofcore]; i++) {
4123 struct taskdescriptor * task=taskarray[numofcore][i];
4126 if(corenum > NUMCORES - 1) {
4130 for(i=0; i<numtasks[corenum]; i++) {
4131 struct taskdescriptor * task=taskarray[corenum][i];
4134 printf("%s\n", task->name);
4136 for(j=0; j<task->numParameters; j++) {
4137 struct parameterdescriptor *param=task->descriptorarray[j];
4138 struct parameterwrapper *parameter=param->queue;
4139 struct ObjectHash * set=parameter->objectset;
4140 struct ObjectIterator objit;
4142 printf(" Parameter %d\n", j);
4144 ObjectHashiterator(set, &objit);
4145 while(ObjhasNext(&objit)) {
4146 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
4147 struct ___Object___ * tagptr=obj->___tags___;
4148 int nonfailed=Objdata4(&objit);
4149 int numflags=Objdata3(&objit);
4150 int flags=Objdata2(&objit);
4153 printf(" Contains %lx\n", obj);
4154 printf(" flag=%d\n", obj->flag);
4157 } else if (tagptr->type==TAGTYPE) {
4159 printf(" tag=%lx\n",tagptr);
4164 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
4165 for(; tagindex<ao->___cachedCode___; tagindex++) {
4167 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
4177 /* This function processes the task information to create queues for
4178 each parameter type. */
4180 void processtasks() {
4183 if(corenum > NUMCORES - 1) {
4187 #ifdef THREADSIMULATE
4188 int numofcore = pthread_getspecific(key);
4189 for(i=0; i<numtasks[numofcore]; i++) {
4190 struct taskdescriptor *task=taskarray[numofcore][i];
4192 for(i=0; i<numtasks[corenum]; i++) {
4193 struct taskdescriptor * task=taskarray[corenum][i];
4197 /* Build objectsets */
4198 for(j=0; j<task->numParameters; j++) {
4199 struct parameterdescriptor *param=task->descriptorarray[j];
4200 struct parameterwrapper *parameter=param->queue;
4201 parameter->objectset=allocateObjectHash(10);
4202 parameter->task=task;
4205 /* Build iterators for parameters */
4206 for(j=0; j<task->numParameters; j++) {
4207 struct parameterdescriptor *param=task->descriptorarray[j];
4208 struct parameterwrapper *parameter=param->queue;
4209 builditerators(task, j, parameter);
4214 void toiReset(struct tagobjectiterator * it) {
4217 } else if (it->numtags>0) {
4220 ObjectHashiterator(it->objectset, &it->it);
4224 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4227 /* Get object with tags */
4228 struct ___Object___ *obj=objectarray[it->tagobjectslot];
4229 struct ___Object___ *tagptr=obj->___tags___;
4230 if (tagptr->type==TAGTYPE) {
4231 if ((it->tagobjindex==0)&& /* First object */
4232 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
4237 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4238 int tagindex=it->tagobjindex;
4239 for(; tagindex<ao->___cachedCode___; tagindex++) {
4240 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
4241 if (td->flag==it->tagid) {
4242 it->tagobjindex=tagindex; /* Found right type of tag */
4248 } else if (it->numtags>0) {
4249 /* Use tags to locate appropriate objects */
4250 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4251 struct ___Object___ *objptr=tag->flagptr;
4253 if (objptr->type!=OBJECTARRAYTYPE) {
4254 if (it->tagobjindex>0)
4256 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4258 for(i=1; i<it->numtags; i++) {
4259 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4260 if (!containstag(objptr,tag2))
4265 struct ArrayObject *ao=(struct ArrayObject *) objptr;
4268 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
4269 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
4270 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4272 for(i=1; i<it->numtags; i++) {
4273 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4274 if (!containstag(objptr,tag2))
4277 it->tagobjindex=tagindex;
4282 it->tagobjindex=tagindex;
4286 return ObjhasNext(&it->it);
4290 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
4292 struct ___Object___ * objptr=tag->flagptr;
4293 if (objptr->type==OBJECTARRAYTYPE) {
4294 struct ArrayObject *ao=(struct ArrayObject *)objptr;
4295 for(j=0; j<ao->___cachedCode___; j++) {
4296 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
4304 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4305 /* hasNext has all of the intelligence */
4308 /* Get object with tags */
4309 struct ___Object___ *obj=objectarray[it->tagobjectslot];
4310 struct ___Object___ *tagptr=obj->___tags___;
4311 if (tagptr->type==TAGTYPE) {
4313 objectarray[it->slot]=tagptr;
4315 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4316 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
4318 } else if (it->numtags>0) {
4319 /* Use tags to locate appropriate objects */
4320 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4321 struct ___Object___ *objptr=tag->flagptr;
4322 if (objptr->type!=OBJECTARRAYTYPE) {
4324 objectarray[it->slot]=objptr;
4326 struct ArrayObject *ao=(struct ArrayObject *) objptr;
4327 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
4330 /* Iterate object */
4331 objectarray[it->slot]=(void *)Objkey(&it->it);