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
66 struct RuntimeHash locktable;
67 static struct RuntimeHash* locktbl = &locktable;
72 struct RuntimeHash * objRedirectLockTbl;
73 void * curr_heapbase=0;
74 void * curr_heaptop=0;
76 int self_numreceiveobjs;
84 struct Queue objqueue;
94 volatile bool isMsgSending;
95 void calCoords(int core_num, int* coordY, int* coordX);
96 #elif defined THREADSIMULATE
97 static struct RuntimeHash* locktbl;
105 struct thread_data thread_data_array[NUMCORES];
107 static pthread_key_t key;
108 static pthread_rwlock_t rwlock_tbl;
109 static pthread_rwlock_t rwlock_init;
111 void run(void * arg);
114 bool transStallMsg(int targetcore);
115 void transStatusConfirmMsg(int targetcore);
117 bool getreadlock(void* ptr);
118 void releasereadlock(void* ptr);
120 bool getreadlock_I_r(void * ptr, void * redirectlock, int core, bool cache);
122 bool getwritelock(void* ptr);
123 void releasewritelock(void* ptr);
124 void releasewritelock_r(void * lock, void * redirectlock);
126 bool getwritelock_I(void* ptr);
127 bool getwritelock_I_r(void* lock, void* redirectlock, int core, bool cache);
128 void releasewritelock_I(void * ptr);
131 // profiling mode of RAW version
134 #define TASKINFOLENGTH 10000
135 //#define INTERRUPTINFOLENGTH 500
141 typedef struct task_info {
146 struct Queue * newObjs;
149 /*typedef struct interrupt_info {
154 TaskInfo * taskInfoArray[TASKINFOLENGTH];
156 bool taskInfoOverflow;
157 /*InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
158 int interruptInfoIndex;
159 bool interruptInfoOverflow;*/
160 int profilestatus[NUMCORES]; // records status of each core
163 bool transProfileRequestMsg(int targetcore);
164 void outputProfileData();
174 int main(int argc, char **argv) {
180 bool sendStall = false;
182 bool tocontinue = false;
183 struct QueueItem * objitem = NULL;
184 struct transObjInfo * objInfo = NULL;
186 bool allStall = true;
189 corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
191 // initialize the arrays
192 if(STARTUPCORE == corenum) {
193 // startup core to initialize corestatus[]
194 for(i = 0; i < NUMCORES; ++i) {
196 numsendobjs[i] = 0; // assume all variables in RAW are local variables! MAY BE WRONG!!!
197 numreceiveobjs[i] = 0;
202 for(i = 0; i < NUMCORES; ++i) {
203 profilestatus[i] = 1;
208 self_numsendobjs = 0;
209 self_numreceiveobjs = 0;
210 for(i = 0; i < 30; ++i) {
217 for(i = 0; i < 30; ++i) {
223 isMsgHanging = false;
224 isMsgSending = false;
226 // create the lock table, lockresult table and obj queue
228 locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
229 /* Set allocation blocks*/
230 locktable.listhead=NULL;
231 locktable.listtail=NULL;
233 locktable.numelements = 0;
241 objqueue.head = NULL;
242 objqueue.tail = NULL;
243 lockRedirectTbl = allocateRuntimeHash(20);
244 objRedirectLockTbl = allocateRuntimeHash(20);
248 //isInterrupt = true;
251 /*interruptInfoIndex = 0;
252 taskInfoOverflow = false;
253 interruptInfoOverflow = false;*/
257 if (corenum < NUMCORES) {
260 raw_user_interrupts_on();
264 #elif defined THREADSIMULATE
268 pthread_t threads[NUMCORES];
271 // initialize three arrays and msg queue array
272 char * pathhead = "/msgqueue_";
273 int targetlen = strlen(pathhead);
274 for(i = 0; i < NUMCORES; ++i) {
277 numreceiveobjs[i] = 0;
282 corenumstr[0] = i + '0';
283 corenumstr[1] = '\0';
286 corenumstr[1] = i %10 + '0';
287 corenumstr[0] = (i / 10) + '0';
288 corenumstr[2] = '\0';
291 printf("Error: i >= 100\n");
295 char path[targetlen + sourcelen + 1];
296 strcpy(path, pathhead);
297 strncat(path, corenumstr, sourcelen);
298 int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
299 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
301 mqd[i]= mq_open(path, oflags, omodes, NULL);
303 printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
306 printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
311 pthread_key_create(&key, NULL);
313 // create the lock table and initialize its mutex
314 locktbl = allocateRuntimeHash(20);
315 int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
316 printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
318 for(i = 0; i < NUMCORES; ++i) {
319 thread_data_array[i].corenum = i;
320 thread_data_array[i].argc = argc;
321 thread_data_array[i].argv = argv;
322 thread_data_array[i].numsendobjs = 0;
323 thread_data_array[i].numreceiveobjs = 0;
324 printf("[main] creating thread %d\n", i);
325 rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
327 printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
337 void run(void* arg) {
338 struct thread_data * my_tdata = (struct thread_data *)arg;
339 pthread_setspecific(key, (void *)my_tdata->corenum);
340 int argc = my_tdata->argc;
341 char** argv = my_tdata->argv;
342 printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
348 GC_init(); // Initialize the garbage collector
356 initializeexithandler();
357 /* Create table for failed tasks */
359 if(corenum > NUMCORES - 1) {
363 raw_test_pass(0xee01);
364 raw_test_pass_reg(taskInfoIndex);
365 raw_test_pass_reg(taskInfoOverflow);
366 if(!taskInfoOverflow) {
367 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
368 taskInfoArray[taskInfoIndex] = taskInfo;
369 taskInfo->taskName = "msg handling";
370 taskInfo->startTime = raw_get_cycle();
371 taskInfo->endTime = -1;
375 //isInterrupt = false;
382 /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
383 (int (*)(void *,void *)) &comparetpd);*/
385 /* Create queue of active tasks */
386 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
387 (int(*) (void *,void *)) &comparetpd);
389 /* Process task information */
392 if(STARTUPCORE == corenum) {
393 /* Create startup object */
394 createstartupobject(argc, argv);
399 raw_test_pass(0xee00);
403 // check if there are new active tasks can be executed
407 while(receiveObject() != -1) {
412 raw_test_pass(0xee01);
415 // check if there are some pending objects, if yes, enqueue them and executetasks again
419 bool isChecking = false;
420 if(!isEmpty(&objqueue)) {
421 if(!taskInfoOverflow) {
422 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
423 taskInfoArray[taskInfoIndex] = taskInfo;
424 taskInfo->taskName = "objqueue checking";
425 taskInfo->startTime = raw_get_cycle();
426 taskInfo->endTime = -1;
427 taskInfo->exitIndex = -1;
428 taskInfo->newObjs = NULL;
433 while(!isEmpty(&objqueue)) {
436 raw_user_interrupts_off();
439 //isInterrupt = false;
442 raw_test_pass(0xeee1);
446 objitem = getTail(&objqueue);
447 objInfo = (struct transObjInfo *)objitem->objectptr;
448 obj = objInfo->objptr;
450 raw_test_pass_reg((int)obj);
452 // grab lock and flush the obj
460 raw_test_pass_reg(grount);
475 raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
477 // enqueue the object
478 for(k = 0; k < objInfo->length; ++k) {
479 int taskindex = objInfo->queues[2 * k];
480 int paramindex = objInfo->queues[2 * k + 1];
481 struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
483 raw_test_pass_reg(taskindex);
484 raw_test_pass_reg(paramindex);
486 enqueueObject_I(obj, queues, 1);
488 removeItem(&objqueue, objitem);
489 releasewritelock_I(obj);
490 RUNFREE(objInfo->queues);
494 // put it at the end of the queue
495 // and try to execute active tasks already enqueued first
496 removeItem(&objqueue, objitem);
497 addNewItem_I(&objqueue, objInfo);
499 //isInterrupt = true;
502 raw_user_interrupts_on();
507 raw_user_interrupts_on();
511 if(isChecking && (!taskInfoOverflow)) {
512 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
514 if(taskInfoIndex == TASKINFOLENGTH) {
515 taskInfoOverflow = true;
521 raw_test_pass(0xee02);
526 if(STARTUPCORE == corenum) {
529 raw_test_pass(0xee03);
534 (waitconfirm && (numconfirm == 0))) {
536 raw_test_pass(0xee04);
539 raw_user_interrupts_off();
541 corestatus[corenum] = 0;
542 numsendobjs[corenum] = self_numsendobjs;
543 numreceiveobjs[corenum] = self_numreceiveobjs;
544 // check the status of all cores
547 raw_test_pass_reg(NUMCORES);
549 for(i = 0; i < NUMCORES; ++i) {
551 raw_test_pass(0xe000 + corestatus[i]);
553 if(corestatus[i] != 0) {
560 // the first time found all cores stall
561 // send out status confirm msg to all other cores
562 // reset the corestatus array too
564 raw_test_pass(0xee05);
566 corestatus[corenum] = 1;
567 for(i = 1; i < NUMCORES; ++i) {
569 transStatusConfirmMsg(i);
572 numconfirm = NUMCORES - 1;
574 // all the core status info are the latest
575 // check if the sum of send objs and receive obj are the same
576 // yes->terminate; for profiling mode, yes->send request to all
577 // other cores to pour out profiling data
578 // no->go on executing
580 raw_test_pass(0xee06);
583 for(i = 0; i < NUMCORES; ++i) {
584 sumsendobj += numsendobjs[i];
586 raw_test_pass(0xf000 + numsendobjs[i]);
589 for(i = 0; i < NUMCORES; ++i) {
590 sumsendobj -= numreceiveobjs[i];
592 raw_test_pass(0xf000 + numreceiveobjs[i]);
595 if(0 == sumsendobj) {
598 raw_test_pass(0xee07);
601 totalexetime = raw_get_cycle();
603 raw_test_pass(0xbbbbbbbb);
604 raw_test_pass(raw_get_cycle());
606 // profile mode, send msgs to other cores to request pouring
607 // out progiling data
610 // reopen gdn_avail interrupts
611 raw_user_interrupts_on();
613 for(i = 1; i < NUMCORES; ++i) {
614 transProfileRequestMsg(i);
616 // pour profiling data on startup core
620 raw_user_interrupts_off();
622 profilestatus[corenum] = 0;
623 // check the status of all cores
626 raw_test_pass_reg(NUMCORES);
628 for(i = 0; i < NUMCORES; ++i) {
630 raw_test_pass(0xe000 + profilestatus[i]);
632 if(profilestatus[i] != 0) {
640 raw_user_interrupts_on();
649 raw_test_done(1); // All done.
651 // still some objects on the fly on the network
652 // reset the waitconfirm and numconfirm
659 raw_user_interrupts_on();
665 raw_test_pass(0xee08);
671 // wait for some time
674 raw_test_pass(0xee09);
680 // send StallMsg to startup core
682 raw_test_pass(0xee0a);
684 sendStall = transStallMsg(STARTUPCORE);
695 raw_test_pass(0xee0b);
701 } // right-bracket for if-else of line 380
702 #elif defined THREADSIMULATE
703 /* Start executing the tasks */
707 // check if there are new objects coming
708 bool sendStall = false;
710 int numofcore = pthread_getspecific(key);
712 switch(receiveObject()) {
714 //printf("[run, %d] receive an object\n", numofcore);
716 // received an object
717 // check if there are new active tasks can be executed
723 //printf("[run, %d] no msg\n", numofcore);
725 if(STARTUPCORE == numofcore) {
726 corestatus[numofcore] = 0;
727 // check the status of all cores
728 bool allStall = true;
729 for(i = 0; i < NUMCORES; ++i) {
730 if(corestatus[i] != 0) {
736 // check if the sum of send objs and receive obj are the same
738 // no->go on executing
740 for(i = 0; i < NUMCORES; ++i) {
741 sumsendobj += numsendobjs[i];
743 for(i = 0; i < NUMCORES; ++i) {
744 sumsendobj -= numreceiveobjs[i];
746 if(0 == sumsendobj) {
750 int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
751 printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
752 struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
753 while(0 != RunhasNext(it_lock)) {
754 int key = Runkey(it_lock);
755 pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
756 int rc_des = pthread_rwlock_destroy(rwlock_obj);
757 printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
760 freeRuntimeHash(locktbl);
764 // destroy all message queues
765 char * pathhead = "/msgqueue_";
766 int targetlen = strlen(pathhead);
767 for(i = 0; i < NUMCORES; ++i) {
771 corenumstr[0] = i + '0';
772 corenumstr[1] = '\0';
775 corenumstr[1] = i %10 + '0';
776 corenumstr[0] = (i / 10) + '0';
777 corenumstr[2] = '\0';
780 printf("Error: i >= 100\n");
784 char path[targetlen + sourcelen + 1];
785 strcpy(path, pathhead);
786 strncat(path, corenumstr, sourcelen);
790 printf("[run, %d] terminate!\n", numofcore);
797 // send StallMsg to startup core
798 sendStall = transStallMsg(STARTUPCORE);
805 printf("[run, %d] receive a stall msg\n", numofcore);
806 // receive a Stall Msg, do nothing
807 assert(STARTUPCORE == numofcore); // only startup core can receive such msg
813 printf("[run, %d] Error: invalid message type.\n", numofcore);
823 void createstartupobject(int argc, char ** argv) {
826 /* Allocate startup object */
828 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
829 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
831 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
832 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
834 /* Build array of strings */
835 startupobject->___parameters___=stringarray;
836 for(i=1; i<argc; i++) {
837 int length=strlen(argv[i]);
839 struct ___String___ *newstring=NewString(NULL, argv[i],length);
841 struct ___String___ *newstring=NewString(argv[i],length);
843 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
846 startupobject->isolate = 1;
847 startupobject->version = 0;
848 startupobject->lock = NULL;
850 /* Set initialized flag for startup object */
851 flagorandinit(startupobject,1,0xFFFFFFFF);
852 enqueueObject(startupobject, NULL, 0);
854 raw_flush_entire_cache();
858 int hashCodetpd(struct taskparamdescriptor *ftd) {
859 int hash=(int)ftd->task;
861 for(i=0; i<ftd->numParameters; i++) {
862 hash^=(int)ftd->parameterArray[i];
867 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
869 if (ftd1->task!=ftd2->task)
871 for(i=0; i<ftd1->numParameters; i++)
872 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
877 /* This function sets a tag. */
879 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
881 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
883 struct ArrayObject * ao=NULL;
884 struct ___Object___ * tagptr=obj->___tags___;
886 obj->___tags___=(struct ___Object___ *)tagd;
888 /* Have to check if it is already set */
889 if (tagptr->type==TAGTYPE) {
890 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
895 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
896 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
897 obj=(struct ___Object___ *)ptrarray[2];
898 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
899 td=(struct ___TagDescriptor___ *) obj->___tags___;
901 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
903 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
904 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
905 obj->___tags___=(struct ___Object___ *) ao;
906 ao->___cachedCode___=2;
910 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
911 for(i=0; i<ao->___cachedCode___; i++) {
912 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
917 if (ao->___cachedCode___<ao->___length___) {
918 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
919 ao->___cachedCode___++;
922 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
923 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
924 obj=(struct ___Object___ *)ptrarray[2];
925 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
926 ao=(struct ArrayObject *)obj->___tags___;
928 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
930 aonew->___cachedCode___=ao->___length___+1;
931 for(i=0; i<ao->___length___; i++) {
932 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
934 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
940 struct ___Object___ * tagset=tagd->flagptr;
943 } else if (tagset->type!=OBJECTARRAYTYPE) {
945 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
946 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
947 obj=(struct ___Object___ *)ptrarray[2];
948 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
950 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
952 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
953 ARRAYSET(ao, struct ___Object___ *, 1, obj);
954 ao->___cachedCode___=2;
955 tagd->flagptr=(struct ___Object___ *)ao;
957 struct ArrayObject *ao=(struct ArrayObject *) tagset;
958 if (ao->___cachedCode___<ao->___length___) {
959 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
963 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
964 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
965 obj=(struct ___Object___ *)ptrarray[2];
966 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
967 ao=(struct ArrayObject *)tagd->flagptr;
969 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
971 aonew->___cachedCode___=ao->___cachedCode___+1;
972 for(i=0; i<ao->___length___; i++) {
973 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
975 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
976 tagd->flagptr=(struct ___Object___ *) aonew;
982 /* This function clears a tag. */
984 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
986 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
988 /* We'll assume that tag is alway there.
989 Need to statically check for this of course. */
990 struct ___Object___ * tagptr=obj->___tags___;
992 if (tagptr->type==TAGTYPE) {
993 if ((struct ___TagDescriptor___ *)tagptr==tagd)
994 obj->___tags___=NULL;
997 printf("ERROR 1 in tagclear\n");
1001 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1003 for(i=0; i<ao->___cachedCode___; i++) {
1004 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
1006 ao->___cachedCode___--;
1007 if (i<ao->___cachedCode___)
1008 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
1009 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
1010 if (ao->___cachedCode___==0)
1011 obj->___tags___=NULL;
1016 printf("ERROR 2 in tagclear\n");
1022 struct ___Object___ *tagset=tagd->flagptr;
1023 if (tagset->type!=OBJECTARRAYTYPE) {
1028 printf("ERROR 3 in tagclear\n");
1032 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1034 for(i=0; i<ao->___cachedCode___; i++) {
1035 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
1037 ao->___cachedCode___--;
1038 if (i<ao->___cachedCode___)
1039 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
1040 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
1041 if (ao->___cachedCode___==0)
1047 printf("ERROR 4 in tagclear\n");
1055 /* This function allocates a new tag. */
1057 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
1058 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
1060 struct ___TagDescriptor___ * allocate_tag(int index) {
1061 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
1070 /* This function updates the flag for object ptr. It or's the flag
1071 with the or mask and and's it with the andmask. */
1073 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
1075 int flagcomp(const int *val1, const int *val2) {
1076 return (*val1)-(*val2);
1079 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
1081 int oldflag=((int *)ptr)[1];
1082 int flag=ormask|oldflag;
1084 flagbody(ptr, flag, queues, length, false);
1088 bool intflagorand(void * ptr, int ormask, int andmask) {
1090 int oldflag=((int *)ptr)[1];
1091 int flag=ormask|oldflag;
1093 if (flag==oldflag) /* Don't do anything */
1096 flagbody(ptr, flag, NULL, 0, false);
1102 void flagorandinit(void * ptr, int ormask, int andmask) {
1103 int oldflag=((int *)ptr)[1];
1104 int flag=ormask|oldflag;
1106 flagbody(ptr,flag,NULL,0,true);
1109 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1110 struct parameterwrapper * flagptr = NULL;
1112 struct parameterwrapper ** queues = vqueues;
1113 int length = vlength;
1115 int UNUSED, UNUSED2;
1116 int * enterflags = NULL;
1117 if((!isnew) && (queues == NULL)) {
1118 #ifdef THREADSIMULATE
1119 int numofcore = pthread_getspecific(key);
1120 queues = objectqueues[numofcore][ptr->type];
1121 length = numqueues[numofcore][ptr->type];
1124 if(corenum < NUMCORES) {
1126 queues = objectqueues[corenum][ptr->type];
1127 length = numqueues[corenum][ptr->type];
1137 /*Remove object from all queues */
1138 for(i = 0; i < length; ++i) {
1139 flagptr = queues[i];
1140 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1141 ObjectHashremove(flagptr->objectset, (int)ptr);
1142 if (enterflags!=NULL)
1143 RUNFREE(enterflags);
1147 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1148 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1151 struct QueueItem *tmpptr;
1152 struct parameterwrapper * parameter=NULL;
1155 struct parameterwrapper * prevptr=NULL;
1156 struct ___Object___ *tagptr=NULL;
1157 struct parameterwrapper ** queues = vqueues;
1158 int length = vlength;
1160 if(corenum > NUMCORES - 1) {
1164 if(queues == NULL) {
1165 #ifdef THREADSIMULATE
1166 int numofcore = pthread_getspecific(key);
1167 queues = objectqueues[numofcore][ptr->type];
1168 length = numqueues[numofcore][ptr->type];
1170 queues = objectqueues[corenum][ptr->type];
1171 length = numqueues[corenum][ptr->type];
1174 tagptr=ptr->___tags___;
1176 /* Outer loop iterates through all parameter queues an object of
1177 this type could be in. */
1178 for(j = 0; j < length; ++j) {
1179 parameter = queues[j];
1181 if (parameter->numbertags>0) {
1183 goto nextloop; //that means the object has no tag but that param needs tag
1184 else if(tagptr->type==TAGTYPE) { //one tag
1185 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1186 for(i=0; i<parameter->numbertags; i++) {
1187 //slotid is parameter->tagarray[2*i];
1188 int tagid=parameter->tagarray[2*i+1];
1189 if (tagid!=tagptr->flag)
1190 goto nextloop; /*We don't have this tag */
1192 } else { //multiple tags
1193 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1194 for(i=0; i<parameter->numbertags; i++) {
1195 //slotid is parameter->tagarray[2*i];
1196 int tagid=parameter->tagarray[2*i+1];
1198 for(j=0; j<ao->___cachedCode___; j++) {
1199 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1210 for(i=0; i<parameter->numberofterms; i++) {
1211 int andmask=parameter->intarray[i*2];
1212 int checkmask=parameter->intarray[i*2+1];
1213 if ((ptr->flag&andmask)==checkmask) {
1214 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1226 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1227 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1230 struct QueueItem *tmpptr;
1231 struct parameterwrapper * parameter=NULL;
1234 struct parameterwrapper * prevptr=NULL;
1235 struct ___Object___ *tagptr=NULL;
1236 struct parameterwrapper ** queues = vqueues;
1237 int length = vlength;
1239 if(corenum > NUMCORES - 1) {
1243 if(queues == NULL) {
1244 #ifdef THREADSIMULATE
1245 int numofcore = pthread_getspecific(key);
1246 queues = objectqueues[numofcore][ptr->type];
1247 length = numqueues[numofcore][ptr->type];
1249 queues = objectqueues[corenum][ptr->type];
1250 length = numqueues[corenum][ptr->type];
1253 tagptr=ptr->___tags___;
1255 /* Outer loop iterates through all parameter queues an object of
1256 this type could be in. */
1257 for(j = 0; j < length; ++j) {
1258 parameter = queues[j];
1260 if (parameter->numbertags>0) {
1262 goto nextloop; //that means the object has no tag but that param needs tag
1263 else if(tagptr->type==TAGTYPE) { //one tag
1264 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1265 for(i=0; i<parameter->numbertags; i++) {
1266 //slotid is parameter->tagarray[2*i];
1267 int tagid=parameter->tagarray[2*i+1];
1268 if (tagid!=tagptr->flag) {
1269 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) {
1291 for(i=0; i<parameter->numberofterms; i++) {
1292 int andmask=parameter->intarray[i*2];
1293 int checkmask=parameter->intarray[i*2+1];
1294 if ((ptr->flag&andmask)==checkmask) {
1295 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1306 // helper function to compute the coordinates of a core from the core number
1307 void calCoords(int core_num, int* coordY, int* coordX) {
1308 *coordX = core_num % raw_get_array_size_x();
1309 *coordY = core_num / raw_get_array_size_x();
1313 int * getAliasLock(void ** ptrs, int length, struct RuntimeHash * tbl) {
1315 return (int*)(RUNMALLOC(sizeof(int)));
1320 bool redirect = false;
1321 int redirectlock = 0;
1322 for(; i < length; i++) {
1323 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1326 if(ptr->lock == NULL) {
1329 lock = (int)(ptr->lock);
1332 if(lock != redirectlock) {
1333 RuntimeHashadd(tbl, lock, redirectlock);
1336 if(RuntimeHashcontainskey(tbl, lock)) {
1337 // already redirected
1339 RuntimeHashget(tbl, lock, &redirectlock);
1340 for(; j < locklen; j++) {
1341 if(locks[j] != redirectlock) {
1342 RuntimeHashadd(tbl, locks[j], redirectlock);
1347 for(j = 0; j < locklen; j++) {
1348 if(locks[j] == lock) {
1351 } else if(locks[j] > lock) {
1358 locks[h] = locks[h-1];
1367 return (int *)redirectlock;
1369 return (int *)(locks[0]);
1374 void addAliasLock(void * ptr, int lock) {
1375 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1376 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1377 // originally no alias lock associated or have a different alias lock
1378 // flush it as the new one
1379 obj->lock = (int *)lock;
1383 /* Message format for RAW version:
1385 * type: 0 -- transfer object
1386 * 1 -- transfer stall msg
1391 * // add for profile info
1392 * 6 -- transfer profile output msg
1393 * 7 -- transfer profile output finish msg
1394 * // add for alias lock strategy
1395 * 8 -- redirect lock request
1396 * 9 -- lock grant with redirect info
1397 * a -- lock deny with redirect info
1398 * b -- lock release with redirect info
1399 * c -- status confirm request
1400 * d -- status report msg
1402 * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1403 * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1404 * LockMsg: 2 + lock type + obj pointer + lock + request core (size is always 5 * sizeof(int))
1405 * 3/4/5 + lock type + obj pointer + lock (size is always 4 * sizeof(int))
1406 * 8 + lock type + obj pointer + redirect lock + root request core + request core (size is always 6 * sizeof(int))
1407 * 9/a + lock type + obj pointer + redirect lock (size is always 4 * sizeof(int))
1408 * b + lock type + lock + redirect lock (size is always 4 * sizeof(int))
1409 * lock type: 0 -- read; 1 -- write
1410 * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
1411 * 7 + corenum (size is always 2 * sizeof(int))
1412 * StatusMsg: c (size is always 1 * sizeof(int))
1413 * d + status + corenum (size is always 3 * sizeof(int))
1414 * status: 0 -- stall; 1 -- busy
1417 // transfer an object to targetcore
1419 void transferObject(struct transObjInfo * transObj) {
1420 void * obj = transObj->objptr;
1421 int type=((int *)obj)[0];
1422 int size=classsize[type];
1423 int targetcore = transObj->targetcore;
1427 int self_y, self_x, target_y, target_x;
1428 // for 32 bit machine, the size of fixed part is always 3 words
1429 int msgsize = 3 + transObj->length * 2;
1432 struct ___Object___ * newobj = (struct ___Object___ *)obj;
1434 calCoords(corenum, &self_y, &self_x);
1435 calCoords(targetcore, &target_y, &target_x);
1436 isMsgSending = true;
1437 // Build the message header
1438 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1440 target_y, target_x);
1441 // start sending msg, set sand msg flag
1442 //isMsgSending = true;
1443 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1445 raw_test_pass(0xbbbb);
1446 raw_test_pass(0xb000 + targetcore); // targetcore
1454 raw_test_pass_reg(msgsize);
1458 raw_test_pass_reg(obj);
1460 for(i = 0; i < transObj->length; ++i) {
1461 int taskindex = transObj->queues[2*i];
1462 int paramindex = transObj->queues[2*i+1];
1463 gdn_send(taskindex);
1465 raw_test_pass_reg(taskindex);
1467 gdn_send(paramindex);
1469 raw_test_pass_reg(paramindex);
1473 raw_test_pass(0xffff);
1475 ++(self_numsendobjs);
1476 // end of sending this msg, set sand msg flag false
1477 isMsgSending = false;
1478 // check if there are pending msgs
1479 while(isMsgHanging) {
1480 // get the msg from outmsgdata[]
1481 // length + target + msg
1482 outmsgleft = outmsgdata[outmsgindex++];
1483 targetcore = outmsgdata[outmsgindex++];
1484 calCoords(targetcore, &target_y, &target_x);
1485 isMsgSending = true;
1486 // Build the message header
1487 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1489 target_y, target_x);
1490 //isMsgSending = true;
1493 raw_test_pass(0xbbbb);
1494 raw_test_pass(0xb000 + targetcore); // targetcore
1496 while(outmsgleft-- > 0) {
1497 gdn_send(outmsgdata[outmsgindex++]);
1499 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1503 raw_test_pass(0xffff);
1505 isMsgSending = false;
1507 raw_user_interrupts_off();
1509 // check if there are still msg hanging
1510 if(outmsgindex == outmsglast) {
1512 outmsgindex = outmsglast = 0;
1513 isMsgHanging = false;
1516 raw_user_interrupts_on();
1519 #elif defined THREADSIMULATE
1520 int numofcore = pthread_getspecific(key);
1522 // use POSIX message queue to transfer objects between cores
1526 if(targetcore < 10) {
1527 corenumstr[0] = targetcore + '0';
1528 corenumstr[1] = '\0';
1530 } else if(targetcore < 100) {
1531 corenumstr[1] = targetcore % 10 + '0';
1532 corenumstr[0] = (targetcore / 10) + '0';
1533 corenumstr[2] = '\0';
1536 printf("Error: targetcore >= 100\n");
1540 char * pathhead = "/msgqueue_";
1541 int targetlen = strlen(pathhead);
1542 char path[targetlen + sourcelen + 1];
1543 strcpy(path, pathhead);
1544 strncat(path, corenumstr, sourcelen);
1545 int oflags = O_WRONLY|O_NONBLOCK;
1546 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1547 mqdnum = mq_open(path, oflags, omodes, NULL);
1549 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1553 struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1554 memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1555 int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1556 memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1557 tmptransObj->queues = tmpqueue;
1558 struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1559 newobj->type = ((struct ___Object___ *)obj)->type;
1560 newobj->original = (struct ___Object___ *)tmptransObj;
1563 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1565 printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1569 if(numofcore == STARTUPCORE) {
1570 ++numsendobjs[numofcore];
1572 ++(thread_data_array[numofcore].numsendobjs);
1574 printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1578 // send terminate message to targetcore
1580 bool transStallMsg(int targetcore) {
1583 int self_y, self_x, target_y, target_x;
1584 // for 32 bit machine, the size is always 4 words
1585 //int msgsize = sizeof(int) * 4;
1588 calCoords(corenum, &self_y, &self_x);
1589 calCoords(targetcore, &target_y, &target_x);
1590 isMsgSending = true;
1591 // Build the message header
1592 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1594 target_y, target_x);
1595 // start sending msgs, set msg sending flag
1596 //isMsgSending = true;
1597 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1599 raw_test_pass(0xbbbb);
1600 raw_test_pass(0xb000 + targetcore); // targetcore
1608 raw_test_pass_reg(corenum);
1610 gdn_send(self_numsendobjs);
1612 raw_test_pass_reg(self_numsendobjs);
1614 gdn_send(self_numreceiveobjs);
1616 raw_test_pass_reg(self_numreceiveobjs);
1617 raw_test_pass(0xffff);
1619 // end of sending this msg, set sand msg flag false
1620 isMsgSending = false;
1621 // check if there are pending msgs
1622 while(isMsgHanging) {
1623 // get the msg from outmsgdata[]
1624 // length + target + msg
1625 outmsgleft = outmsgdata[outmsgindex++];
1626 targetcore = outmsgdata[outmsgindex++];
1627 calCoords(targetcore, &target_y, &target_x);
1628 isMsgSending = true;
1629 // Build the message header
1630 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1632 target_y, target_x);
1633 //isMsgSending = true;
1634 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1636 raw_test_pass(0xbbbb);
1637 raw_test_pass(0xb000 + targetcore); // targetcore
1639 while(outmsgleft-- > 0) {
1640 gdn_send(outmsgdata[outmsgindex++]);
1642 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1646 raw_test_pass(0xffff);
1648 isMsgSending = false;
1650 raw_user_interrupts_off();
1652 // check if there are still msg hanging
1653 if(outmsgindex == outmsglast) {
1655 outmsgindex = outmsglast = 0;
1656 isMsgHanging = false;
1659 raw_user_interrupts_on();
1663 #elif defined THREADSIMULATE
1664 struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1665 // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1667 int numofcore = pthread_getspecific(key);
1668 newobj->flag = numofcore;
1669 newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1670 newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1672 // use POSIX message queue to send stall msg to startup core
1673 assert(targetcore == STARTUPCORE);
1677 if(targetcore < 10) {
1678 corenumstr[0] = targetcore + '0';
1679 corenumstr[1] = '\0';
1681 } else if(targetcore < 100) {
1682 corenumstr[1] = targetcore % 10 + '0';
1683 corenumstr[0] = (targetcore / 10) + '0';
1684 corenumstr[2] = '\0';
1687 printf("Error: targetcore >= 100\n");
1691 char * pathhead = "/msgqueue_";
1692 int targetlen = strlen(pathhead);
1693 char path[targetlen + sourcelen + 1];
1694 strcpy(path, pathhead);
1695 strncat(path, corenumstr, sourcelen);
1696 int oflags = O_WRONLY|O_NONBLOCK;
1697 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1698 mqdnum = mq_open(path, oflags, omodes, NULL);
1700 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1705 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1707 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1711 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1712 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1719 void transStatusConfirmMsg(int targetcore) {
1722 int self_y, self_x, target_y, target_x;
1723 // for 32 bit machine, the size is always 1 words
1724 //int msgsize = sizeof(int) * 1;
1727 calCoords(corenum, &self_y, &self_x);
1728 calCoords(targetcore, &target_y, &target_x);
1729 isMsgSending = true;
1730 // Build the message header
1731 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1733 target_y, target_x);
1734 // start sending msgs, set msg sending flag
1735 //isMsgSending = true;
1736 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1738 raw_test_pass(0xbbbb);
1739 raw_test_pass(0xb000 + targetcore); // targetcore
1744 raw_test_pass(0xffff);
1746 // end of sending this msg, set sand msg flag false
1747 isMsgSending = false;
1748 // check if there are pending msgs
1749 while(isMsgHanging) {
1750 // get the msg from outmsgdata[]
1751 // length + target + msg
1752 outmsgleft = outmsgdata[outmsgindex++];
1753 targetcore = outmsgdata[outmsgindex++];
1754 calCoords(targetcore, &target_y, &target_x);
1755 isMsgSending = true;
1756 // Build the message header
1757 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1759 target_y, target_x);
1760 //isMsgSending = true;
1761 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1763 raw_test_pass(0xbbbb);
1764 raw_test_pass(0xb000 + targetcore); // targetcore
1766 while(outmsgleft-- > 0) {
1767 gdn_send(outmsgdata[outmsgindex++]);
1769 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1773 raw_test_pass(0xffff);
1775 isMsgSending = false;
1777 raw_user_interrupts_off();
1779 // check if there are still msg hanging
1780 if(outmsgindex == outmsglast) {
1782 outmsgindex = outmsglast = 0;
1783 isMsgHanging = false;
1786 raw_user_interrupts_on();
1789 #elif defined THREADSIMULATE
1795 // send profile request message to targetcore
1797 bool transProfileRequestMsg(int targetcore) {
1799 int self_y, self_x, target_y, target_x;
1800 // for 32 bit machine, the size is always 4 words
1803 calCoords(corenum, &self_y, &self_x);
1804 calCoords(targetcore, &target_y, &target_x);
1805 isMsgSending = true;
1806 // Build the message header
1807 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1809 target_y, target_x);
1810 // start sending msgs, set msg sending flag
1811 //isMsgSending = true;
1812 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1814 raw_test_pass(0xbbbb);
1815 raw_test_pass(0xb000 + targetcore); // targetcore
1821 gdn_send(totalexetime);
1823 raw_test_pass_reg(totalexetime);
1824 raw_test_pass(0xffff);
1826 // end of sending this msg, set sand msg flag false
1827 isMsgSending = false;
1828 // check if there are pending msgs
1829 while(isMsgHanging) {
1830 // get the msg from outmsgdata[]
1831 // length + target + msg
1832 outmsgleft = outmsgdata[outmsgindex++];
1833 targetcore = outmsgdata[outmsgindex++];
1834 calCoords(targetcore, &target_y, &target_x);
1835 isMsgSending = true;
1836 // Build the message header
1837 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1839 target_y, target_x);
1840 //isMsgSending = true;
1843 raw_test_pass(0xbbbb);
1844 raw_test_pass(0xb000 + targetcore); // targetcore
1846 while(outmsgleft-- > 0) {
1847 gdn_send(outmsgdata[outmsgindex++]);
1849 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1853 raw_test_pass(0xffff);
1855 isMsgSending = false;
1857 raw_user_interrupts_off();
1859 // check if there are still msg hanging
1860 if(outmsgindex == outmsglast) {
1862 outmsgindex = outmsglast = 0;
1863 isMsgHanging = false;
1866 raw_user_interrupts_on();
1872 // output the profiling data
1873 void outputProfileData() {
1880 int totaltasktime = 0;
1881 int preprocessingtime = 0;
1882 int objqueuecheckingtime = 0;
1883 int postprocessingtime = 0;
1884 //int interruptiontime = 0;
1886 int averagetasktime = 0;
1889 for(i = 0; i < 50; i++) {
1893 calCoords(corenum, &self_y, &self_x);
1894 c_y = (char)self_y + '0';
1895 c_x = (char)self_x + '0';
1896 strcat(fn, "profile_");
1902 if((fp = fopen(fn, "w+")) == NULL) {
1903 fprintf(stderr, "fopen error\n");
1907 fprintf(fp, "Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
1908 // output task related info
1909 for(i = 0; i < taskInfoIndex; i++) {
1910 TaskInfo* tmpTInfo = taskInfoArray[i];
1911 int duration = tmpTInfo->endTime - tmpTInfo->startTime;
1912 fprintf(fp, "%s, %d, %d, %d, %d", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration, tmpTInfo->exitIndex);
1913 // summarize new obj info
1914 if(tmpTInfo->newObjs != NULL) {
1915 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
1916 struct RuntimeIterator * iter = NULL;
1917 while(0 == isEmpty(tmpTInfo->newObjs)) {
1918 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
1919 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
1921 RuntimeHashget(nobjtbl, (int)objtype, &num);
1922 RuntimeHashremovekey(nobjtbl, (int)objtype);
1924 RuntimeHashadd(nobjtbl, (int)objtype, num);
1926 RuntimeHashadd(nobjtbl, (int)objtype, 1);
1928 //fprintf(stderr, "new obj!\n");
1931 // output all new obj info
1932 iter = RuntimeHashcreateiterator(nobjtbl);
1933 while(RunhasNext(iter)) {
1934 char * objtype = (char *)Runkey(iter);
1935 int num = Runnext(iter);
1936 fprintf(fp, ", %s, %d", objtype, num);
1940 if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
1941 preprocessingtime += duration;
1942 } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
1943 postprocessingtime += duration;
1944 } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
1945 objqueuecheckingtime += duration;
1947 totaltasktime += duration;
1948 averagetasktime += duration;
1953 if(taskInfoOverflow) {
1954 fprintf(stderr, "Caution: task info overflow!\n");
1957 other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
1958 averagetasktime /= tasknum;
1960 fprintf(fp, "\nTotal time: %d\n", totalexetime);
1961 fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
1962 fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
1963 fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
1964 fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
1965 fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
1967 fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
1974 raw_test_pass(0xdddd);
1975 // output task related info
1976 for(i= 0; i < taskInfoIndex; i++) {
1977 TaskInfo* tmpTInfo = taskInfoArray[i];
1978 char* tmpName = tmpTInfo->taskName;
1979 int nameLen = strlen(tmpName);
1980 raw_test_pass(0xddda);
1981 for(j = 0; j < nameLen; j++) {
1982 raw_test_pass_reg(tmpName[j]);
1984 raw_test_pass(0xdddb);
1985 raw_test_pass_reg(tmpTInfo->startTime);
1986 raw_test_pass_reg(tmpTInfo->endTime);
1987 raw_test_pass_reg(tmpTInfo->exitIndex);
1988 if(tmpTInfo->newObjs != NULL) {
1989 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
1990 struct RuntimeIterator * iter = NULL;
1991 while(0 == isEmpty(tmpTInfo->newObjs)) {
1992 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
1993 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
1995 RuntimeHashget(nobjtbl, (int)objtype, &num);
1996 RuntimeHashremovekey(nobjtbl, (int)objtype);
1998 RuntimeHashadd(nobjtbl, (int)objtype, num);
2000 RuntimeHashadd(nobjtbl, (int)objtype, 1);
2004 // ouput all new obj info
2005 iter = RuntimeHashcreateiterator(nobjtbl);
2006 while(RunhasNext(iter)) {
2007 char * objtype = (char *)Runkey(iter);
2008 int num = Runnext(iter);
2009 int nameLen = strlen(objtype);
2010 raw_test_pass(0xddda);
2011 for(j = 0; j < nameLen; j++) {
2012 raw_test_pass_reg(objtype[j]);
2014 raw_test_pass(0xdddb);
2015 raw_test_pass_reg(num);
2018 raw_test_pass(0xdddc);
2021 if(taskInfoOverflow) {
2022 raw_test_pass(0xefee);
2025 // output interrupt related info
2026 /*for(i = 0; i < interruptInfoIndex; i++) {
2027 InterruptInfo* tmpIInfo = interruptInfoArray[i];
2028 raw_test_pass(0xddde);
2029 raw_test_pass_reg(tmpIInfo->startTime);
2030 raw_test_pass_reg(tmpIInfo->endTime);
2031 raw_test_pass(0xdddf);
2034 if(interruptInfoOverflow) {
2035 raw_test_pass(0xefef);
2038 raw_test_pass(0xeeee);
2042 inline void setTaskExitIndex(int index) {
2043 taskInfoArray[taskInfoIndex]->exitIndex = index;
2046 inline void addNewObjInfo(void * nobj) {
2047 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
2048 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
2050 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
2054 // receive object transferred from other cores
2055 // or the terminate message from other cores
2056 // NOTICE: following format is for threadsimulate version only
2057 // RAW version please see previous description
2058 // format: type + object
2059 // type: -1--stall msg
2061 // return value: 0--received an object
2062 // 1--received nothing
2063 // 2--received a Stall Msg
2064 // 3--received a lock Msg
2065 // RAW version: -1 -- received nothing
2066 // otherwise -- received msg type
2067 int receiveObject() {
2071 int self_y, self_x, target_y, target_x;
2073 if(gdn_input_avail() == 0) {
2075 if(corenum < NUMCORES) {
2076 raw_test_pass(0xd001);
2082 /*if(isInterrupt && (!interruptInfoOverflow)) {
2083 // raw_test_pass(0xffff);
2084 interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
2085 interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
2086 interruptInfoArray[interruptInfoIndex]->endTime = -1;
2091 raw_test_pass(0xcccc);
2093 while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
2094 msgdata[msgdataindex] = gdn_receive();
2095 if(msgdataindex == 0) {
2096 if(msgdata[0] > 0xc) {
2098 } else if (msgdata[0] == 0xc) {
2100 } else if(msgdata[0] > 8) {
2102 } else if(msgdata[0] == 8) {
2104 } else if(msgdata[0] > 5) {
2106 } else if (msgdata[0] > 2) {
2108 } else if (msgdata[0] == 2) {
2110 } else if (msgdata[0] > 0) {
2113 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
2114 msglength = msgdata[msgdataindex];
2117 raw_test_pass_reg(msgdata[msgdataindex]);
2122 raw_test_pass(0xffff);
2124 if(msgdataindex == msglength) {
2125 // received a whole msg
2126 int type, data1; // will receive at least 2 words including type
2131 // receive a object transfer msg
2132 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
2135 raw_test_pass(0xe880);
2137 if(corenum > NUMCORES - 1) {
2138 raw_test_pass_reg(msgdata[2]);
2139 raw_test_done(0xa001);
2140 } else if((corenum == STARTUPCORE) && waitconfirm) {
2141 waitconfirm = false;
2144 // store the object and its corresponding queue info, enqueue it later
2145 transObj->objptr = (void *)msgdata[2]; // data1 is now size of the msg
2146 transObj->length = (msglength - 3) / 2;
2147 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
2148 for(k = 0; k < transObj->length; ++k) {
2149 transObj->queues[2*k] = msgdata[3+2*k];
2151 raw_test_pass_reg(transObj->queues[2*k]);
2153 transObj->queues[2*k+1] = msgdata[3+2*k+1];
2155 raw_test_pass_reg(transObj->queues[2*k+1]);
2158 // check if there is an existing duplicate item
2160 struct QueueItem * qitem = getTail(&objqueue);
2161 struct QueueItem * prev = NULL;
2162 while(qitem != NULL) {
2163 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
2164 if(tmpinfo->objptr == transObj->objptr) {
2165 // the same object, remove outdate one
2166 removeItem(&objqueue, qitem);
2171 qitem = getTail(&objqueue);
2173 qitem = getNextQueueItem(prev);
2176 addNewItem_I(&objqueue, (void *)transObj);
2178 ++(self_numreceiveobjs);
2183 // receive a stall msg
2184 if(corenum != STARTUPCORE) {
2185 // non startup core can not receive stall msg
2187 raw_test_pass_reg(data1);
2188 raw_test_done(0xa002);
2189 } else if(waitconfirm) {
2190 waitconfirm = false;
2193 if(data1 < NUMCORES) {
2195 raw_test_pass(0xe881);
2197 corestatus[data1] = 0;
2198 numsendobjs[data1] = msgdata[2];
2199 numreceiveobjs[data1] = msgdata[3];
2205 // receive lock request msg
2206 // for 32 bit machine, the size is always 4 words
2207 //int msgsize = sizeof(int) * 4;
2209 // lock request msg, handle it right now
2210 // check to see if there is a lock exist in locktbl for the required obj
2211 // data1 -> lock type
2212 int data2 = msgdata[2]; // obj pointer
2213 int data3 = msgdata[3]; // lock
2214 int data4 = msgdata[4]; // request core
2216 if( ((data3 >> 5) % TOTALCORE) != corenum ) {
2217 // the lock should not be on this core
2218 raw_test_pass_reg(data4);
2219 raw_test_done(0xa003);
2221 if((corenum == STARTUPCORE) && waitconfirm) {
2222 waitconfirm = false;
2225 if(!RuntimeHashcontainskey(locktbl, data3)) {
2226 // no locks for this object
2227 // first time to operate on this shared object
2228 // create a lock for it
2229 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2230 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2231 lockvalue->redirectlock = 0;
2233 raw_test_pass(0xe882);
2236 lockvalue->value = 1;
2238 lockvalue->value = -1;
2240 RuntimeHashadd_I(locktbl, data3, (int)lockvalue);
2243 struct LockValue * lockvalue = NULL;
2245 raw_test_pass(0xe883);
2247 RuntimeHashget(locktbl, data3, &rwlock_obj);
2248 lockvalue = (struct LockValue *)(rwlock_obj);
2250 raw_test_pass_reg(lockvalue->redirectlock);
2252 if(lockvalue->redirectlock != 0) {
2253 // this lock is redirected
2255 raw_test_pass(0xe884);
2258 getreadlock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2260 getwritelock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2265 raw_test_pass_reg(lockvalue->value);
2267 if(0 == lockvalue->value) {
2269 lockvalue->value = 1;
2271 lockvalue->value = -1;
2273 } else if((lockvalue->value > 0) && (data1 == 0)) {
2274 // read lock request and there are only read locks
2280 raw_test_pass_reg(lockvalue->value);
2285 // check if there is still some msg on sending
2288 raw_test_pass(0xe885);
2290 isMsgHanging = true;
2291 // cache the msg in outmsgdata and send it later
2292 // msglength + target core + msg
2293 outmsgdata[outmsglast++] = msgsize;
2294 outmsgdata[outmsglast++] = targetcore;
2296 outmsgdata[outmsglast++] = 4;
2298 outmsgdata[outmsglast++] = 3;
2300 outmsgdata[outmsglast++] = data1;
2301 outmsgdata[outmsglast++] = data2;
2302 outmsgdata[outmsglast++] = data3;
2305 raw_test_pass(0xe886);
2307 // no msg on sending, send it out
2308 calCoords(corenum, &self_y, &self_x);
2309 calCoords(targetcore, &target_y, &target_x);
2310 // Build the message header
2311 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2313 target_y, target_x);
2314 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2316 raw_test_pass(0xbbbb);
2317 raw_test_pass(0xb000 + targetcore); // targetcore
2320 // deny the lock request
2321 gdn_send(4); // lock request
2326 // grount the lock request
2327 gdn_send(3); // lock request
2332 gdn_send(data1); // lock type
2334 raw_test_pass_reg(data1);
2336 gdn_send(data2); // obj pointer
2338 raw_test_pass_reg(data2);
2340 gdn_send(data3); // lock
2342 raw_test_pass_reg(data3);
2343 raw_test_pass(0xffff);
2350 // receive lock grount msg
2351 if(corenum > NUMCORES - 1) {
2352 raw_test_pass_reg(msgdata[2]);
2353 raw_test_done(0xa004);
2354 } else if((corenum == STARTUPCORE) && waitconfirm) {
2355 waitconfirm = false;
2358 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
2360 raw_test_pass(0xe887);
2368 // conflicts on lockresults
2369 raw_test_pass_reg(msgdata[2]);
2370 raw_test_done(0xa005);
2376 // receive lock grount/deny msg
2377 if(corenum > NUMCORES - 1) {
2378 raw_test_pass_reg(msgdata[2]);
2379 raw_test_done(0xa006);
2380 } else if((corenum == STARTUPCORE) && waitconfirm) {
2381 waitconfirm = false;
2384 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
2386 raw_test_pass(0xe888);
2394 // conflicts on lockresults
2395 raw_test_pass_reg(msgdata[2]);
2396 raw_test_done(0xa007);
2402 // receive lock release msg
2403 if((corenum == STARTUPCORE) && waitconfirm) {
2404 waitconfirm = false;
2407 if(!RuntimeHashcontainskey(locktbl, msgdata[3])) {
2408 // no locks for this object, something is wrong
2409 raw_test_pass_reg(msgdata[3]);
2410 raw_test_done(0xa008);
2413 struct LockValue * lockvalue = NULL;
2414 RuntimeHashget(locktbl, msgdata[3], &rwlock_obj);
2415 lockvalue = (struct LockValue*)(rwlock_obj);
2417 raw_test_pass(0xe889);
2418 raw_test_pass_reg(lockvalue->value);
2426 raw_test_pass_reg(lockvalue->value);
2434 // receive an output request msg
2435 if(corenum == STARTUPCORE) {
2436 // startup core can not receive profile output finish msg
2437 raw_test_done(0xa009);
2440 raw_test_pass(0xe88a);
2445 totalexetime = data1;
2446 outputProfileData();
2447 /*if(data1 >= NUMCORES) {
2448 raw_test_pass_reg(taskInfoIndex);
2449 raw_test_pass_reg(taskInfoOverflow);
2450 if(!taskInfoOverflow) {
2451 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
2453 if(taskInfoIndex == TASKINFOLENGTH) {
2454 taskInfoOverflow = true;
2458 // no msg on sending, send it out
2459 targetcore = STARTUPCORE;
2460 calCoords(corenum, &self_y, &self_x);
2461 calCoords(targetcore, &target_y, &target_x);
2462 // Build the message header
2463 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2465 target_y, target_x);
2468 raw_test_pass(0xbbbb);
2469 raw_test_pass(0xb000 + targetcore); // targetcore
2477 raw_test_pass_reg(corenum);
2478 raw_test_pass(0xffff);
2485 // receive a profile output finish msg
2486 if(corenum != STARTUPCORE) {
2487 // non startup core can not receive profile output finish msg
2488 raw_test_pass_reg(data1);
2489 raw_test_done(0xa00a);
2492 raw_test_pass(0xe88b);
2494 profilestatus[data1] = 0;
2500 // receive a redirect lock request msg
2501 // for 32 bit machine, the size is always 4 words
2502 //int msgsize = sizeof(int) * 4;
2504 // lock request msg, handle it right now
2505 // check to see if there is a lock exist in locktbl for the required obj
2506 // data1 -> lock type
2507 int data2 = msgdata[2]; // obj pointer
2508 int data3 = msgdata[3]; // redirect lock
2509 int data4 = msgdata[4]; // root request core
2510 int data5 = msgdata[5]; // request core
2511 if( ((data3 >> 5) % TOTALCORE) != corenum ) {
2512 // the lock should not be on this core
2513 raw_test_pass_reg(data5);
2514 raw_test_done(0xa00b);
2515 } if((corenum == STARTUPCORE) && waitconfirm) {
2516 waitconfirm = false;
2520 if(!RuntimeHashcontainskey(locktbl, data3)) {
2521 // no locks for this object
2522 // first time to operate on this shared object
2523 // create a lock for it
2524 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2525 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2526 lockvalue->redirectlock = 0;
2528 raw_test_pass(0xe88c);
2531 lockvalue->value = 1;
2533 lockvalue->value = -1;
2535 RuntimeHashadd_I(locktbl, data3, (int)lockvalue);
2538 struct LockValue * lockvalue = NULL;
2540 raw_test_pass(0xe88d);
2542 RuntimeHashget(locktbl, data3, &rwlock_obj);
2543 lockvalue = (struct LockValue *)(rwlock_obj);
2545 raw_test_pass_reg(lockvalue->redirectlock);
2547 if(lockvalue->redirectlock != 0) {
2548 // this lock is redirected
2550 raw_test_pass(0xe88e);
2553 getreadlock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2555 getwritelock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2560 raw_test_pass_reg(lockvalue->value);
2562 if(0 == lockvalue->value) {
2564 lockvalue->value = 1;
2566 lockvalue->value = -1;
2568 } else if((lockvalue->value > 0) && (data1 == 0)) {
2569 // read lock request and there are only read locks
2575 raw_test_pass_reg(lockvalue->value);
2580 // check if there is still some msg on sending
2583 raw_test_pass(0xe88f);
2585 isMsgHanging = true;
2586 // cache the msg in outmsgdata and send it later
2587 // msglength + target core + msg
2588 outmsgdata[outmsglast++] = msgsize;
2589 outmsgdata[outmsglast++] = targetcore;
2591 outmsgdata[outmsglast++] = 0xa;
2593 outmsgdata[outmsglast++] = 9;
2595 outmsgdata[outmsglast++] = data1;
2596 outmsgdata[outmsglast++] = data2;
2597 outmsgdata[outmsglast++] = data3;
2600 raw_test_pass(0xe890);
2602 // no msg on sending, send it out
2603 calCoords(corenum, &self_y, &self_x);
2604 calCoords(targetcore, &target_y, &target_x);
2605 // Build the message header
2606 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2608 target_y, target_x);
2609 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2611 raw_test_pass(0xbbbb);
2612 raw_test_pass(0xb000 + targetcore); // targetcore
2615 // deny the lock request
2616 gdn_send(0xa); // lock request
2621 // grount the lock request
2622 gdn_send(9); // lock request
2627 gdn_send(data1); // lock type
2629 raw_test_pass_reg(data1);
2631 gdn_send(data2); // obj pointer
2633 raw_test_pass_reg(data2);
2635 gdn_send(data3); // lock
2637 raw_test_pass_reg(data3);
2638 raw_test_pass(0xffff);
2645 // receive a lock grant msg with redirect info
2646 if(corenum > NUMCORES - 1) {
2647 raw_test_pass_reg(msgdata[2]);
2648 raw_test_done(0xa00c);
2649 } if((corenum == STARTUPCORE) && waitconfirm) {
2650 waitconfirm = false;
2653 if(lockobj == msgdata[2]) {
2655 raw_test_pass(0xe891);
2659 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
2664 // conflicts on lockresults
2665 raw_test_pass_reg(msgdata[2]);
2666 raw_test_done(0xa00d);
2672 // receive a lock deny msg with redirect info
2673 if(corenum > NUMCORES - 1) {
2674 raw_test_pass_reg(msgdata[2]);
2675 raw_test_done(0xa00e);
2676 } if((corenum == STARTUPCORE) && waitconfirm) {
2677 waitconfirm = false;
2680 if(lockobj == msgdata[2]) {
2682 raw_test_pass(0xe892);
2686 //RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
2691 // conflicts on lockresults
2692 raw_test_pass_reg(msgdata[2]);
2693 raw_test_done(0xa00f);
2699 // receive a lock release msg with redirect info
2700 if((corenum == STARTUPCORE) && waitconfirm) {
2701 waitconfirm = false;
2704 if(!RuntimeHashcontainskey(locktbl, msgdata[2])) {
2705 // no locks for this object, something is wrong
2706 raw_test_pass_reg(msgdata[2]);
2707 raw_test_done(0xa010);
2710 struct LockValue * lockvalue = NULL;
2711 RuntimeHashget(locktbl, msgdata[2], &rwlock_obj);
2712 lockvalue = (struct LockValue*)(rwlock_obj);
2714 raw_test_pass(0xe893);
2715 raw_test_pass_reg(lockvalue->value);
2723 raw_test_pass_reg(lockvalue->value);
2725 lockvalue->redirectlock = msgdata[3];
2731 // receive a status confirm info
2732 if((corenum == STARTUPCORE) || (corenum > NUMCORES - 1)) {
2733 // wrong core to receive such msg
2734 raw_test_done(0xa011);
2737 int targetcore = STARTUPCORE;
2739 raw_test_pass(0xe888);
2741 // check if there is still some msg on sending
2744 raw_test_pass(0xe888);
2746 isMsgHanging = true;
2747 // cache the msg in outmsgdata and send it later
2748 // msglength + target core + msg
2749 outmsgdata[outmsglast++] = msgsize;
2750 outmsgdata[outmsglast++] = targetcore;
2751 outmsgdata[outmsglast++] = 0xd;
2753 outmsgdata[outmsglast++] = 1;
2755 outmsgdata[outmsglast++] = 0;
2757 outmsgdata[outmsglast++] = corenum;
2760 raw_test_pass(0xe888);
2762 // no msg on sending, send it out
2763 calCoords(corenum, &self_y, &self_x);
2764 calCoords(targetcore, &target_y, &target_x);
2765 // Build the message header
2766 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2768 target_y, target_x);
2771 raw_test_pass(0xbbbb);
2772 raw_test_pass(0xb000 + targetcore);
2774 gdn_send(0xd); // status report
2778 if(busystatus == true) {
2791 gdn_send(corenum); // corenum
2793 raw_test_pass_reg(corenum);
2794 raw_test_pass(0xffff);
2802 // receive a status confirm info
2803 if(corenum != STARTUPCORE) {
2804 // wrong core to receive such msg
2805 raw_test_pass_reg(msgdata[2]);
2806 raw_test_done(0xa012);
2809 raw_test_pass(0xe888);
2814 corestatus[msgdata[2]] = msgdata[1];
2822 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
2823 msgdata[msgdataindex] = -1;
2828 raw_test_pass(0xe894);
2830 if(gdn_input_avail() != 0) {
2834 /* if(isInterrupt && (!interruptInfoOverflow)) {
2835 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2836 interruptInfoIndex++;
2837 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2838 interruptInfoOverflow = true;
2846 raw_test_pass(0xe895);
2849 /* if(isInterrupt && (!interruptInfoOverflow)) {
2850 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2851 interruptInfoIndex++;
2852 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2853 interruptInfoOverflow = true;
2859 #elif defined THREADSIMULATE
2860 int numofcore = pthread_getspecific(key);
2861 // use POSIX message queue to transfer object
2863 struct mq_attr mqattr;
2864 mq_getattr(mqd[numofcore], &mqattr);
2865 void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
2866 msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
2872 //printf("msg: %s\n",msgptr);
2873 if(((int*)msgptr)[0] == -1) {
2875 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2876 int index = tmpptr->flag;
2877 corestatus[index] = 0;
2878 numsendobjs[index] = tmpptr->___cachedHash___;
2879 numreceiveobjs[index] = tmpptr->___cachedCode___;
2880 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
2885 if(numofcore == STARTUPCORE) {
2886 ++(numreceiveobjs[numofcore]);
2888 ++(thread_data_array[numofcore].numreceiveobjs);
2890 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2891 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
2892 tmpptr = (struct ___Object___ *)(transObj->objptr);
2893 int type = tmpptr->type;
2894 int size=classsize[type];
2895 struct ___Object___ * newobj=RUNMALLOC(size);
2896 memcpy(newobj, tmpptr, size);
2897 if(0 == newobj->isolate) {
2898 newobj->original=tmpptr;
2903 for(k = 0; k < transObj->length; ++k) {
2904 int taskindex = transObj->queues[2 * k];
2905 int paramindex = transObj->queues[2 * k + 1];
2906 struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2907 enqueueObject(newobj, queues, 1);
2909 RUNFREE(transObj->queues);
2916 bool getreadlock(void * ptr) {
2919 int self_y, self_x, target_y, target_x;
2921 // for 32 bit machine, the size is always 5 words
2925 if(((struct ___Object___ *)ptr)->lock == NULL) {
2926 lock2require = lockobj;
2928 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
2930 targetcore = (lock2require >> 5) % TOTALCORE;
2937 if(targetcore == corenum) {
2938 // reside on this core
2941 raw_user_interrupts_off();
2943 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
2944 // no locks for this object
2945 // first time to operate on this shared object
2946 // create a lock for it
2947 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2948 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2949 lockvalue->redirectlock = 0;
2950 lockvalue->value = 1;
2951 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
2954 struct LockValue* lockvalue;
2955 RuntimeHashget(locktbl, lock2require, &rwlock_obj);
2956 lockvalue = (struct LockValue*)rwlock_obj;
2957 if(lockvalue->redirectlock != 0) {
2958 // the lock is redirected
2959 getreadlock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
2962 if(-1 != lockvalue->value) {
2970 raw_user_interrupts_on();
2972 if(lockobj == (int)ptr) {
2983 // conflicts on lockresults
2984 raw_test_done(0xa013);
2989 calCoords(corenum, &self_y, &self_x);
2990 calCoords(targetcore, &target_y, &target_x);
2991 isMsgSending = true;
2992 // Build the message header
2993 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2995 target_y, target_x);
2996 // start sending the msg, set send msg flag
2997 //isMsgSending = true;
2998 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3000 raw_test_pass(0xbbbb);
3001 raw_test_pass(0xb000 + targetcore); // targetcore
3003 gdn_send(2); // lock request
3007 gdn_send(0); // read lock
3011 gdn_send((int)ptr); // obj pointer
3013 raw_test_pass_reg(ptr);
3015 gdn_send(lock2require); // lock
3017 raw_test_pass_reg(lock2require);
3019 gdn_send(corenum); // request core
3021 raw_test_pass_reg(corenum);
3022 raw_test_pass(0xffff);
3024 // end of sending this msg, set sand msg flag false
3025 isMsgSending = false;
3026 // check if there are pending msgs
3027 while(isMsgHanging) {
3028 // get the msg from outmsgdata[]
3029 // length + target + msg
3030 outmsgleft = outmsgdata[outmsgindex++];
3031 targetcore = outmsgdata[outmsgindex++];
3032 calCoords(targetcore, &target_y, &target_x);
3033 isMsgSending = true;
3034 // Build the message header
3035 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3037 target_y, target_x);
3038 //isMsgSending = true;
3039 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3041 raw_test_pass(0xbbbb);
3042 raw_test_pass(0xb000 + targetcore); // targetcore
3044 while(outmsgleft-- > 0) {
3045 gdn_send(outmsgdata[outmsgindex++]);
3047 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3051 raw_test_pass(0xffff);
3053 isMsgSending = false;
3055 raw_user_interrupts_off();
3057 // check if there are still msg hanging
3058 if(outmsgindex == outmsglast) {
3060 outmsgindex = outmsglast = 0;
3061 isMsgHanging = false;
3064 raw_user_interrupts_on();
3068 #elif defined THREADSIMULATE
3069 // TODO : need modification for alias lock
3070 int numofcore = pthread_getspecific(key);
3072 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3073 printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3077 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3078 // no locks for this object
3079 // first time to operate on this shared object
3080 // create a lock for it
3081 rc = pthread_rwlock_unlock(&rwlock_tbl);
3082 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3083 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3084 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3085 rc = pthread_rwlock_init(rwlock, NULL);
3086 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3087 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3088 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3093 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3095 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3098 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3100 rc = pthread_rwlock_unlock(&rwlock_tbl);
3101 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3103 rc = pthread_rwlock_tryrdlock(rwlock);
3104 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3111 pthread_rwlock_t* rwlock_obj = NULL;
3112 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3113 rc = pthread_rwlock_unlock(&rwlock_tbl);
3114 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3115 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
3116 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3126 void releasereadlock(void * ptr) {
3129 int self_y, self_x, target_y, target_x;
3131 // for 32 bit machine, the size is always 4 words
3135 if(((struct ___Object___ *)ptr)->lock == NULL) {
3136 reallock = (int)ptr;
3138 reallock = (int)(((struct ___Object___ *)ptr)->lock);
3140 targetcore = (reallock >> 5) % TOTALCORE;
3142 if(targetcore == corenum) {
3144 raw_user_interrupts_off();
3146 // reside on this core
3147 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3148 // no locks for this object, something is wrong
3149 raw_test_done(0xa014);
3152 struct LockValue * lockvalue = NULL;
3153 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3154 lockvalue = (struct LockValue *)rwlock_obj;
3158 raw_user_interrupts_on();
3163 calCoords(corenum, &self_y, &self_x);
3164 calCoords(targetcore, &target_y, &target_x);
3165 isMsgSending = true;
3166 // Build the message header
3167 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3169 target_y, target_x);
3170 // start sending the msg, set send msg flag
3171 //isMsgSending = true;
3172 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3174 raw_test_pass(0xbbbb);
3175 raw_test_pass(0xb000 + targetcore); // targetcore
3177 gdn_send(5); // lock release
3181 gdn_send(0); // read lock
3185 gdn_send((int)ptr); // obj pointer
3187 raw_test_pass_reg(ptr);
3189 gdn_send(reallock); // lock
3191 raw_test_pass_reg(reallock);
3192 raw_test_pass(0xffff);
3194 // end of sending this msg, set sand msg flag false
3195 isMsgSending = false;
3196 // check if there are pending msgs
3197 while(isMsgHanging) {
3198 // get the msg from outmsgdata[]
3199 // length + target + msg
3200 outmsgleft = outmsgdata[outmsgindex++];
3201 targetcore = outmsgdata[outmsgindex++];
3202 calCoords(targetcore, &target_y, &target_x);
3203 isMsgSending = true;
3204 // Build the message header
3205 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3207 target_y, target_x);
3208 //isMsgSending = true;
3209 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3211 raw_test_pass(0xbbbb);
3212 raw_test_pass(0xb000 + targetcore); // targetcore
3214 while(outmsgleft-- > 0) {
3215 gdn_send(outmsgdata[outmsgindex++]);
3217 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3221 raw_test_pass(0xffff);
3223 isMsgSending = false;
3225 raw_user_interrupts_off();
3227 // check if there are still msg hanging
3228 if(outmsgindex == outmsglast) {
3230 outmsgindex = outmsglast = 0;
3231 isMsgHanging = false;
3234 raw_user_interrupts_on();
3237 #elif defined THREADSIMULATE
3238 int numofcore = pthread_getspecific(key);
3239 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3240 printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3241 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3242 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3245 pthread_rwlock_t* rwlock_obj = NULL;
3246 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3247 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3248 printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3249 rc = pthread_rwlock_unlock(&rwlock_tbl);
3250 printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3255 // redirected lock request
3256 bool getreadlock_I_r(void * ptr, void * redirectlock, int core, bool cache) {
3258 int self_y, self_x, target_y, target_x;
3260 // for 32 bit machine, the size is always 6 words
3263 if(core == corenum) {
3265 lock2require = (int)redirectlock;
3272 targetcore = ((int)redirectlock >> 5) % TOTALCORE;
3274 if(targetcore == corenum) {
3275 // reside on this core
3277 if(!RuntimeHashcontainskey(locktbl, (int)redirectlock)) {
3278 // no locks for this object
3279 // first time to operate on this shared object
3280 // create a lock for it
3281 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3282 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3283 lockvalue->redirectlock = 0;
3284 lockvalue->value = 1;
3285 RuntimeHashadd_I(locktbl, (int)redirectlock, (int)lockvalue);
3288 struct LockValue* lockvalue;
3289 RuntimeHashget(locktbl, (int)redirectlock, &rwlock_obj);
3290 lockvalue = (struct LockValue*)rwlock_obj;
3291 if(lockvalue->redirectlock != 0) {
3292 // the lock is redirected
3293 getreadlock_I_r(ptr, (void *)lockvalue->redirectlock, core, cache);
3296 if(-1 != lockvalue->value) {
3303 if(core == corenum) {
3304 if(lockobj == (int)ptr) {
3309 RuntimeHashadd_I(objRedirectLockTbl, (int)ptr, (int)redirectlock);
3316 // conflicts on lockresults
3317 raw_test_done(0xa015);
3321 // send lock grant/deny request to the root requiring core
3322 // check if there is still some msg on sending
3324 if((!cache) || (cache && !isMsgSending)) {
3325 calCoords(corenum, &self_y, &self_x);
3326 calCoords(core, &target_y, &target_x);
3327 // Build the message header
3328 msgHdr = construct_dyn_hdr(0, msgsize1, 0, // msgsize word sent.
3330 target_y, target_x);
3331 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3333 raw_test_pass(0xbbbb);
3334 raw_test_pass(0xb000 + core); // targetcore
3338 gdn_send(0xa); // lock deny with redirected info
3344 gdn_send(9); // lock grant with redirected info
3349 gdn_send(0); // read lock
3353 gdn_send((int)ptr); // obj pointer
3355 raw_test_pass_reg(ptr);
3357 gdn_send((int)redirectlock); // redirected lock
3359 raw_test_pass_reg((int)redirectlock);
3360 raw_test_pass(0xffff);
3362 } else if(cache && isMsgSending) {
3363 isMsgHanging = true;
3364 // cache the msg in outmsgdata and send it later
3365 // msglength + target core + msg
3366 outmsgdata[outmsglast++] = msgsize1;
3367 outmsgdata[outmsglast++] = core;
3369 outmsgdata[outmsglast++] = 0xa; // deny
3371 outmsgdata[outmsglast++] = 9; // grant
3373 outmsgdata[outmsglast++] = 0;
3374 outmsgdata[outmsglast++] = (int)ptr;
3375 outmsgdata[outmsglast++] = (int)redirectlock;
3380 // check if there is still some msg on sending
3381 if((!cache) || (cache && !isMsgSending)) {
3382 calCoords(corenum, &self_y, &self_x);
3383 calCoords(targetcore, &target_y, &target_x);
3384 // Build the message header
3385 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3387 target_y, target_x);
3388 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3390 raw_test_pass(0xbbbb);
3391 raw_test_pass(0xb000 + targetcore); // targetcore
3393 gdn_send(8); // redirected lock request
3397 gdn_send(0); // read lock
3401 gdn_send((int)ptr); // obj pointer
3403 raw_test_pass_reg(ptr);
3405 gdn_send(lock2require); // redirected lock
3407 raw_test_pass_reg(lock2require);
3409 gdn_send(core); // root request core
3411 raw_test_pass_reg(core);
3413 gdn_send(corenum); // request core
3415 raw_test_pass_reg(corenum);
3416 raw_test_pass(0xffff);
3418 } else if(cache && isMsgSending) {
3419 isMsgHanging = true;
3420 // cache the msg in outmsgdata and send it later
3421 // msglength + target core + msg
3422 outmsgdata[outmsglast++] = msgsize;
3423 outmsgdata[outmsglast++] = targetcore;
3424 outmsgdata[outmsglast++] = 8;
3425 outmsgdata[outmsglast++] = 0;
3426 outmsgdata[outmsglast++] = (int)ptr;
3427 outmsgdata[outmsglast++] = lock2require;
3428 outmsgdata[outmsglast++] = core;
3429 outmsgdata[outmsglast++] = corenum;
3436 bool getwritelock(void * ptr) {
3439 int self_y, self_x, target_y, target_x;
3441 // for 32 bit machine, the size is always 5 words
3445 if(((struct ___Object___ *)ptr)->lock == NULL) {
3446 lock2require = lockobj;
3448 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
3450 targetcore = (lock2require >> 5) % TOTALCORE;
3458 raw_test_pass(0xe551);
3459 raw_test_pass_reg(lockobj);
3460 raw_test_pass_reg(lock2require);
3461 raw_test_pass_reg(targetcore);
3464 if(targetcore == corenum) {
3465 // reside on this core
3468 raw_user_interrupts_off();
3470 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
3471 // no locks for this object
3472 // first time to operate on this shared object
3473 // create a lock for it
3474 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3476 raw_test_pass(0xe552);
3478 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3479 lockvalue->redirectlock = 0;
3480 lockvalue->value = -1;
3481 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
3484 struct LockValue* lockvalue;
3485 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3486 lockvalue = (struct LockValue*)rwlock_obj;
3488 raw_test_pass(0xe553);
3489 raw_test_pass_reg(lockvalue->value);
3491 if(lockvalue->redirectlock != 0) {
3492 // the lock is redirected
3494 raw_test_pass(0xe554);
3496 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
3499 if(0 == lockvalue->value) {
3500 lockvalue->value = -1;
3507 raw_user_interrupts_on();
3510 raw_test_pass(0xe555);
3511 raw_test_pass_reg(lockresult);
3513 if(lockobj == (int)ptr) {
3530 // conflicts on lockresults
3531 raw_test_done(0xa016);
3537 raw_test_pass(0xe556);
3539 calCoords(corenum, &self_y, &self_x);
3540 calCoords(targetcore, &target_y, &target_x);
3542 raw_test_pass_reg(self_y);
3543 raw_test_pass_reg(self_x);
3544 raw_test_pass_reg(target_y);
3545 raw_test_pass_reg(target_x);
3547 isMsgSending = true;
3548 // Build the message header
3549 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3551 target_y, target_x);
3552 // start sending the msg, set send msg flag
3553 //isMsgSending = true;
3554 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3556 raw_test_pass(0xbbbb);
3557 raw_test_pass(0xb000 + targetcore); // targetcore
3559 gdn_send(2); // lock request
3563 gdn_send(1); // write lock
3567 gdn_send((int)ptr); // obj pointer
3569 raw_test_pass_reg(ptr);
3571 gdn_send(lock2require); // lock
3573 raw_test_pass_reg(lock2require);
3575 gdn_send(corenum); // request core
3577 raw_test_pass_reg(corenum);
3578 raw_test_pass(0xffff);
3580 // end of sending this msg, set sand msg flag false
3581 isMsgSending = false;
3582 // check if there are pending msgs
3583 while(isMsgHanging) {
3584 // get the msg from outmsgdata[]
3585 // length + target + msg
3586 outmsgleft = outmsgdata[outmsgindex++];
3587 targetcore = outmsgdata[outmsgindex++];
3588 calCoords(targetcore, &target_y, &target_x);
3589 isMsgSending = true;
3590 // Build the message header
3591 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3593 target_y, target_x);
3594 //isMsgSending = true;
3595 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3597 raw_test_pass(0xe557);
3598 raw_test_pass(0xbbbb);
3599 raw_test_pass(0xb000 + targetcore); // targetcore
3601 while(outmsgleft-- > 0) {
3602 gdn_send(outmsgdata[outmsgindex++]);
3604 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3608 raw_test_pass(0xffff);
3610 isMsgSending = false;
3612 raw_user_interrupts_off();
3614 // check if there are still msg hanging
3615 if(outmsgindex == outmsglast) {
3617 outmsgindex = outmsglast = 0;
3618 isMsgHanging = false;
3621 raw_user_interrupts_on();
3625 #elif defined THREADSIMULATE
3626 int numofcore = pthread_getspecific(key);
3628 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3629 printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3633 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3634 // no locks for this object
3635 // first time to operate on this shared object
3636 // create a lock for it
3637 rc = pthread_rwlock_unlock(&rwlock_tbl);
3638 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3639 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3640 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3641 rc = pthread_rwlock_init(rwlock, NULL);
3642 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3643 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3644 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3646 pthread_rwlock_destroy(rwlock);
3650 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3652 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3654 pthread_rwlock_destroy(rwlock);
3656 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3658 rc = pthread_rwlock_unlock(&rwlock_tbl);
3659 printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3661 rc = pthread_rwlock_trywrlock(rwlock);
3662 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3669 pthread_rwlock_t* rwlock_obj = NULL;
3670 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3671 rc = pthread_rwlock_unlock(&rwlock_tbl);
3672 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3673 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
3674 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3684 void releasewritelock(void * ptr) {
3687 int self_y, self_x, target_y, target_x;
3689 // for 32 bit machine, the size is always 4 words
3693 if(((struct ___Object___ *)ptr)->lock == NULL) {
3694 reallock = (int)ptr;
3696 reallock = (int)(((struct ___Object___ *)ptr)->lock);
3698 targetcore = (reallock >> 5) % TOTALCORE;
3701 raw_test_pass(0xe661);
3702 raw_test_pass_reg((int)ptr);
3703 raw_test_pass_reg(reallock);
3704 raw_test_pass_reg(targetcore);
3707 if(targetcore == corenum) {
3709 raw_user_interrupts_off();
3711 // reside on this core
3712 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3713 // no locks for this object, something is wrong
3714 raw_test_done(0xa017);
3717 struct LockValue * lockvalue = NULL;
3719 raw_test_pass(0xe662);
3721 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3722 lockvalue = (struct LockValue *)rwlock_obj;
3724 raw_test_pass_reg(lockvalue->value);
3728 raw_test_pass_reg(lockvalue->value);
3732 raw_user_interrupts_on();
3738 raw_test_pass(0xe663);
3740 calCoords(corenum, &self_y, &self_x);
3741 calCoords(targetcore, &target_y, &target_x);
3742 isMsgSending = true;
3743 // Build the message header
3744 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3746 target_y, target_x);
3747 // start sending the msg, set send msg flag
3748 //isMsgSending = true;
3749 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3751 raw_test_pass(0xbbbb);
3752 raw_test_pass(0xb000 + targetcore);
3754 gdn_send(5); // lock release
3758 gdn_send(1); // write lock
3762 gdn_send((int)ptr); // obj pointer
3764 raw_test_pass_reg(ptr);
3766 gdn_send(reallock); // lock
3768 raw_test_pass_reg(reallock);
3769 raw_test_pass(0xffff);
3771 // end of sending this msg, set sand msg flag false
3772 isMsgSending = false;
3773 // check if there are pending msgs
3774 while(isMsgHanging) {
3775 // get the msg from outmsgdata[]
3776 // length + target + msg
3777 outmsgleft = outmsgdata[outmsgindex++];
3778 targetcore = outmsgdata[outmsgindex++];
3779 calCoords(targetcore, &target_y, &target_x);
3780 isMsgSending = true;
3781 // Build the message header
3782 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3784 target_y, target_x);
3785 //isMsgSending = true;
3786 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3788 raw_test_pass(0xbbbb);
3789 raw_test_pass(0xb000 + targetcore); // targetcore
3791 while(outmsgleft-- > 0) {
3792 gdn_send(outmsgdata[outmsgindex++]);
3794 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3798 raw_test_pass(0xffff);
3800 isMsgSending = false;
3802 raw_user_interrupts_off();
3804 // check if there are still msg hanging
3805 if(outmsgindex == outmsglast) {
3807 outmsgindex = outmsglast = 0;
3808 isMsgHanging = false;
3811 raw_user_interrupts_on();
3814 #elif defined THREADSIMULATE
3815 int numofcore = pthread_getspecific(key);
3816 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3817 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3818 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3819 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3822 pthread_rwlock_t* rwlock_obj = NULL;
3823 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3824 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3825 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3826 rc = pthread_rwlock_unlock(&rwlock_tbl);
3827 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3831 void releasewritelock_r(void * lock, void * redirectlock) {
3834 int self_y, self_x, target_y, target_x;
3836 // for 32 bit machine, the size is always 4 words
3839 int reallock = (int)lock;
3840 targetcore = (reallock >> 5) % TOTALCORE;
3843 raw_test_pass(0xe671);
3844 raw_test_pass_reg((int)lock);
3845 raw_test_pass_reg(reallock);
3846 raw_test_pass_reg(targetcore);
3849 if(targetcore == corenum) {
3851 raw_user_interrupts_off();
3853 // reside on this core
3854 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3855 // no locks for this object, something is wrong
3856 raw_test_done(0xa018);
3859 struct LockValue * lockvalue = NULL;
3861 raw_test_pass(0xe672);
3863 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3864 lockvalue = (struct LockValue *)rwlock_obj;
3866 raw_test_pass_reg(lockvalue->value);
3869 lockvalue->redirectlock = (int)redirectlock;
3871 raw_test_pass_reg(lockvalue->value);
3875 raw_user_interrupts_on();
3881 raw_test_pass(0xe673);
3883 calCoords(corenum, &self_y, &self_x);
3884 calCoords(targetcore, &target_y, &target_x);
3885 isMsgSending = true;
3886 // Build the message header
3887 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3889 target_y, target_x);
3890 // start sending the msg, set send msg flag
3891 //isMsgSending = true;
3894 raw_test_pass(0xbbbb);
3895 raw_test_pass(0xb000 + targetcore);
3897 gdn_send(0xb); // lock release with redirect info
3901 gdn_send(1); // write lock
3905 gdn_send((int)lock); // lock
3907 raw_test_pass_reg(lock);
3909 gdn_send((int)redirectlock); // redirect lock
3911 raw_test_pass_reg(redirectlock);
3912 raw_test_pass(0xffff);
3914 // end of sending this msg, set sand msg flag false
3915 isMsgSending = false;
3916 // check if there are pending msgs
3917 while(isMsgHanging) {
3918 // get the msg from outmsgdata[]
3919 // length + target + msg
3920 outmsgleft = outmsgdata[outmsgindex++];
3921 targetcore = outmsgdata[outmsgindex++];
3922 calCoords(targetcore, &target_y, &target_x);
3923 isMsgSending = true;
3924 // Build the message header
3925 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3927 target_y, target_x);
3928 //isMsgSending = true;
3929 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3931 raw_test_pass(0xbbbb);
3932 raw_test_pass(0xb000 + targetcore); // targetcore
3934 while(outmsgleft-- > 0) {
3935 gdn_send(outmsgdata[outmsgindex++]);
3937 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3941 raw_test_pass(0xffff);
3943 isMsgSending = false;
3945 raw_user_interrupts_off();
3947 // check if there are still msg hanging
3948 if(outmsgindex == outmsglast) {
3950 outmsgindex = outmsglast = 0;
3951 isMsgHanging = false;
3954 raw_user_interrupts_on();
3957 #elif defined THREADSIMULATE
3958 // TODO, need modification according to alias lock
3959 int numofcore = pthread_getspecific(key);
3960 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3961 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3962 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3963 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3966 pthread_rwlock_t* rwlock_obj = NULL;
3967 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3968 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3969 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3970 rc = pthread_rwlock_unlock(&rwlock_tbl);
3971 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3976 bool getwritelock_I(void * ptr) {
3978 int self_y, self_x, target_y, target_x;
3980 // for 32 bit machine, the size is always 5 words
3984 if(((struct ___Object___ *)ptr)->lock == NULL) {
3985 lock2require = lockobj;
3987 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
3989 targetcore = (lock2require >> 5) % TOTALCORE;
3997 raw_test_pass(0xe561);
3998 raw_test_pass_reg(lockobj);
3999 raw_test_pass_reg(lock2require);
4000 raw_test_pass_reg(targetcore);
4003 if(targetcore == corenum) {
4004 // reside on this core
4006 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
4007 // no locks for this object
4008 // first time to operate on this shared object
4009 // create a lock for it
4010 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
4012 raw_test_pass(0xe562);
4014 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
4015 lockvalue->redirectlock = 0;
4016 lockvalue->value = -1;
4017 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
4020 struct LockValue* lockvalue;
4021 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
4022 lockvalue = (struct LockValue*)rwlock_obj;
4024 raw_test_pass(0xe563);
4025 raw_test_pass_reg(lockvalue->value);
4027 if(lockvalue->redirectlock != 0) {
4028 // the lock is redirected
4030 raw_test_pass(0xe564);
4032 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
4035 if(0 == lockvalue->value) {
4036 lockvalue->value = -1;
4043 raw_test_pass(0xe565);
4044 raw_test_pass_reg(lockresult);
4046 if(lockobj == (int)ptr) {
4063 // conflicts on lockresults
4064 raw_test_done(0xa019);
4070 raw_test_pass(0xe566);
4072 calCoords(corenum, &self_y, &self_x);
4073 calCoords(targetcore, &target_y, &target_x);
4074 // Build the message header
4075 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4077 target_y, target_x);
4078 // start sending the msg, set send msg flag
4079 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4081 raw_test_pass(0xbbbb);
4082 raw_test_pass(0xb000 + targetcore); // targetcore
4084 gdn_send(2); // lock request
4088 gdn_send(1); // write lock
4092 gdn_send((int)ptr); // obj pointer
4094 raw_test_pass_reg(ptr);
4096 gdn_send(lock2require); // lock
4098 raw_test_pass_reg(lock2require);
4100 gdn_send(corenum); // request core
4102 raw_test_pass_reg(corenum);
4103 raw_test_pass(0xffff);
4108 // redirected lock request
4109 bool getwritelock_I_r(void * ptr, void * redirectlock, int core, bool cache) {
4111 int self_y, self_x, target_y, target_x;
4113 // for 32 bit machine, the size is always 6 words
4116 if(core == corenum) {
4118 lock2require = (int)redirectlock;
4125 targetcore = ((int)redirectlock >> 5) % TOTALCORE;
4128 raw_test_pass(0xe571);
4129 raw_test_pass_reg((int)ptr);
4130 raw_test_pass_reg((int)redirectlock);
4131 raw_test_pass_reg(core);
4132 raw_test_pass_reg((int)cache);
4133 raw_test_pass_reg(targetcore);
4137 if(targetcore == corenum) {
4138 // reside on this core
4140 if(!RuntimeHashcontainskey(locktbl, (int)redirectlock)) {
4141 // no locks for this object
4142 // first time to operate on this shared object
4143 // create a lock for it
4144 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
4145 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
4146 lockvalue->redirectlock = 0;
4147 lockvalue->value = -1;
4148 RuntimeHashadd_I(locktbl, (int)redirectlock, (int)lockvalue);
4151 struct LockValue* lockvalue;
4152 RuntimeHashget(locktbl, (int)redirectlock, &rwlock_obj);
4153 lockvalue = (struct LockValue*)rwlock_obj;
4154 if(lockvalue->redirectlock != 0) {
4155 // the lock is redirected
4157 raw_test_pass(0xe572);
4159 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, core, cache);
4162 if(0 == lockvalue->value) {
4163 lockvalue->value = -1;
4169 if(core == corenum) {
4170 if(lockobj == (int)ptr) {
4175 RuntimeHashadd_I(objRedirectLockTbl, (int)ptr, (int)redirectlock);
4182 // conflicts on lockresults
4183 raw_test_done(0xa01a);
4187 // send lock grant/deny request to the root requiring core
4188 // check if there is still some msg on sending
4190 if((!cache) || (cache && !isMsgSending)) {
4191 calCoords(corenum, &self_y, &self_x);
4192 calCoords(core, &target_y, &target_x);
4193 // Build the message header
4194 msgHdr = construct_dyn_hdr(0, msgsize1, 0, // msgsize word sent.
4196 target_y, target_x);
4197 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4199 raw_test_pass(0xbbbb);
4200 raw_test_pass(0xb000 + core); // targetcore
4204 gdn_send(0xa); // lock deny with redirected info
4210 gdn_send(9); // lock grant with redirected info
4215 gdn_send(1); // write lock
4219 gdn_send((int)ptr); // obj pointer
4221 raw_test_pass_reg(ptr);
4223 gdn_send((int)redirectlock); // redirected lock
4225 raw_test_pass_reg((int)redirectlock);
4226 raw_test_pass(0xffff);
4228 } else if(cache && isMsgSending) {
4229 isMsgHanging = true;
4230 // cache the msg in outmsgdata and send it later
4231 // msglength + target core + msg
4232 outmsgdata[outmsglast++] = msgsize1;
4233 outmsgdata[outmsglast++] = core;
4235 outmsgdata[outmsglast++] = 0xa; // deny
4237 outmsgdata[outmsglast++] = 9; // grant
4239 outmsgdata[outmsglast++] = 1;
4240 outmsgdata[outmsglast++] = (int)ptr;
4241 outmsgdata[outmsglast++] = (int)redirectlock;
4246 // check if there is still some msg on sending
4247 if((!cache) || (cache && !isMsgSending)) {
4248 calCoords(corenum, &self_y, &self_x);
4249 calCoords(targetcore, &target_y, &target_x);
4250 // Build the message header
4251 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4253 target_y, target_x);
4254 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4256 raw_test_pass(0xbbbb);
4257 raw_test_pass(0xb000 + targetcore); // targetcore
4259 gdn_send(8); // redirected lock request
4263 gdn_send(1); // write lock
4267 gdn_send((int)ptr); // obj pointer
4269 raw_test_pass_reg(ptr);
4271 gdn_send((int)redirectlock); // redirected lock
4273 raw_test_pass_reg((int)redirectlock);
4275 gdn_send(core); // root request core
4277 raw_test_pass_reg(core);
4279 gdn_send(corenum); // request core
4281 raw_test_pass_reg(corenum);
4282 raw_test_pass(0xffff);
4284 } else if(cache && isMsgSending) {
4285 isMsgHanging = true;
4286 // cache the msg in outmsgdata and send it later
4287 // msglength + target core + msg
4288 outmsgdata[outmsglast++] = msgsize;
4289 outmsgdata[outmsglast++] = targetcore;
4290 outmsgdata[outmsglast++] = 8;
4291 outmsgdata[outmsglast++] = 1;
4292 outmsgdata[outmsglast++] = (int)ptr;
4293 outmsgdata[outmsglast++] = (int)redirectlock;
4294 outmsgdata[outmsglast++] = core;
4295 outmsgdata[outmsglast++] = corenum;
4300 void releasewritelock_I(void * ptr) {
4302 int self_y, self_x, target_y, target_x;
4304 // for 32 bit machine, the size is always 4 words
4308 if(((struct ___Object___ *)ptr)->lock == NULL) {
4309 reallock = (int)ptr;
4311 reallock = (int)(((struct ___Object___ *)ptr)->lock);
4313 targetcore = (reallock >> 5) % TOTALCORE;
4316 raw_test_pass(0xe681);
4317 raw_test_pass_reg((int)ptr);
4318 raw_test_pass_reg(reallock);
4319 raw_test_pass_reg(targetcore);
4322 if(targetcore == corenum) {
4323 // reside on this core
4324 if(!RuntimeHashcontainskey(locktbl, reallock)) {
4325 // no locks for this object, something is wrong
4326 raw_test_done(0xa01b);
4329 struct LockValue * lockvalue = NULL;
4330 RuntimeHashget(locktbl, reallock, &rwlock_obj);
4331 lockvalue = (struct LockValue *)rwlock_obj;
4337 calCoords(corenum, &self_y, &self_x);
4338 calCoords(targetcore, &target_y, &target_x);
4339 // Build the message header
4340 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4342 target_y, target_x);
4343 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4345 raw_test_pass(0xbbbb);
4346 raw_test_pass(0xb000 + targetcore); // targetcore
4348 gdn_send(5); // lock release
4352 gdn_send(1); // write lock
4356 gdn_send((int)ptr); // obj pointer
4358 raw_test_pass_reg(ptr);
4360 gdn_send(reallock); // lock
4362 raw_test_pass_reg(reallock);
4363 raw_test_pass(0xffff);
4367 void releasewritelock_I_r(void * lock, void * redirectlock) {
4369 int self_y, self_x, target_y, target_x;
4371 // for 32 bit machine, the size is always 4 words
4374 int reallock = (int)lock;
4375 targetcore = (reallock >> 5) % TOTALCORE;
4378 raw_test_pass(0xe691);
4379 raw_test_pass_reg((int)lock);
4380 raw_test_pass_reg(reallock);
4381 raw_test_pass_reg(targetcore);
4384 if(targetcore == corenum) {
4385 // reside on this core
4386 if(!RuntimeHashcontainskey(locktbl, reallock)) {
4387 // no locks for this object, something is wrong
4388 raw_test_done(0xa01c);
4391 struct LockValue * lockvalue = NULL;
4393 raw_test_pass(0xe692);
4395 RuntimeHashget(locktbl, reallock, &rwlock_obj);
4396 lockvalue = (struct LockValue *)rwlock_obj;
4398 raw_test_pass_reg(lockvalue->value);
4401 lockvalue->redirectlock = (int)redirectlock;
4403 raw_test_pass_reg(lockvalue->value);
4410 raw_test_pass(0xe693);
4412 calCoords(corenum, &self_y, &self_x);
4413 calCoords(targetcore, &target_y, &target_x);
4414 // Build the message header
4415 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4417 target_y, target_x);
4418 // start sending the msg, set send msg flag
4421 raw_test_pass(0xbbbb);
4422 raw_test_pass(0xb000 + targetcore);
4424 gdn_send(0xb); // lock release with redirect info
4428 gdn_send(1); // write lock
4432 gdn_send((int)lock); // lock
4434 raw_test_pass_reg(lock);
4436 gdn_send((int)redirectlock); // redirect lock
4438 raw_test_pass_reg(redirectlock);
4439 raw_test_pass(0xffff);
4444 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
4445 void * taskpointerarray[MAXTASKPARAMS];
4447 int numparams=parameter->task->numParameters;
4448 int numiterators=parameter->task->numTotal-1;
4453 struct taskdescriptor * task=parameter->task;
4455 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
4457 /* Add enqueued object to parameter vector */
4458 taskpointerarray[parameter->slot]=ptr;
4460 /* Reset iterators */
4461 for(j=0; j<numiterators; j++) {
4462 toiReset(¶meter->iterators[j]);
4465 /* Find initial state */
4466 for(j=0; j<numiterators; j++) {
4468 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4469 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4471 /* Need to backtrack */
4472 toiReset(¶meter->iterators[j]);
4476 /* Nothing to enqueue */
4483 /* Enqueue current state */
4485 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
4487 tpd->numParameters=numiterators+1;
4488 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
4489 for(j=0; j<=numiterators; j++) {
4490 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
4493 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
4494 genputtable(activetasks, tpd, tpd);
4496 RUNFREE(tpd->parameterArray);
4500 /* This loop iterates to the next parameter combination */
4501 if (numiterators==0)
4504 for(j=numiterators-1; j<numiterators; j++) {
4506 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4507 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4509 /* Need to backtrack */
4510 toiReset(¶meter->iterators[j]);
4514 /* Nothing more to enqueue */
4523 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
4524 void * taskpointerarray[MAXTASKPARAMS];
4526 int numparams=parameter->task->numParameters;
4527 int numiterators=parameter->task->numTotal-1;
4532 struct taskdescriptor * task=parameter->task;
4534 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
4536 /* Add enqueued object to parameter vector */
4537 taskpointerarray[parameter->slot]=ptr;
4539 /* Reset iterators */
4540 for(j=0; j<numiterators; j++) {
4541 toiReset(¶meter->iterators[j]);
4544 /* Find initial state */
4545 for(j=0; j<numiterators; j++) {
4547 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4548 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4550 /* Need to backtrack */
4551 toiReset(¶meter->iterators[j]);
4555 /* Nothing to enqueue */
4561 /* Enqueue current state */
4563 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
4565 tpd->numParameters=numiterators+1;
4566 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
4567 for(j=0; j<=numiterators; j++) {
4568 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
4571 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
4572 genputtable_I(activetasks, tpd, tpd);
4574 RUNFREE(tpd->parameterArray);
4578 /* This loop iterates to the next parameter combination */
4579 if (numiterators==0)
4582 for(j=numiterators-1; j<numiterators; j++) {
4584 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4585 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4587 /* Need to backtrack */
4588 toiReset(¶meter->iterators[j]);
4592 /* Nothing more to enqueue */
4601 /* Handler for signals. The signals catch null pointer errors and
4602 arithmatic errors. */
4604 void myhandler(int sig, siginfo_t *info, void *uap) {
4607 printf("sig=%d\n",sig);
4610 sigemptyset(&toclear);
4611 sigaddset(&toclear, sig);
4612 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
4613 longjmp(error_handler,1);
4619 struct RuntimeHash *fdtoobject;
4621 void addreadfd(int fd) {
4624 FD_SET(fd, &readfds);
4627 void removereadfd(int fd) {
4628 FD_CLR(fd, &readfds);
4629 if (maxreadfd==(fd+1)) {
4631 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
4642 void executetasks() {
4643 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
4646 struct ___Object___ * tmpparam = NULL;
4647 struct parameterdescriptor * pd=NULL;
4648 struct parameterwrapper *pw=NULL;
4654 struct LockValue * locks[MAXTASKPARAMS];
4660 for(j = 0; j < MAXTASKPARAMS; j++) {
4661 locks[j] = (struct LockValue *)(RUNMALLOC(sizeof(struct LockValue)));
4662 locks[j]->redirectlock = 0;
4663 locks[j]->value = 0;
4668 /* Set up signal handlers */
4669 struct sigaction sig;
4670 sig.sa_sigaction=&myhandler;
4671 sig.sa_flags=SA_SIGINFO;
4672 sigemptyset(&sig.sa_mask);
4674 /* Catch bus errors, segmentation faults, and floating point exceptions*/
4675 sigaction(SIGBUS,&sig,0);
4676 sigaction(SIGSEGV,&sig,0);
4677 sigaction(SIGFPE,&sig,0);
4678 sigaction(SIGPIPE,&sig,0);
4687 fdtoobject=allocateRuntimeHash(100);
4691 /* Map first block of memory to protected, anonymous page */
4692 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
4696 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
4700 raw_test_pass(0xe990);
4703 /* Check if any filedescriptors have IO pending */
4706 struct timeval timeout={0,0};
4710 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
4712 /* Process ready fd's */
4714 for(fd=0; fd<maxreadfd; fd++) {
4715 if (FD_ISSET(fd, &tmpreadfds)) {
4716 /* Set ready flag on object */
4718 // printf("Setting fd %d\n",fd);
4719 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
4720 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
4721 enqueueObject(objptr, NULL, 0);
4730 /* See if there are any active tasks */
4731 if (hashsize(activetasks)>0) {
4734 if(!taskInfoOverflow) {
4735 TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
4736 taskInfoArray[taskInfoIndex] = checkTaskInfo;
4737 checkTaskInfo->taskName = "tpd checking";
4738 checkTaskInfo->startTime = raw_get_cycle();
4739 checkTaskInfo->endTime = -1;
4740 checkTaskInfo->exitIndex = -1;
4741 checkTaskInfo->newObjs = NULL;
4745 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
4746 genfreekey(activetasks, currtpd);
4748 numparams=currtpd->task->numParameters;
4749 numtotal=currtpd->task->numTotal;
4751 #ifdef THREADSIMULATE
4752 int isolateflags[numparams];
4755 // clear the lockRedirectTbl (TODO, this table should be empty after all locks are released)
4757 // get all required locks
4759 // check which locks are needed
4760 for(i = 0; i < numparams; i++) {
4761 void * param = currtpd->parameterArray[i];
4765 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
4767 taskpointerarray[i+OFFSET]=param;
4770 if(((struct ___Object___ *)param)->lock == NULL) {
4771 tmplock = (int)param;
4773 tmplock = (int)(((struct ___Object___ *)param)->lock);
4775 // insert into the locks array
4776 for(j = 0; j < locklen; j++) {
4777 if(locks[j]->value == tmplock) {
4780 } else if(locks[j]->value > tmplock) {
4787 locks[h]->redirectlock = locks[h-1]->redirectlock;
4788 locks[h]->value = locks[h-1]->value;
4790 locks[j]->value = tmplock;
4791 locks[j]->redirectlock = (int)param;
4795 // grab these required locks
4797 raw_test_pass(0xe991);
4799 for(i = 0; i < locklen; i++) {
4800 int * lock = (int *)(locks[i]->redirectlock);
4802 // require locks for this parameter if it is not a startup object
4804 raw_test_pass_reg((int)lock);
4805 raw_test_pass_reg((int)(locks[i]->value));
4810 raw_user_interrupts_off();
4813 //isInterrupt = false;
4820 while(receiveObject() != -1) {
4824 grount = lockresult;
4834 //isInterrupt = true;
4837 raw_user_interrupts_on();
4843 raw_test_pass(0xe992);
4845 // can not get the lock, try later
4846 // releas all grabbed locks for previous parameters
4847 for(j = 0; j < i; ++j) {
4848 lock = (int*)(locks[j]->redirectlock);
4849 releasewritelock(lock);
4851 genputtable(activetasks, currtpd, currtpd);
4852 if(hashsize(activetasks) == 1) {
4853 // only one task right now, wait a little while before next try
4859 // fail, set the end of the checkTaskInfo
4860 if(!taskInfoOverflow) {
4861 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4863 if(taskInfoIndex == TASKINFOLENGTH) {
4864 taskInfoOverflow = true;
4871 #elif defined THREADSIMULATE
4872 // TODO: need modification according to added alias locks
4876 raw_test_pass(0xe993);
4878 /* Make sure that the parameters are still in the queues */
4879 for(i=0; i<numparams; i++) {
4880 void * parameter=currtpd->parameterArray[i];
4884 #ifdef RAWCACHEFLUSH
4886 raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
4889 raw_user_interrupts_off();
4891 /*if(RuntimeHashcontainskey(objRedirectLockTbl, (int)parameter)) {
4892 int redirectlock_r = 0;
4893 RuntimeHashget(objRedirectLockTbl, (int)parameter, &redirectlock_r);
4894 ((struct ___Object___ *)parameter)->lock = redirectlock_r;
4895 RuntimeHashremovekey(objRedirectLockTbl, (int)parameter);
4898 raw_user_interrupts_on();
4902 tmpparam = (struct ___Object___ *)parameter;
4903 #ifdef THREADSIMULATE
4904 if(0 == tmpparam->isolate) {
4905 isolateflags[i] = 0;
4906 // shared object, need to flush with current value
4907 // TODO: need modification according to added alias locks
4908 if(!getwritelock(tmpparam->original)) {
4909 // fail to get write lock, release all obtained locks and try this task later
4911 for(j = 0; j < i; ++j) {
4912 if(0 == isolateflags[j]) {
4913 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
4916 genputtable(activetasks, currtpd, currtpd);
4919 if(tmpparam->version != tmpparam->original->version) {
4920 // release all obtained locks
4922 for(j = 0; j < i; ++j) {
4923 if(0 == isolateflags[j]) {
4924 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
4927 releasewritelock(tmpparam->original);
4929 // dequeue this object
4930 int numofcore = pthread_getspecific(key);
4931 struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
4932 int length = numqueues[numofcore][tmpparam->type];
4933 for(j = 0; j < length; ++j) {
4934 struct parameterwrapper * pw = queues[j];
4935 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
4937 int UNUSED, UNUSED2;
4939 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
4940 ObjectHashremove(pw->objectset, (int)tmpparam);
4941 if (enterflags!=NULL)
4945 // Free up task parameter descriptor
4946 RUNFREE(currtpd->parameterArray);
4951 isolateflags[i] = 1;
4954 pd=currtpd->task->descriptorarray[i];
4955 pw=(struct parameterwrapper *) pd->queue;
4956 /* Check that object is still in queue */
4958 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
4960 raw_test_pass(0xe994);
4962 // release grabbed locks
4964 for(j = 0; j < locklen; ++j) {
4965 int * lock = (int *)(locks[j]->redirectlock);
4966 releasewritelock(lock);
4968 #elif defined THREADSIMULATE
4970 RUNFREE(currtpd->parameterArray);
4976 /* Check if the object's flags still meets requirements */
4980 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
4981 andmask=pw->intarray[tmpi*2];
4982 checkmask=pw->intarray[tmpi*2+1];
4983 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
4989 // flags are never suitable
4990 // remove this obj from the queue
4992 int UNUSED, UNUSED2;
4995 raw_test_pass(0xe995);
4997 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
4998 ObjectHashremove(pw->objectset, (int)parameter);
4999 if (enterflags!=NULL)
5001 // release grabbed locks
5002 for(j = 0; j < locklen; ++j) {
5003 int * lock = (int *)(locks[j]->redirectlock);
5004 releasewritelock(lock);
5006 RUNFREE(currtpd->parameterArray);
5009 // fail, set the end of the checkTaskInfo
5010 if(!taskInfoOverflow) {
5011 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5013 if(taskInfoIndex == TASKINFOLENGTH) {
5014 taskInfoOverflow = true;
5024 /* Check that object still has necessary tags */
5025 for(j=0; j<pd->numbertags; j++) {
5026 int slotid=pd->tagarray[2*j]+numparams;
5027 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
5028 if (!containstag(parameter, tagd)) {
5030 raw_test_pass(0xe996);
5033 // release grabbed locks
5035 for(tmpj = 0; tmpj < locklen; ++tmpj) {
5036 int * lock = (int *)(locks[tmpj]->redirectlock);
5037 releasewritelock(lock);
5040 RUNFREE(currtpd->parameterArray);
5046 taskpointerarray[i+OFFSET]=parameter;
5049 for(; i<numtotal; i++) {
5050 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
5053 #ifdef THREADSIMULATE
5054 for(i = 0; i < numparams; ++i) {
5055 if(0 == isolateflags[i]) {
5056 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
5057 if(tmpparam != tmpparam->original) {
5058 taskpointerarray[i+OFFSET] = tmpparam->original;
5067 /* Checkpoint the state */
5068 forward=allocateRuntimeHash(100);
5069 reverse=allocateRuntimeHash(100);
5070 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
5073 if (x=setjmp(error_handler)) {
5078 printf("Fatal Error=%d, Recovering!\n",x);
5082 genputtable(failedtasks,currtpd,currtpd);
5083 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
5085 freeRuntimeHash(forward);
5086 freeRuntimeHash(reverse);
5093 raw_test_pass_reg(x);
5094 raw_test_done(0xa01d);
5099 /*if (injectfailures) {
5100 if ((((double)random())/RAND_MAX)<failurechance) {
5101 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
5102 longjmp(error_handler,10);
5105 /* Actually call task */
5107 ((int *)taskpointerarray)[0]=currtpd->numParameters;
5108 taskpointerarray[1]=NULL;
5113 // check finish, set the end of the checkTaskInfo
5114 if(!taskInfoOverflow) {
5115 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5117 if(taskInfoIndex == TASKINFOLENGTH) {
5118 taskInfoOverflow = true;
5122 if(!taskInfoOverflow) {
5123 // new a taskInfo for the task execution
5124 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
5125 taskInfoArray[taskInfoIndex] = taskInfo;
5126 taskInfo->taskName = currtpd->task->name;
5127 taskInfo->startTime = raw_get_cycle();
5128 taskInfo->endTime = -1;
5129 taskInfo->exitIndex = -1;
5130 taskInfo->newObjs = NULL;
5136 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
5138 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
5140 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
5144 raw_test_pass(0xe997);
5146 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
5149 // task finish, set the end of the checkTaskInfo
5150 if(!taskInfoOverflow) {
5151 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5153 if(taskInfoIndex == TASKINFOLENGTH) {
5154 taskInfoOverflow = true;
5157 // new a PostTaskInfo for the post-task execution
5158 if(!taskInfoOverflow) {
5159 TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
5160 taskInfoArray[taskInfoIndex] = postTaskInfo;
5161 postTaskInfo->taskName = "post task execution";
5162 postTaskInfo->startTime = raw_get_cycle();
5163 postTaskInfo->endTime = -1;
5164 postTaskInfo->exitIndex = -1;
5165 postTaskInfo->newObjs = NULL;
5169 raw_test_pass(0xe998);
5170 raw_test_pass_reg(islock);
5176 raw_test_pass(0xe999);
5178 for(i = 0; i < locklen; ++i) {
5179 void * ptr = (void *)(locks[i]->redirectlock);
5180 int * lock = (int *)(locks[i]->value);
5182 raw_test_pass_reg((int)ptr);
5183 raw_test_pass_reg((int)lock);
5185 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
5187 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
5188 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
5189 releasewritelock_r(lock, (int *)redirectlock);
5191 releasewritelock(ptr);
5194 #elif defined THREADSIMULATE
5195 // TODO : need modification for alias lock
5196 for(i = 0; i < numparams; ++i) {
5198 if(0 == isolateflags[i]) {
5199 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
5200 if(tmpparam->lock == NULL) {
5201 lock = (int*)tmpparam;
5203 lock = tmpparam->lock;
5205 releasewritelock(lock);
5212 // post task execution finish, set the end of the postTaskInfo
5213 if(!taskInfoOverflow) {
5214 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5216 if(taskInfoIndex == TASKINFOLENGTH) {
5217 taskInfoOverflow = true;
5224 freeRuntimeHash(forward);
5225 freeRuntimeHash(reverse);
5229 // Free up task parameter descriptor
5230 RUNFREE(currtpd->parameterArray);
5239 raw_test_pass(0xe99a);
5246 raw_test_pass(0xe99b);
5250 /* This function processes an objects tags */
5251 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
5254 for(i=0; i<pd->numbertags; i++) {
5255 int slotid=pd->tagarray[2*i];
5256 int tagid=pd->tagarray[2*i+1];
5258 if (statusarray[slotid+numparams]==0) {
5259 parameter->iterators[*iteratorcount].istag=1;
5260 parameter->iterators[*iteratorcount].tagid=tagid;
5261 parameter->iterators[*iteratorcount].slot=slotid+numparams;
5262 parameter->iterators[*iteratorcount].tagobjectslot=index;
5263 statusarray[slotid+numparams]=1;
5270 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
5273 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
5275 parameter->iterators[*iteratorcount].istag=0;
5276 parameter->iterators[*iteratorcount].slot=index;
5277 parameter->iterators[*iteratorcount].objectset=objectset;
5278 statusarray[index]=1;
5280 for(i=0; i<pd->numbertags; i++) {
5281 int slotid=pd->tagarray[2*i];
5282 int tagid=pd->tagarray[2*i+1];
5283 if (statusarray[slotid+numparams]!=0) {
5284 /* This tag has already been enqueued, use it to narrow search */
5285 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
5289 parameter->iterators[*iteratorcount].numtags=tagcount;
5294 /* This function builds the iterators for a task & parameter */
5296 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
5297 int statusarray[MAXTASKPARAMS];
5299 int numparams=task->numParameters;
5300 int iteratorcount=0;
5301 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
5303 statusarray[index]=1; /* Initial parameter */
5304 /* Process tags for initial iterator */
5306 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
5310 /* Check for objects with existing tags */
5311 for(i=0; i<numparams; i++) {
5312 if (statusarray[i]==0) {
5313 struct parameterdescriptor *pd=task->descriptorarray[i];
5315 for(j=0; j<pd->numbertags; j++) {
5316 int slotid=pd->tagarray[2*j];
5317 if(statusarray[slotid+numparams]!=0) {
5318 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5319 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5326 /* Next do objects w/ unbound tags*/
5328 for(i=0; i<numparams; i++) {
5329 if (statusarray[i]==0) {
5330 struct parameterdescriptor *pd=task->descriptorarray[i];
5331 if (pd->numbertags>0) {
5332 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5333 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5339 /* Nothing with a tag enqueued */
5341 for(i=0; i<numparams; i++) {
5342 if (statusarray[i]==0) {
5343 struct parameterdescriptor *pd=task->descriptorarray[i];
5344 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5345 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5358 #ifdef THREADSIMULATE
5359 int numofcore = pthread_getspecific(key);
5360 for(i=0; i<numtasks[numofcore]; i++) {
5361 struct taskdescriptor * task=taskarray[numofcore][i];
5364 if(corenum > NUMCORES - 1) {
5368 for(i=0; i<numtasks[corenum]; i++) {
5369 struct taskdescriptor * task=taskarray[corenum][i];
5372 printf("%s\n", task->name);
5374 for(j=0; j<task->numParameters; j++) {
5375 struct parameterdescriptor *param=task->descriptorarray[j];
5376 struct parameterwrapper *parameter=param->queue;
5377 struct ObjectHash * set=parameter->objectset;
5378 struct ObjectIterator objit;
5380 printf(" Parameter %d\n", j);
5382 ObjectHashiterator(set, &objit);
5383 while(ObjhasNext(&objit)) {
5384 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
5385 struct ___Object___ * tagptr=obj->___tags___;
5386 int nonfailed=Objdata4(&objit);
5387 int numflags=Objdata3(&objit);
5388 int flags=Objdata2(&objit);
5391 printf(" Contains %lx\n", obj);
5392 printf(" flag=%d\n", obj->flag);
5395 } else if (tagptr->type==TAGTYPE) {
5397 printf(" tag=%lx\n",tagptr);
5402 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
5403 for(; tagindex<ao->___cachedCode___; tagindex++) {
5405 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
5415 /* This function processes the task information to create queues for
5416 each parameter type. */
5418 void processtasks() {
5421 if(corenum > NUMCORES - 1) {
5425 #ifdef THREADSIMULATE
5426 int numofcore = pthread_getspecific(key);
5427 for(i=0; i<numtasks[numofcore]; i++) {
5428 struct taskdescriptor *task=taskarray[numofcore][i];
5430 for(i=0; i<numtasks[corenum]; i++) {
5431 struct taskdescriptor * task=taskarray[corenum][i];
5435 /* Build objectsets */
5436 for(j=0; j<task->numParameters; j++) {
5437 struct parameterdescriptor *param=task->descriptorarray[j];
5438 struct parameterwrapper *parameter=param->queue;
5439 parameter->objectset=allocateObjectHash(10);
5440 parameter->task=task;
5443 /* Build iterators for parameters */
5444 for(j=0; j<task->numParameters; j++) {
5445 struct parameterdescriptor *param=task->descriptorarray[j];
5446 struct parameterwrapper *parameter=param->queue;
5447 builditerators(task, j, parameter);
5452 void toiReset(struct tagobjectiterator * it) {
5455 } else if (it->numtags>0) {
5458 ObjectHashiterator(it->objectset, &it->it);
5462 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
5465 /* Get object with tags */
5466 struct ___Object___ *obj=objectarray[it->tagobjectslot];
5467 struct ___Object___ *tagptr=obj->___tags___;
5468 if (tagptr->type==TAGTYPE) {
5469 if ((it->tagobjindex==0)&& /* First object */
5470 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
5475 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
5476 int tagindex=it->tagobjindex;
5477 for(; tagindex<ao->___cachedCode___; tagindex++) {
5478 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
5479 if (td->flag==it->tagid) {
5480 it->tagobjindex=tagindex; /* Found right type of tag */
5486 } else if (it->numtags>0) {
5487 /* Use tags to locate appropriate objects */
5488 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
5489 struct ___Object___ *objptr=tag->flagptr;
5491 if (objptr->type!=OBJECTARRAYTYPE) {
5492 if (it->tagobjindex>0)
5494 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
5496 for(i=1; i<it->numtags; i++) {
5497 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
5498 if (!containstag(objptr,tag2))
5503 struct ArrayObject *ao=(struct ArrayObject *) objptr;
5506 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
5507 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
5508 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
5510 for(i=1; i<it->numtags; i++) {
5511 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
5512 if (!containstag(objptr,tag2))
5515 it->tagobjindex=tagindex;
5520 it->tagobjindex=tagindex;
5524 return ObjhasNext(&it->it);
5528 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
5530 struct ___Object___ * objptr=tag->flagptr;
5531 if (objptr->type==OBJECTARRAYTYPE) {
5532 struct ArrayObject *ao=(struct ArrayObject *)objptr;
5533 for(j=0; j<ao->___cachedCode___; j++) {
5534 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
5542 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
5543 /* hasNext has all of the intelligence */
5546 /* Get object with tags */
5547 struct ___Object___ *obj=objectarray[it->tagobjectslot];
5548 struct ___Object___ *tagptr=obj->___tags___;
5549 if (tagptr->type==TAGTYPE) {
5551 objectarray[it->slot]=tagptr;
5553 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
5554 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
5556 } else if (it->numtags>0) {
5557 /* Use tags to locate appropriate objects */
5558 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
5559 struct ___Object___ *objptr=tag->flagptr;
5560 if (objptr->type!=OBJECTARRAYTYPE) {
5562 objectarray[it->slot]=objptr;
5564 struct ArrayObject *ao=(struct ArrayObject *) objptr;
5565 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
5568 /* Iterate object */
5569 objectarray[it->slot]=(void *)Objkey(&it->it);