4 #include "structdefs.h"
6 #include "checkpoint.h"
8 #include "SimpleHash.h"
9 #include "GenericHashtable.h"
10 #include <sys/select.h>
11 #include <sys/types.h>
26 #include <raw_compiler_defs.h>
27 #elif defined THREADSIMULATE
28 // use POSIX message queue
29 // for each core, its message queue named as
35 extern int injectfailures;
36 extern float failurechance;
42 #define TOTALCORE raw_get_num_tiles()
46 #include "instrument.h"
49 struct genhashtable * activetasks;
50 struct genhashtable * failedtasks;
51 struct taskparamdescriptor * currtpd;
53 struct RuntimeHash * forward;
54 struct RuntimeHash * reverse;
57 int corestatus[NUMCORES]; // records status of each core
60 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
61 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
63 struct RuntimeHash locktable;
64 static struct RuntimeHash* locktbl = &locktable;
69 struct RuntimeHash * objRedirectLockTbl;
70 void * curr_heapbase=0;
71 void * curr_heaptop=0;
73 int self_numreceiveobjs;
81 struct Queue objqueue;
92 void calCoords(int core_num, int* coordY, int* coordX);
93 #elif defined THREADSIMULATE
94 static struct RuntimeHash* locktbl;
102 struct thread_data thread_data_array[NUMCORES];
104 static pthread_key_t key;
105 static pthread_rwlock_t rwlock_tbl;
106 static pthread_rwlock_t rwlock_init;
108 void run(void * arg);
111 bool transStallMsg(int targetcore);
112 void transTerminateMsg(int targetcore);
114 bool getreadlock(void* ptr);
115 void releasereadlock(void* ptr);
117 bool getreadlock_I_r(void * ptr, void * redirectlock, int core, bool cache);
119 bool getwritelock(void* ptr);
120 void releasewritelock(void* ptr);
121 void releasewritelock_r(void * lock, void * redirectlock);
123 bool getwritelock_I(void* ptr);
124 bool getwritelock_I_r(void* lock, void* redirectlock, int core, bool cache);
125 void releasewritelock_I(void * ptr);
128 // profiling mode of RAW version
131 #define TASKINFOLENGTH 1000
132 //#define INTERRUPTINFOLENGTH 500
138 typedef struct task_info {
143 struct Queue * newObjs;
146 /*typedef struct interrupt_info {
151 TaskInfo * taskInfoArray[TASKINFOLENGTH];
153 bool taskInfoOverflow;
154 /*InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
155 int interruptInfoIndex;
156 bool interruptInfoOverflow;*/
157 int profilestatus[NUMCORES]; // records status of each core
160 bool transProfileRequestMsg(int targetcore);
161 void outputProfileData();
171 int main(int argc, char **argv) {
177 bool sendStall = false;
179 bool tocontinue = false;
180 struct QueueItem * objitem = NULL;
181 struct transObjInfo * objInfo = NULL;
183 bool allStall = true;
187 raw_test_pass(0xee01);
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;
200 for(i = 0; i < NUMCORES; ++i) {
201 profilestatus[i] = 1;
205 self_numsendobjs = 0;
206 self_numreceiveobjs = 0;
207 for(i = 0; i < 30; ++i) {
214 for(i = 0; i < 30; ++i) {
220 isMsgHanging = false;
221 isMsgSending = false;
223 raw_test_pass(0xee02);
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);
246 raw_test_pass(0xee03);
251 //isInterrupt = true;
254 /*interruptInfoIndex = 0;
255 taskInfoOverflow = false;
256 interruptInfoOverflow = false;*/
260 if (corenum < NUMCORES) {
263 raw_user_interrupts_on();
265 raw_test_pass(0xee04);
270 #elif defined THREADSIMULATE
274 pthread_t threads[NUMCORES];
277 // initialize three arrays and msg queue array
278 char * pathhead = "/msgqueue_";
279 int targetlen = strlen(pathhead);
280 for(i = 0; i < NUMCORES; ++i) {
283 numreceiveobjs[i] = 0;
288 corenumstr[0] = i + '0';
289 corenumstr[1] = '\0';
292 corenumstr[1] = i %10 + '0';
293 corenumstr[0] = (i / 10) + '0';
294 corenumstr[2] = '\0';
297 printf("Error: i >= 100\n");
301 char path[targetlen + sourcelen + 1];
302 strcpy(path, pathhead);
303 strncat(path, corenumstr, sourcelen);
304 int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
305 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
307 mqd[i]= mq_open(path, oflags, omodes, NULL);
309 printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
312 printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
317 pthread_key_create(&key, NULL);
319 // create the lock table and initialize its mutex
320 locktbl = allocateRuntimeHash(20);
321 int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
322 printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
324 for(i = 0; i < NUMCORES; ++i) {
325 thread_data_array[i].corenum = i;
326 thread_data_array[i].argc = argc;
327 thread_data_array[i].argv = argv;
328 thread_data_array[i].numsendobjs = 0;
329 thread_data_array[i].numreceiveobjs = 0;
330 printf("[main] creating thread %d\n", i);
331 rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
333 printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
343 void run(void* arg) {
344 struct thread_data * my_tdata = (struct thread_data *)arg;
345 pthread_setspecific(key, (void *)my_tdata->corenum);
346 int argc = my_tdata->argc;
347 char** argv = my_tdata->argv;
348 printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
354 GC_init(); // Initialize the garbage collector
362 initializeexithandler();
364 raw_test_pass(0xee05);
366 /* Create table for failed tasks */
368 if(corenum > NUMCORES - 1) {
372 raw_test_pass(0xee01);
373 raw_test_pass_reg(taskInfoIndex);
374 raw_test_pass_reg(taskInfoOverflow);
375 if(!taskInfoOverflow) {
376 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
377 taskInfoArray[taskInfoIndex] = taskInfo;
378 taskInfo->taskName = "msg handling";
379 taskInfo->startTime = raw_get_cycle();
380 taskInfo->endTime = -1;
384 //isInterrupt = false;
391 raw_test_pass(0xee06);
394 /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
395 (int (*)(void *,void *)) &comparetpd);*/
398 raw_test_pass(0xee07);
400 /* Create queue of active tasks */
401 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
402 (int(*) (void *,void *)) &comparetpd);
404 raw_test_pass(0xee08);
407 /* Process task information */
410 raw_test_pass(0xee09);
413 if(STARTUPCORE == corenum) {
414 /* Create startup object */
415 createstartupobject(argc, argv);
418 raw_test_pass(0xee0a);
423 raw_test_pass(0xee0b);
427 // check if there are new active tasks can be executed
431 while(receiveObject() != -1) {
436 raw_test_pass(0xee0c);
439 // check if there are some pending objects, if yes, enqueue them and executetasks again
442 raw_test_pass(0xee0d);
446 bool isChecking = false;
447 if(!isEmpty(&objqueue)) {
448 if(!taskInfoOverflow) {
449 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
450 taskInfoArray[taskInfoIndex] = taskInfo;
451 taskInfo->taskName = "objqueue checking";
452 taskInfo->startTime = raw_get_cycle();
453 taskInfo->endTime = -1;
454 taskInfo->exitIndex = -1;
455 taskInfo->newObjs = NULL;
460 while(!isEmpty(&objqueue)) {
463 raw_user_interrupts_off();
466 //isInterrupt = false;
469 raw_test_pass(0xeee1);
473 objitem = getTail(&objqueue);
474 objInfo = (struct transObjInfo *)objitem->objectptr;
475 obj = objInfo->objptr;
477 raw_test_pass_reg((int)obj);
479 // grab lock and flush the obj
487 raw_test_pass_reg(grount);
501 raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
502 /*if(RuntimeHashcontainskey(objRedirectLockTbl, (int)obj)) {
503 int redirectlock = 0;
504 RuntimeHashget(objRedirectLockTbl, (int)obj, &redirectlock);
505 ((struct ___Object___ *)obj)->lock = redirectlock;
506 raw_flush_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
507 RuntimeHashremovekey(objRedirectLockTbl, (int)obj);
509 // enqueue the object
510 for(k = 0; k < objInfo->length; ++k) {
511 int taskindex = objInfo->queues[2 * k];
512 int paramindex = objInfo->queues[2 * k + 1];
513 struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
515 raw_test_pass_reg(taskindex);
516 raw_test_pass_reg(paramindex);
518 enqueueObject_I(obj, queues, 1);
520 removeItem(&objqueue, objitem);
521 releasewritelock_I(obj);
522 RUNFREE(objInfo->queues);
526 // put it at the end of the queue
527 // and try to execute active tasks already enqueued first
528 removeItem(&objqueue, objitem);
529 addNewItem_I(&objqueue, objInfo);
531 //isInterrupt = true;
534 raw_user_interrupts_on();
539 raw_user_interrupts_on();
542 raw_test_pass(0xee0e);
546 if(isChecking && (!taskInfoOverflow)) {
547 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
549 if(taskInfoIndex == TASKINFOLENGTH) {
550 taskInfoOverflow = true;
556 raw_test_pass(0xee0f);
561 if(STARTUPCORE == corenum) {
564 raw_test_pass(0xee10);
569 raw_user_interrupts_off();
571 corestatus[corenum] = 0;
572 numsendobjs[corenum] = self_numsendobjs;
573 numreceiveobjs[corenum] = self_numreceiveobjs;
574 // check the status of all cores
577 raw_test_pass_reg(NUMCORES);
579 for(i = 0; i < NUMCORES; ++i) {
581 raw_test_pass(0xe000 + corestatus[i]);
583 if(corestatus[i] != 0) {
589 // check if the sum of send objs and receive obj are the same
590 // yes->terminate; for profiling mode, yes->send request to all
591 // other cores to pour out profiling data
592 // no->go on executing
594 for(i = 0; i < NUMCORES; ++i) {
595 sumsendobj += numsendobjs[i];
597 raw_test_pass(0xf000 + numsendobjs[i]);
600 for(i = 0; i < NUMCORES; ++i) {
601 sumsendobj -= numreceiveobjs[i];
603 raw_test_pass(0xf000 + numreceiveobjs[i]);
606 if(0 == sumsendobj) {
609 raw_test_pass(0xee11);
612 totalexetime = raw_get_cycle();
614 raw_test_pass(0xbbbbbbbb);
615 raw_test_pass(raw_get_cycle());
618 // profile mode, send msgs to other cores to request pouring
619 // out progiling data
622 // reopen gdn_avail interrupts
623 raw_user_interrupts_on();
625 for(i = 1; i < NUMCORES; ++i) {
626 transProfileRequestMsg(i);
628 // pour profiling data on startup core
632 raw_user_interrupts_off();
634 profilestatus[corenum] = 0;
635 // check the status of all cores
638 raw_test_pass_reg(NUMCORES);
640 for(i = 0; i < NUMCORES; ++i) {
642 raw_test_pass(0xe000 + profilestatus[i]);
644 if(profilestatus[i] != 0) {
652 raw_user_interrupts_on();
661 raw_test_done(1); // All done.
665 raw_user_interrupts_on();
670 raw_test_pass(0xee12);
676 // wait for some time
679 raw_test_pass(0xee13);
685 raw_test_pass(0xee14);
688 // send StallMsg to startup core
690 raw_test_pass(0xee15);
692 sendStall = transStallMsg(STARTUPCORE);
701 raw_test_pass(0xee16);
708 #elif defined THREADSIMULATE
709 /* Start executing the tasks */
713 // check if there are new objects coming
714 bool sendStall = false;
716 int numofcore = pthread_getspecific(key);
718 switch(receiveObject()) {
720 //printf("[run, %d] receive an object\n", numofcore);
722 // received an object
723 // check if there are new active tasks can be executed
729 //printf("[run, %d] no msg\n", numofcore);
731 if(STARTUPCORE == numofcore) {
732 corestatus[numofcore] = 0;
733 // check the status of all cores
734 bool allStall = true;
735 for(i = 0; i < NUMCORES; ++i) {
736 if(corestatus[i] != 0) {
742 // check if the sum of send objs and receive obj are the same
744 // no->go on executing
746 for(i = 0; i < NUMCORES; ++i) {
747 sumsendobj += numsendobjs[i];
749 for(i = 0; i < NUMCORES; ++i) {
750 sumsendobj -= numreceiveobjs[i];
752 if(0 == sumsendobj) {
756 int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
757 printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
758 struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
759 while(0 != RunhasNext(it_lock)) {
760 int key = Runkey(it_lock);
761 pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
762 int rc_des = pthread_rwlock_destroy(rwlock_obj);
763 printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
766 freeRuntimeHash(locktbl);
770 // destroy all message queues
771 char * pathhead = "/msgqueue_";
772 int targetlen = strlen(pathhead);
773 for(i = 0; i < NUMCORES; ++i) {
777 corenumstr[0] = i + '0';
778 corenumstr[1] = '\0';
781 corenumstr[1] = i %10 + '0';
782 corenumstr[0] = (i / 10) + '0';
783 corenumstr[2] = '\0';
786 printf("Error: i >= 100\n");
790 char path[targetlen + sourcelen + 1];
791 strcpy(path, pathhead);
792 strncat(path, corenumstr, sourcelen);
796 printf("[run, %d] terminate!\n", numofcore);
803 // send StallMsg to startup core
804 sendStall = transStallMsg(STARTUPCORE);
811 printf("[run, %d] receive a stall msg\n", numofcore);
812 // receive a Stall Msg, do nothing
813 assert(STARTUPCORE == numofcore); // only startup core can receive such msg
819 printf("[run, %d] Error: invalid message type.\n", numofcore);
829 void createstartupobject(int argc, char ** argv) {
832 /* Allocate startup object */
834 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
835 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
837 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
838 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
840 /* Build array of strings */
841 startupobject->___parameters___=stringarray;
842 for(i=1; i<argc; i++) {
843 int length=strlen(argv[i]);
845 struct ___String___ *newstring=NewString(NULL, argv[i],length);
847 struct ___String___ *newstring=NewString(argv[i],length);
849 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
852 startupobject->isolate = 1;
853 startupobject->version = 0;
854 startupobject->lock = NULL;
856 /* Set initialized flag for startup object */
857 flagorandinit(startupobject,1,0xFFFFFFFF);
858 enqueueObject(startupobject, NULL, 0);
860 raw_flush_entire_cache();
864 int hashCodetpd(struct taskparamdescriptor *ftd) {
865 int hash=(int)ftd->task;
867 for(i=0; i<ftd->numParameters; i++) {
868 hash^=(int)ftd->parameterArray[i];
873 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
875 if (ftd1->task!=ftd2->task)
877 for(i=0; i<ftd1->numParameters; i++)
878 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
883 /* This function sets a tag. */
885 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
887 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
889 struct ArrayObject * ao=NULL;
890 struct ___Object___ * tagptr=obj->___tags___;
892 raw_test_pass(0xebb0);
896 raw_test_pass(0xebb1);
898 obj->___tags___=(struct ___Object___ *)tagd;
900 /* Have to check if it is already set */
901 if (tagptr->type==TAGTYPE) {
902 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
904 raw_test_pass(0xebb2);
908 raw_test_pass(0xebb3);
913 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
914 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
915 obj=(struct ___Object___ *)ptrarray[2];
916 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
917 td=(struct ___TagDescriptor___ *) obj->___tags___;
920 raw_test_pass(0xebb4);
922 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
925 raw_test_pass(0xebb5);
927 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
928 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
929 obj->___tags___=(struct ___Object___ *) ao;
930 ao->___cachedCode___=2;
932 raw_test_pass(0xebb6);
937 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
939 raw_test_pass(0xebb7);
941 for(i=0; i<ao->___cachedCode___; i++) {
942 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
944 raw_test_pass(0xebb8);
948 raw_test_pass(0xebb9);
953 if (ao->___cachedCode___<ao->___length___) {
955 raw_test_pass(0xebba);
957 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
958 ao->___cachedCode___++;
960 raw_test_pass(0xebbb);
964 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
965 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
966 obj=(struct ___Object___ *)ptrarray[2];
967 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
968 ao=(struct ArrayObject *)obj->___tags___;
970 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
973 raw_test_pass(0xebbc);
975 aonew->___cachedCode___=ao->___length___+1;
976 for(i=0; i<ao->___length___; i++) {
978 raw_test_pass(0xebbd);
980 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
983 raw_test_pass(0xebbe);
985 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
987 raw_test_pass(0xebbf);
994 struct ___Object___ * tagset=tagd->flagptr;
996 raw_test_pass(0xb008);
1000 raw_test_pass(0xb009);
1003 } else if (tagset->type!=OBJECTARRAYTYPE) {
1005 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1006 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1007 obj=(struct ___Object___ *)ptrarray[2];
1008 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1010 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1012 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
1013 ARRAYSET(ao, struct ___Object___ *, 1, obj);
1014 ao->___cachedCode___=2;
1015 tagd->flagptr=(struct ___Object___ *)ao;
1017 raw_test_pass(0xb00a);
1020 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1021 if (ao->___cachedCode___<ao->___length___) {
1023 raw_test_pass(0xb00b);
1025 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
1029 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1030 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
1031 obj=(struct ___Object___ *)ptrarray[2];
1032 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1033 ao=(struct ArrayObject *)tagd->flagptr;
1035 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1037 aonew->___cachedCode___=ao->___cachedCode___+1;
1038 for(i=0; i<ao->___length___; i++) {
1039 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
1041 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
1042 tagd->flagptr=(struct ___Object___ *) aonew;
1044 raw_test_pass(0xb00c);
1051 /* This function clears a tag. */
1053 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1055 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1057 /* We'll assume that tag is alway there.
1058 Need to statically check for this of course. */
1059 struct ___Object___ * tagptr=obj->___tags___;
1061 if (tagptr->type==TAGTYPE) {
1062 if ((struct ___TagDescriptor___ *)tagptr==tagd)
1063 obj->___tags___=NULL;
1066 printf("ERROR 1 in tagclear\n");
1070 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1072 for(i=0; i<ao->___cachedCode___; i++) {
1073 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
1075 ao->___cachedCode___--;
1076 if (i<ao->___cachedCode___)
1077 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
1078 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
1079 if (ao->___cachedCode___==0)
1080 obj->___tags___=NULL;
1085 printf("ERROR 2 in tagclear\n");
1091 struct ___Object___ *tagset=tagd->flagptr;
1092 if (tagset->type!=OBJECTARRAYTYPE) {
1097 printf("ERROR 3 in tagclear\n");
1101 struct ArrayObject *ao=(struct ArrayObject *) tagset;
1103 for(i=0; i<ao->___cachedCode___; i++) {
1104 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
1106 ao->___cachedCode___--;
1107 if (i<ao->___cachedCode___)
1108 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
1109 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
1110 if (ao->___cachedCode___==0)
1116 printf("ERROR 4 in tagclear\n");
1124 /* This function allocates a new tag. */
1126 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
1127 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
1129 struct ___TagDescriptor___ * allocate_tag(int index) {
1130 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
1139 /* This function updates the flag for object ptr. It or's the flag
1140 with the or mask and and's it with the andmask. */
1142 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
1144 int flagcomp(const int *val1, const int *val2) {
1145 return (*val1)-(*val2);
1148 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
1150 int oldflag=((int *)ptr)[1];
1151 int flag=ormask|oldflag;
1154 raw_test_pass_reg((int)ptr);
1155 raw_test_pass(0xaa000000 + oldflag);
1156 raw_test_pass(0xaa000000 + flag);
1158 flagbody(ptr, flag, queues, length, false);
1162 bool intflagorand(void * ptr, int ormask, int andmask) {
1164 int oldflag=((int *)ptr)[1];
1165 int flag=ormask|oldflag;
1167 if (flag==oldflag) /* Don't do anything */
1170 flagbody(ptr, flag, NULL, 0, false);
1176 void flagorandinit(void * ptr, int ormask, int andmask) {
1177 int oldflag=((int *)ptr)[1];
1178 int flag=ormask|oldflag;
1181 raw_test_pass(0xaa100000 + oldflag);
1182 raw_test_pass(0xaa100000 + flag);
1184 flagbody(ptr,flag,NULL,0,true);
1187 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1188 struct parameterwrapper * flagptr = NULL;
1190 struct parameterwrapper ** queues = vqueues;
1191 int length = vlength;
1193 int UNUSED, UNUSED2;
1194 int * enterflags = NULL;
1195 if((!isnew) && (queues == NULL)) {
1196 #ifdef THREADSIMULATE
1197 int numofcore = pthread_getspecific(key);
1198 queues = objectqueues[numofcore][ptr->type];
1199 length = numqueues[numofcore][ptr->type];
1202 if(corenum < NUMCORES) {
1204 queues = objectqueues[corenum][ptr->type];
1205 length = numqueues[corenum][ptr->type];
1215 raw_test_pass(0xbb000000 + ptr->flag);
1218 /*Remove object from all queues */
1219 for(i = 0; i < length; ++i) {
1220 flagptr = queues[i];
1221 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1222 ObjectHashremove(flagptr->objectset, (int)ptr);
1223 if (enterflags!=NULL)
1224 RUNFREE(enterflags);
1228 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1229 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1232 struct QueueItem *tmpptr;
1233 struct parameterwrapper * parameter=NULL;
1236 struct parameterwrapper * prevptr=NULL;
1237 struct ___Object___ *tagptr=NULL;
1238 struct parameterwrapper ** queues = vqueues;
1239 int length = vlength;
1241 if(corenum > NUMCORES - 1) {
1245 if(queues == NULL) {
1246 #ifdef THREADSIMULATE
1247 int numofcore = pthread_getspecific(key);
1248 queues = objectqueues[numofcore][ptr->type];
1249 length = numqueues[numofcore][ptr->type];
1251 queues = objectqueues[corenum][ptr->type];
1252 length = numqueues[corenum][ptr->type];
1255 tagptr=ptr->___tags___;
1257 /* Outer loop iterates through all parameter queues an object of
1258 this type could be in. */
1259 for(j = 0; j < length; ++j) {
1260 parameter = queues[j];
1262 if (parameter->numbertags>0) {
1264 goto nextloop; //that means the object has no tag but that param needs tag
1265 else if(tagptr->type==TAGTYPE) { //one tag
1266 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1267 for(i=0; i<parameter->numbertags; i++) {
1268 //slotid is parameter->tagarray[2*i];
1269 int tagid=parameter->tagarray[2*i+1];
1270 if (tagid!=tagptr->flag)
1271 goto nextloop; /*We don't have this tag */
1273 } else { //multiple tags
1274 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1275 for(i=0; i<parameter->numbertags; i++) {
1276 //slotid is parameter->tagarray[2*i];
1277 int tagid=parameter->tagarray[2*i+1];
1279 for(j=0; j<ao->___cachedCode___; j++) {
1280 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) {
1296 raw_test_pass(0xcc000000 + andmask);
1297 raw_test_pass_reg((int)ptr);
1298 raw_test_pass(0xcc000000 + ptr->flag);
1299 raw_test_pass(0xcc000000 + checkmask);
1301 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1313 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1314 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1317 struct QueueItem *tmpptr;
1318 struct parameterwrapper * parameter=NULL;
1321 struct parameterwrapper * prevptr=NULL;
1322 struct ___Object___ *tagptr=NULL;
1323 struct parameterwrapper ** queues = vqueues;
1324 int length = vlength;
1326 if(corenum > NUMCORES - 1) {
1330 if(queues == NULL) {
1331 #ifdef THREADSIMULATE
1332 int numofcore = pthread_getspecific(key);
1333 queues = objectqueues[numofcore][ptr->type];
1334 length = numqueues[numofcore][ptr->type];
1336 queues = objectqueues[corenum][ptr->type];
1337 length = numqueues[corenum][ptr->type];
1341 raw_test_pass(0xeaa1);
1342 raw_test_pass_reg(queues);
1343 raw_test_pass_reg(length);
1345 tagptr=ptr->___tags___;
1347 /* Outer loop iterates through all parameter queues an object of
1348 this type could be in. */
1349 for(j = 0; j < length; ++j) {
1350 parameter = queues[j];
1352 if (parameter->numbertags>0) {
1354 raw_test_pass(0xeaa2);
1355 raw_test_pass_reg(tagptr);
1358 goto nextloop; //that means the object has no tag but that param needs tag
1359 else if(tagptr->type==TAGTYPE) { //one tag
1360 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1362 raw_test_pass(0xeaa3);
1364 for(i=0; i<parameter->numbertags; i++) {
1365 //slotid is parameter->tagarray[2*i];
1366 int tagid=parameter->tagarray[2*i+1];
1367 if (tagid!=tagptr->flag) {
1369 raw_test_pass(0xeaa4);
1371 goto nextloop; /*We don't have this tag */
1374 } else { //multiple tags
1375 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1377 raw_test_pass(0xeaa5);
1379 for(i=0; i<parameter->numbertags; i++) {
1380 //slotid is parameter->tagarray[2*i];
1381 int tagid=parameter->tagarray[2*i+1];
1383 for(j=0; j<ao->___cachedCode___; j++) {
1384 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1389 raw_test_pass(0xeaa6);
1399 for(i=0; i<parameter->numberofterms; i++) {
1400 int andmask=parameter->intarray[i*2];
1401 int checkmask=parameter->intarray[i*2+1];
1403 raw_test_pass(0xeaa7);
1404 raw_test_pass(0xcc000000 + andmask);
1405 raw_test_pass_reg(ptr);
1406 raw_test_pass(0xcc000000 + ptr->flag);
1407 raw_test_pass(0xcc000000 + checkmask);
1409 if ((ptr->flag&andmask)==checkmask) {
1411 raw_test_pass(0xeaa8);
1413 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1424 // helper function to compute the coordinates of a core from the core number
1425 void calCoords(int core_num, int* coordY, int* coordX) {
1426 *coordX = core_num % 4;
1427 *coordY = core_num / 4;
1431 int * getAliasLock(void ** ptrs, int length, struct RuntimeHash * tbl) {
1433 return (int*)(RUNMALLOC(sizeof(int)));
1438 bool redirect = false;
1439 int redirectlock = 0;
1440 for(; i < length; i++) {
1441 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1444 if(ptr->lock == NULL) {
1447 lock = (int)(ptr->lock);
1450 if(lock != redirectlock) {
1451 RuntimeHashadd(tbl, lock, redirectlock);
1454 if(RuntimeHashcontainskey(tbl, lock)) {
1455 // already redirected
1457 RuntimeHashget(tbl, lock, &redirectlock);
1458 for(; j < locklen; j++) {
1459 if(locks[j] != redirectlock) {
1460 RuntimeHashadd(tbl, locks[j], redirectlock);
1465 for(j = 0; j < locklen; j++) {
1466 if(locks[j] == lock) {
1469 } else if(locks[j] > lock) {
1476 locks[h] = locks[h-1];
1485 return (int *)redirectlock;
1487 return (int *)(locks[0]);
1492 void addAliasLock(void * ptr, int lock) {
1493 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1494 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1495 // originally no alias lock associated or have a different alias lock
1496 // flush it as the new one
1497 obj->lock = (int *)lock;
1501 /* Message format for RAW version:
1503 * type: 0 -- transfer object
1504 * 1 -- transfer stall msg
1509 * // add for profile info
1510 * 6 -- transfer profile output msg
1511 * 7 -- transfer profile output finish msg
1512 * // add for alias lock strategy
1513 * 8 -- redirect lock request
1514 * 9 -- lock grant with redirect info
1515 * a -- lock deny with redirect info
1516 * b -- lock release with redirect info
1518 * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1519 * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1520 * LockMsg: 2 + lock type + obj pointer + lock + request core (size is always 5 * sizeof(int))
1521 * 3/4/5 + lock type + obj pointer + lock (size is always 4 * sizeof(int))
1522 * 8 + lock type + obj pointer + redirect lock + root request core + request core (size is always 6 * sizeof(int))
1523 * 9/a + lock type + obj pointer + redirect lock (size is always 4 * sizeof(int))
1524 * b + lock type + lock + redirect lock (size is always 4 * sizeof(int))
1525 * lock type: 0 -- read; 1 -- write
1526 * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
1527 * 7 + corenum (size is always 2 * sizeof(int))
1530 // transfer an object to targetcore
1532 void transferObject(struct transObjInfo * transObj) {
1533 void * obj = transObj->objptr;
1534 int type=((int *)obj)[0];
1535 int size=classsize[type];
1536 int targetcore = transObj->targetcore;
1540 int self_y, self_x, target_y, target_x;
1541 // for 32 bit machine, the size of fixed part is always 3 words
1542 int msgsize = 3 + transObj->length * 2;
1545 struct ___Object___ * newobj = (struct ___Object___ *)obj;
1547 calCoords(corenum, &self_y, &self_x);
1548 calCoords(targetcore, &target_y, &target_x);
1549 // Build the message header
1550 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1552 target_y, target_x);
1553 // start sending msg, set sand msg flag
1554 isMsgSending = true;
1555 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1557 raw_test_pass(0xbbbb);
1558 raw_test_pass(0xb000 + targetcore); // targetcore
1566 raw_test_pass_reg(msgsize);
1570 raw_test_pass_reg(obj);
1572 for(i = 0; i < transObj->length; ++i) {
1573 int taskindex = transObj->queues[2*i];
1574 int paramindex = transObj->queues[2*i+1];
1575 gdn_send(taskindex);
1577 raw_test_pass_reg(taskindex);
1579 gdn_send(paramindex);
1581 raw_test_pass_reg(paramindex);
1585 raw_test_pass(0xffff);
1587 ++(self_numsendobjs);
1588 // end of sending this msg, set sand msg flag false
1589 isMsgSending = false;
1590 // check if there are pending msgs
1591 while(isMsgHanging) {
1592 // get the msg from outmsgdata[]
1593 // length + target + msg
1594 outmsgleft = outmsgdata[outmsgindex++];
1595 targetcore = outmsgdata[outmsgindex++];
1596 calCoords(targetcore, &target_y, &target_x);
1597 // Build the message header
1598 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1600 target_y, target_x);
1601 isMsgSending = true;
1604 raw_test_pass(0xbbbb);
1605 raw_test_pass(0xb000 + targetcore); // targetcore
1607 while(outmsgleft-- > 0) {
1608 gdn_send(outmsgdata[outmsgindex++]);
1610 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1614 raw_test_pass(0xffff);
1616 isMsgSending = false;
1618 raw_user_interrupts_off();
1620 // check if there are still msg hanging
1621 if(outmsgindex == outmsglast) {
1623 outmsgindex = outmsglast = 0;
1624 isMsgHanging = false;
1627 raw_user_interrupts_on();
1630 #elif defined THREADSIMULATE
1631 int numofcore = pthread_getspecific(key);
1633 // use POSIX message queue to transfer objects between cores
1637 if(targetcore < 10) {
1638 corenumstr[0] = targetcore + '0';
1639 corenumstr[1] = '\0';
1641 } else if(targetcore < 100) {
1642 corenumstr[1] = targetcore % 10 + '0';
1643 corenumstr[0] = (targetcore / 10) + '0';
1644 corenumstr[2] = '\0';
1647 printf("Error: targetcore >= 100\n");
1651 char * pathhead = "/msgqueue_";
1652 int targetlen = strlen(pathhead);
1653 char path[targetlen + sourcelen + 1];
1654 strcpy(path, pathhead);
1655 strncat(path, corenumstr, sourcelen);
1656 int oflags = O_WRONLY|O_NONBLOCK;
1657 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1658 mqdnum = mq_open(path, oflags, omodes, NULL);
1660 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1664 struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1665 memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1666 int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1667 memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1668 tmptransObj->queues = tmpqueue;
1669 struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1670 newobj->type = ((struct ___Object___ *)obj)->type;
1671 newobj->original = (struct ___Object___ *)tmptransObj;
1674 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1676 printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1680 if(numofcore == STARTUPCORE) {
1681 ++numsendobjs[numofcore];
1683 ++(thread_data_array[numofcore].numsendobjs);
1685 printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1689 // send terminate message to targetcore
1691 bool transStallMsg(int targetcore) {
1694 int self_y, self_x, target_y, target_x;
1695 // for 32 bit machine, the size is always 4 words
1696 //int msgsize = sizeof(int) * 4;
1699 calCoords(corenum, &self_y, &self_x);
1700 calCoords(targetcore, &target_y, &target_x);
1701 // Build the message header
1702 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1704 target_y, target_x);
1705 // start sending msgs, set msg sending flag
1706 isMsgSending = true;
1707 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1709 raw_test_pass(0xbbbb);
1710 raw_test_pass(0xb000 + targetcore); // targetcore
1718 raw_test_pass_reg(corenum);
1720 gdn_send(self_numsendobjs);
1722 raw_test_pass_reg(self_numsendobjs);
1724 gdn_send(self_numreceiveobjs);
1726 raw_test_pass_reg(self_numreceiveobjs);
1727 raw_test_pass(0xffff);
1729 // end of sending this msg, set sand msg flag false
1730 isMsgSending = false;
1731 // check if there are pending msgs
1732 while(isMsgHanging) {
1733 // get the msg from outmsgdata[]
1734 // length + target + msg
1735 outmsgleft = outmsgdata[outmsgindex++];
1736 targetcore = outmsgdata[outmsgindex++];
1737 calCoords(targetcore, &target_y, &target_x);
1738 // Build the message header
1739 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1741 target_y, target_x);
1742 isMsgSending = true;
1743 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1745 raw_test_pass(0xbbbb);
1746 raw_test_pass(0xb000 + targetcore); // targetcore
1748 while(outmsgleft-- > 0) {
1749 gdn_send(outmsgdata[outmsgindex++]);
1751 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1755 raw_test_pass(0xffff);
1757 isMsgSending = false;
1759 raw_user_interrupts_off();
1761 // check if there are still msg hanging
1762 if(outmsgindex == outmsglast) {
1764 outmsgindex = outmsglast = 0;
1765 isMsgHanging = false;
1768 raw_user_interrupts_on();
1772 #elif defined THREADSIMULATE
1773 struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1774 // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1776 int numofcore = pthread_getspecific(key);
1777 newobj->flag = numofcore;
1778 newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1779 newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1781 // use POSIX message queue to send stall msg to startup core
1782 assert(targetcore == STARTUPCORE);
1786 if(targetcore < 10) {
1787 corenumstr[0] = targetcore + '0';
1788 corenumstr[1] = '\0';
1790 } else if(targetcore < 100) {
1791 corenumstr[1] = targetcore % 10 + '0';
1792 corenumstr[0] = (targetcore / 10) + '0';
1793 corenumstr[2] = '\0';
1796 printf("Error: targetcore >= 100\n");
1800 char * pathhead = "/msgqueue_";
1801 int targetlen = strlen(pathhead);
1802 char path[targetlen + sourcelen + 1];
1803 strcpy(path, pathhead);
1804 strncat(path, corenumstr, sourcelen);
1805 int oflags = O_WRONLY|O_NONBLOCK;
1806 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1807 mqdnum = mq_open(path, oflags, omodes, NULL);
1809 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1814 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1816 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1820 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1821 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1829 // send profile request message to targetcore
1831 bool transProfileRequestMsg(int targetcore) {
1833 int self_y, self_x, target_y, target_x;
1834 // for 32 bit machine, the size is always 4 words
1837 calCoords(corenum, &self_y, &self_x);
1838 calCoords(targetcore, &target_y, &target_x);
1839 // Build the message header
1840 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
1842 target_y, target_x);
1843 // start sending msgs, set msg sending flag
1844 isMsgSending = true;
1845 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
1847 raw_test_pass(0xbbbb);
1848 raw_test_pass(0xb000 + targetcore); // targetcore
1854 gdn_send(totalexetime);
1856 raw_test_pass_reg(totalexetime);
1857 raw_test_pass(0xffff);
1859 // end of sending this msg, set sand msg flag false
1860 isMsgSending = false;
1861 // check if there are pending msgs
1862 while(isMsgHanging) {
1863 // get the msg from outmsgdata[]
1864 // length + target + msg
1865 outmsgleft = outmsgdata[outmsgindex++];
1866 targetcore = outmsgdata[outmsgindex++];
1867 calCoords(targetcore, &target_y, &target_x);
1868 // Build the message header
1869 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
1871 target_y, target_x);
1872 isMsgSending = true;
1875 raw_test_pass(0xbbbb);
1876 raw_test_pass(0xb000 + targetcore); // targetcore
1878 while(outmsgleft-- > 0) {
1879 gdn_send(outmsgdata[outmsgindex++]);
1881 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1885 raw_test_pass(0xffff);
1887 isMsgSending = false;
1889 raw_user_interrupts_off();
1891 // check if there are still msg hanging
1892 if(outmsgindex == outmsglast) {
1894 outmsgindex = outmsglast = 0;
1895 isMsgHanging = false;
1898 raw_user_interrupts_on();
1904 // output the profiling data
1905 void outputProfileData() {
1912 int totaltasktime = 0;
1913 int preprocessingtime = 0;
1914 int objqueuecheckingtime = 0;
1915 int postprocessingtime = 0;
1916 //int interruptiontime = 0;
1918 int averagetasktime = 0;
1921 for(i = 0; i < 50; i++) {
1925 calCoords(corenum, &self_y, &self_x);
1926 c_y = (char)self_y + '0';
1927 c_x = (char)self_x + '0';
1928 strcat(fn, "profile_");
1934 if((fp = fopen(fn, "w+")) == NULL) {
1935 fprintf(stderr, "fopen error\n");
1939 fprintf(fp, "Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
1940 // output task related info
1941 for(i = 0; i < taskInfoIndex; i++) {
1942 TaskInfo* tmpTInfo = taskInfoArray[i];
1943 int duration = tmpTInfo->endTime - tmpTInfo->startTime;
1944 fprintf(fp, "%s, %d, %d, %d, %d", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration, tmpTInfo->exitIndex);
1945 // summarize new obj info
1946 if(tmpTInfo->newObjs != NULL) {
1947 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
1948 struct RuntimeIterator * iter = NULL;
1949 while(0 == isEmpty(tmpTInfo->newObjs)) {
1950 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
1951 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
1953 RuntimeHashget(nobjtbl, (int)objtype, &num);
1954 RuntimeHashremovekey(nobjtbl, (int)objtype);
1956 RuntimeHashadd(nobjtbl, (int)objtype, num);
1958 RuntimeHashadd(nobjtbl, (int)objtype, 1);
1960 //fprintf(stderr, "new obj!\n");
1963 // output all new obj info
1964 iter = RuntimeHashcreateiterator(nobjtbl);
1965 while(RunhasNext(iter)) {
1966 char * objtype = (char *)Runkey(iter);
1967 int num = Runnext(iter);
1968 fprintf(fp, ", %s, %d", objtype, num);
1972 if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
1973 preprocessingtime += duration;
1974 } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
1975 postprocessingtime += duration;
1976 } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
1977 objqueuecheckingtime += duration;
1979 totaltasktime += duration;
1980 averagetasktime += duration;
1985 if(taskInfoOverflow) {
1986 fprintf(stderr, "Caution: task info overflow!\n");
1989 other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
1990 averagetasktime /= tasknum;
1992 fprintf(fp, "\nTotal time: %d\n", totalexetime);
1993 fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
1994 fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
1995 fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
1996 fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
1997 fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
1999 fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
2006 raw_test_pass(0xdddd);
2007 // output task related info
2008 for(i= 0; i < taskInfoIndex; i++) {
2009 TaskInfo* tmpTInfo = taskInfoArray[i];
2010 char* tmpName = tmpTInfo->taskName;
2011 int nameLen = strlen(tmpName);
2012 raw_test_pass(0xddda);
2013 for(j = 0; j < nameLen; j++) {
2014 raw_test_pass_reg(tmpName[j]);
2016 raw_test_pass(0xdddb);
2017 raw_test_pass_reg(tmpTInfo->startTime);
2018 raw_test_pass_reg(tmpTInfo->endTime);
2019 raw_test_pass_reg(tmpTInfo->exitIndex);
2020 if(tmpTInfo->newObjs != NULL) {
2021 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
2022 struct RuntimeIterator * iter = NULL;
2023 while(0 == isEmpty(tmpTInfo->newObjs)) {
2024 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
2025 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
2027 RuntimeHashget(nobjtbl, (int)objtype, &num);
2028 RuntimeHashremovekey(nobjtbl, (int)objtype);
2030 RuntimeHashadd(nobjtbl, (int)objtype, num);
2032 RuntimeHashadd(nobjtbl, (int)objtype, 1);
2036 // ouput all new obj info
2037 iter = RuntimeHashcreateiterator(nobjtbl);
2038 while(RunhasNext(iter)) {
2039 char * objtype = (char *)Runkey(iter);
2040 int num = Runnext(iter);
2041 int nameLen = strlen(objtype);
2042 raw_test_pass(0xddda);
2043 for(j = 0; j < nameLen; j++) {
2044 raw_test_pass_reg(objtype[j]);
2046 raw_test_pass(0xdddb);
2047 raw_test_pass_reg(num);
2050 raw_test_pass(0xdddc);
2053 if(taskInfoOverflow) {
2054 raw_test_pass(0xefee);
2057 // output interrupt related info
2058 /*for(i = 0; i < interruptInfoIndex; i++) {
2059 InterruptInfo* tmpIInfo = interruptInfoArray[i];
2060 raw_test_pass(0xddde);
2061 raw_test_pass_reg(tmpIInfo->startTime);
2062 raw_test_pass_reg(tmpIInfo->endTime);
2063 raw_test_pass(0xdddf);
2066 if(interruptInfoOverflow) {
2067 raw_test_pass(0xefef);
2070 raw_test_pass(0xeeee);
2074 inline void setTaskExitIndex(int index) {
2075 taskInfoArray[taskInfoIndex]->exitIndex = index;
2078 inline void addNewObjInfo(void * nobj) {
2079 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
2080 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
2082 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
2086 // receive object transferred from other cores
2087 // or the terminate message from other cores
2088 // NOTICE: following format is for threadsimulate version only
2089 // RAW version please see previous description
2090 // format: type + object
2091 // type: -1--stall msg
2093 // return value: 0--received an object
2094 // 1--received nothing
2095 // 2--received a Stall Msg
2096 // 3--received a lock Msg
2097 // RAW version: -1 -- received nothing
2098 // otherwise -- received msg type
2099 int receiveObject() {
2103 int self_y, self_x, target_y, target_x;
2105 if(gdn_input_avail() == 0) {
2107 if(corenum < NUMCORES) {
2108 raw_test_pass(0xd001);
2114 /*if(isInterrupt && (!interruptInfoOverflow)) {
2115 // raw_test_pass(0xffff);
2116 interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
2117 interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
2118 interruptInfoArray[interruptInfoIndex]->endTime = -1;
2123 raw_test_pass(0xcccc);
2125 while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
2126 msgdata[msgdataindex] = gdn_receive();
2127 if(msgdataindex == 0) {
2128 if(msgdata[0] > 8) {
2130 } else if(msgdata[0] == 8) {
2132 } else if(msgdata[0] > 5) {
2134 } else if (msgdata[0] > 2) {
2136 } else if (msgdata[0] == 2) {
2138 } else if (msgdata[0] > 0) {
2141 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
2142 msglength = msgdata[msgdataindex];
2145 raw_test_pass_reg(msgdata[msgdataindex]);
2150 raw_test_pass(0xffff);
2152 if(msgdataindex == msglength) {
2153 // received a whole msg
2154 int type, data1; // will receive at least 2 words including type
2159 // receive a object transfer msg
2160 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
2162 if(corenum > NUMCORES - 1) {
2163 raw_test_done(0xa001);
2165 // store the object and its corresponding queue info, enqueue it later
2166 transObj->objptr = (void *)msgdata[2]; // data1 is now size of the msg
2167 transObj->length = (msglength - 3) / 2;
2168 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
2169 for(k = 0; k < transObj->length; ++k) {
2170 transObj->queues[2*k] = msgdata[3+2*k];
2172 raw_test_pass_reg(transObj->queues[2*k]);
2174 transObj->queues[2*k+1] = msgdata[3+2*k+1];
2176 raw_test_pass_reg(transObj->queues[2*k+1]);
2179 // check if there is an existing duplicate item
2181 struct QueueItem * qitem = getTail(&objqueue);
2182 struct QueueItem * prev = NULL;
2183 while(qitem != NULL) {
2184 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
2185 if(tmpinfo->objptr == transObj->objptr) {
2186 // the same object, remove outdate one
2187 removeItem(&objqueue, qitem);
2192 qitem = getTail(&objqueue);
2194 qitem = getNextQueueItem(prev);
2197 addNewItem_I(&objqueue, (void *)transObj);
2199 ++(self_numreceiveobjs);
2201 raw_test_pass(0xe881);
2207 // receive a stall msg
2208 if(corenum != STARTUPCORE) {
2209 // non startup core can not receive stall msg
2211 raw_test_done(0xa002);
2213 if(data1 < NUMCORES) {
2215 raw_test_pass(0xe882);
2217 corestatus[data1] = 0;
2218 numsendobjs[data1] = msgdata[2];
2219 numreceiveobjs[data1] = msgdata[3];
2225 // receive lock request msg
2226 // for 32 bit machine, the size is always 4 words
2227 //int msgsize = sizeof(int) * 4;
2229 // lock request msg, handle it right now
2230 // check to see if there is a lock exist in locktbl for the required obj
2231 // data1 -> lock type
2232 int data2 = msgdata[2]; // obj pointer
2233 int data3 = msgdata[3]; // lock
2234 int data4 = msgdata[4]; // request core
2236 if(!RuntimeHashcontainskey(locktbl, data3)) {
2237 // no locks for this object
2238 // first time to operate on this shared object
2239 // create a lock for it
2240 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2241 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2242 lockvalue->redirectlock = 0;
2244 raw_test_pass(0xe883);
2247 lockvalue->value = 1;
2249 lockvalue->value = -1;
2251 RuntimeHashadd_I(locktbl, data3, (int)lockvalue);
2254 struct LockValue * lockvalue = NULL;
2256 raw_test_pass(0xe884);
2258 RuntimeHashget(locktbl, data3, &rwlock_obj);
2259 lockvalue = (struct LockValue *)(rwlock_obj);
2261 raw_test_pass_reg(lockvalue->redirectlock);
2263 if(lockvalue->redirectlock != 0) {
2264 // this lock is redirected
2266 raw_test_pass(0xe885);
2269 getreadlock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2271 getwritelock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2276 raw_test_pass_reg(lockvalue->value);
2278 if(0 == lockvalue->value) {
2280 lockvalue->value = 1;
2282 lockvalue->value = -1;
2284 } else if((lockvalue->value > 0) && (data1 == 0)) {
2285 // read lock request and there are only read locks
2291 raw_test_pass_reg(lockvalue->value);
2296 // check if there is still some msg on sending
2299 raw_test_pass(0xe886);
2301 isMsgHanging = true;
2302 // cache the msg in outmsgdata and send it later
2303 // msglength + target core + msg
2304 outmsgdata[outmsglast++] = msgsize;
2305 outmsgdata[outmsglast++] = targetcore;
2307 outmsgdata[outmsglast++] = 4;
2309 outmsgdata[outmsglast++] = 3;
2311 outmsgdata[outmsglast++] = data1;
2312 outmsgdata[outmsglast++] = data2;
2313 outmsgdata[outmsglast++] = data3;
2316 raw_test_pass(0xe887);
2318 // no msg on sending, send it out
2319 calCoords(corenum, &self_y, &self_x);
2320 calCoords(targetcore, &target_y, &target_x);
2321 // Build the message header
2322 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2324 target_y, target_x);
2325 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2327 raw_test_pass(0xbbbb);
2328 raw_test_pass(0xb000 + targetcore); // targetcore
2331 // deny the lock request
2332 gdn_send(4); // lock request
2337 // grount the lock request
2338 gdn_send(3); // lock request
2343 gdn_send(data1); // lock type
2345 raw_test_pass_reg(data1);
2347 gdn_send(data2); // obj pointer
2349 raw_test_pass_reg(data2);
2351 gdn_send(data3); // lock
2353 raw_test_pass_reg(data3);
2354 raw_test_pass(0xffff);
2361 // receive lock grount msg
2362 if(corenum > NUMCORES - 1) {
2363 raw_test_done(0xa003);
2365 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
2372 // conflicts on lockresults
2373 raw_test_done(0xa004);
2379 // receive lock grount/deny msg
2380 if(corenum > NUMCORES - 1) {
2381 raw_test_done(0xa005);
2383 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
2390 // conflicts on lockresults
2391 raw_test_done(0xa006);
2397 // receive lock release msg
2398 if(!RuntimeHashcontainskey(locktbl, msgdata[3])) {
2399 // no locks for this object, something is wrong
2400 //raw_test_pass_reg(msgdata[3]);
2401 raw_test_done(0xa007);
2404 struct LockValue * lockvalue = NULL;
2405 RuntimeHashget(locktbl, msgdata[3], &rwlock_obj);
2406 lockvalue = (struct LockValue*)(rwlock_obj);
2408 raw_test_pass(0xe888);
2409 raw_test_pass_reg(lockvalue->value);
2417 raw_test_pass_reg(lockvalue->value);
2425 // receive an output request msg
2426 if(corenum == STARTUPCORE) {
2427 // startup core can not receive profile output finish msg
2428 raw_test_done(0xa008);
2433 totalexetime = data1;
2434 outputProfileData();
2435 /*if(data1 >= NUMCORES) {
2436 raw_test_pass(0xee04);
2437 raw_test_pass_reg(taskInfoIndex);
2438 raw_test_pass_reg(taskInfoOverflow);
2439 if(!taskInfoOverflow) {
2440 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
2442 if(taskInfoIndex == TASKINFOLENGTH) {
2443 taskInfoOverflow = true;
2447 // no msg on sending, send it out
2448 targetcore = STARTUPCORE;
2449 calCoords(corenum, &self_y, &self_x);
2450 calCoords(targetcore, &target_y, &target_x);
2451 // Build the message header
2452 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2454 target_y, target_x);
2457 raw_test_pass(0xbbbb);
2458 raw_test_pass(0xb000 + targetcore); // targetcore
2466 raw_test_pass_reg(corenum);
2467 raw_test_pass(0xffff);
2474 // receive a profile output finish msg
2475 if(corenum != STARTUPCORE) {
2476 // non startup core can not receive profile output finish msg
2477 raw_test_done(0xa009);
2479 profilestatus[data1] = 0;
2485 // receive a redirect lock request msg
2486 // for 32 bit machine, the size is always 4 words
2487 //int msgsize = sizeof(int) * 4;
2489 // lock request msg, handle it right now
2490 // check to see if there is a lock exist in locktbl for the required obj
2491 // data1 -> lock type
2492 int data2 = msgdata[2]; // obj pointer
2493 int data3 = msgdata[3]; // redirect lock
2494 int data4 = msgdata[4]; // root request core
2495 int data5 = msgdata[5]; // request core
2497 if(!RuntimeHashcontainskey(locktbl, data3)) {
2498 // no locks for this object
2499 // first time to operate on this shared object
2500 // create a lock for it
2501 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2502 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2503 lockvalue->redirectlock = 0;
2505 raw_test_pass(0xe889);
2508 lockvalue->value = 1;
2510 lockvalue->value = -1;
2512 RuntimeHashadd_I(locktbl, data3, (int)lockvalue);
2515 struct LockValue * lockvalue = NULL;
2517 raw_test_pass(0xe88a);
2519 RuntimeHashget(locktbl, data3, &rwlock_obj);
2520 lockvalue = (struct LockValue *)(rwlock_obj);
2522 raw_test_pass_reg(lockvalue->redirectlock);
2524 if(lockvalue->redirectlock != 0) {
2525 // this lock is redirected
2527 raw_test_pass(0xe88b);
2530 getreadlock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2532 getwritelock_I_r((void *)data2, (void *)lockvalue->redirectlock, data4, true);
2537 raw_test_pass_reg(lockvalue->value);
2539 if(0 == lockvalue->value) {
2541 lockvalue->value = 1;
2543 lockvalue->value = -1;
2545 } else if((lockvalue->value > 0) && (data1 == 0)) {
2546 // read lock request and there are only read locks
2552 raw_test_pass_reg(lockvalue->value);
2557 // check if there is still some msg on sending
2560 raw_test_pass(0xe88c);
2562 isMsgHanging = true;
2563 // cache the msg in outmsgdata and send it later
2564 // msglength + target core + msg
2565 outmsgdata[outmsglast++] = msgsize;
2566 outmsgdata[outmsglast++] = targetcore;
2568 outmsgdata[outmsglast++] = 0xa;
2570 outmsgdata[outmsglast++] = 9;
2572 outmsgdata[outmsglast++] = data1;
2573 outmsgdata[outmsglast++] = data2;
2574 outmsgdata[outmsglast++] = data3;
2577 raw_test_pass(0xe88d);
2579 // no msg on sending, send it out
2580 calCoords(corenum, &self_y, &self_x);
2581 calCoords(targetcore, &target_y, &target_x);
2582 // Build the message header
2583 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2585 target_y, target_x);
2586 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2588 raw_test_pass(0xbbbb);
2589 raw_test_pass(0xb000 + targetcore); // targetcore
2592 // deny the lock request
2593 gdn_send(0xa); // lock request
2598 // grount the lock request
2599 gdn_send(9); // lock request
2604 gdn_send(data1); // lock type
2606 raw_test_pass_reg(data1);
2608 gdn_send(data2); // obj pointer
2610 raw_test_pass_reg(data2);
2612 gdn_send(data3); // lock
2614 raw_test_pass_reg(data3);
2615 raw_test_pass(0xffff);
2622 // receive a lock grant msg with redirect info
2623 if(corenum > NUMCORES - 1) {
2624 raw_test_done(0xa00a);
2626 if(lockobj == msgdata[2]) {
2629 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
2634 // conflicts on lockresults
2635 raw_test_done(0xa00b);
2641 // receive a lock deny msg with redirect info
2642 if(corenum > NUMCORES - 1) {
2643 raw_test_done(0xa00c);
2645 if(lockobj == msgdata[2]) {
2648 //RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
2653 // conflicts on lockresults
2654 raw_test_done(0xa00d);
2660 // receive a lock release msg with redirect info
2661 if(!RuntimeHashcontainskey(locktbl, msgdata[2])) {
2662 // no locks for this object, something is wrong
2663 //raw_test_pass_reg(msgdata[2]);
2664 raw_test_done(0xa00e);
2667 struct LockValue * lockvalue = NULL;
2668 RuntimeHashget(locktbl, msgdata[2], &rwlock_obj);
2669 lockvalue = (struct LockValue*)(rwlock_obj);
2671 raw_test_pass(0xe88e);
2672 raw_test_pass_reg(lockvalue->value);
2680 raw_test_pass_reg(lockvalue->value);
2682 lockvalue->redirectlock = msgdata[3];
2690 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
2691 msgdata[msgdataindex] = -1;
2696 raw_test_pass(0xe88f);
2698 if(gdn_input_avail() != 0) {
2702 /* if(isInterrupt && (!interruptInfoOverflow)) {
2703 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2704 interruptInfoIndex++;
2705 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2706 interruptInfoOverflow = true;
2714 raw_test_pass(0xe890);
2717 /* if(isInterrupt && (!interruptInfoOverflow)) {
2718 interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2719 interruptInfoIndex++;
2720 if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2721 interruptInfoOverflow = true;
2727 #elif defined THREADSIMULATE
2728 int numofcore = pthread_getspecific(key);
2729 // use POSIX message queue to transfer object
2731 struct mq_attr mqattr;
2732 mq_getattr(mqd[numofcore], &mqattr);
2733 void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
2734 msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
2740 //printf("msg: %s\n",msgptr);
2741 if(((int*)msgptr)[0] == -1) {
2743 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2744 int index = tmpptr->flag;
2745 corestatus[index] = 0;
2746 numsendobjs[index] = tmpptr->___cachedHash___;
2747 numreceiveobjs[index] = tmpptr->___cachedCode___;
2748 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
2753 if(numofcore == STARTUPCORE) {
2754 ++(numreceiveobjs[numofcore]);
2756 ++(thread_data_array[numofcore].numreceiveobjs);
2758 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2759 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
2760 tmpptr = (struct ___Object___ *)(transObj->objptr);
2761 int type = tmpptr->type;
2762 int size=classsize[type];
2763 struct ___Object___ * newobj=RUNMALLOC(size);
2764 memcpy(newobj, tmpptr, size);
2765 if(0 == newobj->isolate) {
2766 newobj->original=tmpptr;
2771 for(k = 0; k < transObj->length; ++k) {
2772 int taskindex = transObj->queues[2 * k];
2773 int paramindex = transObj->queues[2 * k + 1];
2774 struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2775 enqueueObject(newobj, queues, 1);
2777 RUNFREE(transObj->queues);
2784 bool getreadlock(void * ptr) {
2787 int self_y, self_x, target_y, target_x;
2789 // for 32 bit machine, the size is always 5 words
2793 if(((struct ___Object___ *)ptr)->lock == NULL) {
2794 lock2require = lockobj;
2796 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
2798 targetcore = (lock2require >> 5) % TOTALCORE;
2805 if(targetcore == corenum) {
2806 // reside on this core
2809 raw_user_interrupts_off();
2811 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
2812 // no locks for this object
2813 // first time to operate on this shared object
2814 // create a lock for it
2815 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2816 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
2817 lockvalue->redirectlock = 0;
2818 lockvalue->value = 1;
2819 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
2822 struct LockValue* lockvalue;
2823 RuntimeHashget(locktbl, lock2require, &rwlock_obj);
2824 lockvalue = (struct LockValue*)rwlock_obj;
2825 if(lockvalue->redirectlock != 0) {
2826 // the lock is redirected
2827 getreadlock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
2830 if(-1 != lockvalue->value) {
2838 raw_user_interrupts_on();
2840 if(lockobj == (int)ptr) {
2851 // conflicts on lockresults
2852 raw_test_done(0xa00f);
2857 calCoords(corenum, &self_y, &self_x);
2858 calCoords(targetcore, &target_y, &target_x);
2859 // Build the message header
2860 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
2862 target_y, target_x);
2863 // start sending the msg, set send msg flag
2864 isMsgSending = true;
2865 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2867 raw_test_pass(0xbbbb);
2868 raw_test_pass(0xb000 + targetcore); // targetcore
2870 gdn_send(2); // lock request
2874 gdn_send(0); // read lock
2878 gdn_send((int)ptr); // obj pointer
2880 raw_test_pass_reg(ptr);
2882 gdn_send(lock2require); // lock
2884 raw_test_pass_reg(lock2require);
2886 gdn_send(corenum); // request core
2888 raw_test_pass_reg(corenum);
2889 raw_test_pass(0xffff);
2891 // end of sending this msg, set sand msg flag false
2892 isMsgSending = false;
2893 // check if there are pending msgs
2894 while(isMsgHanging) {
2895 // get the msg from outmsgdata[]
2896 // length + target + msg
2897 outmsgleft = outmsgdata[outmsgindex++];
2898 targetcore = outmsgdata[outmsgindex++];
2899 calCoords(targetcore, &target_y, &target_x);
2900 // Build the message header
2901 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
2903 target_y, target_x);
2904 isMsgSending = true;
2905 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
2907 raw_test_pass(0xbbbb);
2908 raw_test_pass(0xb000 + targetcore); // targetcore
2910 while(outmsgleft-- > 0) {
2911 gdn_send(outmsgdata[outmsgindex++]);
2913 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2917 raw_test_pass(0xffff);
2919 isMsgSending = false;
2921 raw_user_interrupts_off();
2923 // check if there are still msg hanging
2924 if(outmsgindex == outmsglast) {
2926 outmsgindex = outmsglast = 0;
2927 isMsgHanging = false;
2930 raw_user_interrupts_on();
2934 #elif defined THREADSIMULATE
2935 // TODO : need modification for alias lock
2936 int numofcore = pthread_getspecific(key);
2938 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2939 printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2943 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2944 // no locks for this object
2945 // first time to operate on this shared object
2946 // create a lock for it
2947 rc = pthread_rwlock_unlock(&rwlock_tbl);
2948 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2949 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2950 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2951 rc = pthread_rwlock_init(rwlock, NULL);
2952 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2953 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2954 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2959 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2961 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2964 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2966 rc = pthread_rwlock_unlock(&rwlock_tbl);
2967 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2969 rc = pthread_rwlock_tryrdlock(rwlock);
2970 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2977 pthread_rwlock_t* rwlock_obj = NULL;
2978 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2979 rc = pthread_rwlock_unlock(&rwlock_tbl);
2980 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2981 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
2982 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2992 void releasereadlock(void * ptr) {
2995 int self_y, self_x, target_y, target_x;
2997 // for 32 bit machine, the size is always 4 words
3001 if(((struct ___Object___ *)ptr)->lock == NULL) {
3002 reallock = (int)ptr;
3004 reallock = (int)(((struct ___Object___ *)ptr)->lock);
3006 targetcore = (reallock >> 5) % TOTALCORE;
3007 if(targetcore == corenum) {
3009 raw_user_interrupts_off();
3011 // reside on this core
3012 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3013 // no locks for this object, something is wrong
3014 raw_test_done(0xa010);
3017 struct LockValue * lockvalue = NULL;
3018 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3019 lockvalue = (struct LockValue *)rwlock_obj;
3023 raw_user_interrupts_on();
3028 calCoords(corenum, &self_y, &self_x);
3029 calCoords(targetcore, &target_y, &target_x);
3030 // Build the message header
3031 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3033 target_y, target_x);
3034 // start sending the msg, set send msg flag
3035 isMsgSending = true;
3036 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3038 raw_test_pass(0xbbbb);
3039 raw_test_pass(0xb000 + targetcore); // targetcore
3041 gdn_send(5); // lock release
3045 gdn_send(0); // read lock
3049 gdn_send((int)ptr); // obj pointer
3051 raw_test_pass_reg(ptr);
3053 gdn_send(reallock); // lock
3055 raw_test_pass_reg(reallock);
3056 raw_test_pass(0xffff);
3058 // end of sending this msg, set sand msg flag false
3059 isMsgSending = false;
3060 // check if there are pending msgs
3061 while(isMsgHanging) {
3062 // get the msg from outmsgdata[]
3063 // length + target + msg
3064 outmsgleft = outmsgdata[outmsgindex++];
3065 targetcore = outmsgdata[outmsgindex++];
3066 calCoords(targetcore, &target_y, &target_x);
3067 // Build the message header
3068 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3070 target_y, target_x);
3071 isMsgSending = true;
3072 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3074 raw_test_pass(0xbbbb);
3075 raw_test_pass(0xb000 + targetcore); // targetcore
3077 while(outmsgleft-- > 0) {
3078 gdn_send(outmsgdata[outmsgindex++]);
3080 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3084 raw_test_pass(0xffff);
3086 isMsgSending = false;
3088 raw_user_interrupts_off();
3090 // check if there are still msg hanging
3091 if(outmsgindex == outmsglast) {
3093 outmsgindex = outmsglast = 0;
3094 isMsgHanging = false;
3097 raw_user_interrupts_on();
3100 #elif defined THREADSIMULATE
3101 int numofcore = pthread_getspecific(key);
3102 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3103 printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3104 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3105 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3108 pthread_rwlock_t* rwlock_obj = NULL;
3109 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3110 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3111 printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3112 rc = pthread_rwlock_unlock(&rwlock_tbl);
3113 printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3118 // redirected lock request
3119 bool getreadlock_I_r(void * ptr, void * redirectlock, int core, bool cache) {
3121 int self_y, self_x, target_y, target_x;
3123 // for 32 bit machine, the size is always 6 words
3126 if(core == corenum) {
3128 lock2require = (int)redirectlock;
3135 targetcore = ((int)redirectlock >> 5) % TOTALCORE;
3137 if(targetcore == corenum) {
3138 // reside on this core
3140 if(!RuntimeHashcontainskey(locktbl, (int)redirectlock)) {
3141 // no locks for this object
3142 // first time to operate on this shared object
3143 // create a lock for it
3144 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3145 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3146 lockvalue->redirectlock = 0;
3147 lockvalue->value = 1;
3148 RuntimeHashadd_I(locktbl, (int)redirectlock, (int)lockvalue);
3151 struct LockValue* lockvalue;
3152 RuntimeHashget(locktbl, (int)redirectlock, &rwlock_obj);
3153 lockvalue = (struct LockValue*)rwlock_obj;
3154 if(lockvalue->redirectlock != 0) {
3155 // the lock is redirected
3156 getreadlock_I_r(ptr, (void *)lockvalue->redirectlock, core, cache);
3159 if(-1 != lockvalue->value) {
3166 if(core == corenum) {
3167 if(lockobj == (int)ptr) {
3172 RuntimeHashadd_I(objRedirectLockTbl, (int)ptr, (int)redirectlock);
3179 // conflicts on lockresults
3180 raw_test_done(0xa011);
3184 // send lock grant/deny request to the root requiring core
3185 // check if there is still some msg on sending
3187 if((!cache) || (cache && !isMsgSending)) {
3188 calCoords(corenum, &self_y, &self_x);
3189 calCoords(core, &target_y, &target_x);
3190 // Build the message header
3191 msgHdr = construct_dyn_hdr(0, msgsize1, 0, // msgsize word sent.
3193 target_y, target_x);
3194 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3196 raw_test_pass(0xbbbb);
3197 raw_test_pass(0xb000 + core); // targetcore
3201 gdn_send(0xa); // lock deny with redirected info
3207 gdn_send(9); // lock grant with redirected info
3212 gdn_send(0); // read lock
3216 gdn_send((int)ptr); // obj pointer
3218 raw_test_pass_reg(ptr);
3220 gdn_send((int)redirectlock); // redirected lock
3222 raw_test_pass_reg((int)redirectlock);
3223 raw_test_pass(0xffff);
3225 } else if(cache && isMsgSending) {
3226 isMsgHanging = true;
3227 // cache the msg in outmsgdata and send it later
3228 // msglength + target core + msg
3229 outmsgdata[outmsglast++] = msgsize1;
3230 outmsgdata[outmsglast++] = core;
3232 outmsgdata[outmsglast++] = 0xa; // deny
3234 outmsgdata[outmsglast++] = 9; // grant
3236 outmsgdata[outmsglast++] = 0;
3237 outmsgdata[outmsglast++] = (int)ptr;
3238 outmsgdata[outmsglast++] = (int)redirectlock;
3243 // check if there is still some msg on sending
3244 if((!cache) || (cache && !isMsgSending)) {
3245 calCoords(corenum, &self_y, &self_x);
3246 calCoords(targetcore, &target_y, &target_x);
3247 // Build the message header
3248 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3250 target_y, target_x);
3251 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3253 raw_test_pass(0xbbbb);
3254 raw_test_pass(0xb000 + targetcore); // targetcore
3256 gdn_send(8); // redirected lock request
3260 gdn_send(0); // read lock
3264 gdn_send((int)ptr); // obj pointer
3266 raw_test_pass_reg(ptr);
3268 gdn_send(lock2require); // redirected lock
3270 raw_test_pass_reg(lock2require);
3272 gdn_send(core); // root request core
3274 raw_test_pass_reg(core);
3276 gdn_send(corenum); // request core
3278 raw_test_pass_reg(corenum);
3279 raw_test_pass(0xffff);
3281 } else if(cache && isMsgSending) {
3282 isMsgHanging = true;
3283 // cache the msg in outmsgdata and send it later
3284 // msglength + target core + msg
3285 outmsgdata[outmsglast++] = msgsize;
3286 outmsgdata[outmsglast++] = targetcore;
3287 outmsgdata[outmsglast++] = 8;
3288 outmsgdata[outmsglast++] = 0;
3289 outmsgdata[outmsglast++] = (int)ptr;
3290 outmsgdata[outmsglast++] = lock2require;
3291 outmsgdata[outmsglast++] = core;
3292 outmsgdata[outmsglast++] = corenum;
3299 bool getwritelock(void * ptr) {
3302 int self_y, self_x, target_y, target_x;
3304 // for 32 bit machine, the size is always 5 words
3308 if(((struct ___Object___ *)ptr)->lock == NULL) {
3309 lock2require = lockobj;
3311 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
3313 targetcore = (lock2require >> 5) % TOTALCORE;
3321 raw_test_pass(0xe551);
3322 raw_test_pass_reg(lockobj);
3323 raw_test_pass_reg(lock2require);
3324 raw_test_pass_reg(targetcore);
3327 if(targetcore == corenum) {
3328 // reside on this core
3331 raw_user_interrupts_off();
3333 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
3334 // no locks for this object
3335 // first time to operate on this shared object
3336 // create a lock for it
3337 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3339 raw_test_pass(0xe552);
3341 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3342 lockvalue->redirectlock = 0;
3343 lockvalue->value = -1;
3344 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
3347 struct LockValue* lockvalue;
3348 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3349 lockvalue = (struct LockValue*)rwlock_obj;
3351 raw_test_pass(0xe553);
3352 raw_test_pass_reg(lockvalue->value);
3354 if(lockvalue->redirectlock != 0) {
3355 // the lock is redirected
3357 raw_test_pass(0xe554);
3359 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
3362 if(0 == lockvalue->value) {
3363 lockvalue->value = -1;
3370 raw_user_interrupts_on();
3373 raw_test_pass(0xe555);
3374 raw_test_pass_reg(lockresult);
3376 if(lockobj == (int)ptr) {
3393 // conflicts on lockresults
3394 raw_test_done(0xa012);
3400 raw_test_pass(0xe556);
3402 calCoords(corenum, &self_y, &self_x);
3403 calCoords(targetcore, &target_y, &target_x);
3404 // Build the message header
3405 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3407 target_y, target_x);
3408 // start sending the msg, set send msg flag
3409 isMsgSending = true;
3410 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3412 raw_test_pass(0xbbbb);
3413 raw_test_pass(0xb000 + targetcore); // targetcore
3415 gdn_send(2); // lock request
3419 gdn_send(1); // write lock
3423 gdn_send((int)ptr); // obj pointer
3425 raw_test_pass_reg(ptr);
3427 gdn_send(lock2require); // lock
3429 raw_test_pass_reg(lock2require);
3431 gdn_send(corenum); // request core
3433 raw_test_pass_reg(corenum);
3434 raw_test_pass(0xffff);
3436 // end of sending this msg, set sand msg flag false
3437 isMsgSending = false;
3438 // check if there are pending msgs
3439 while(isMsgHanging) {
3440 // get the msg from outmsgdata[]
3441 // length + target + msg
3442 outmsgleft = outmsgdata[outmsgindex++];
3443 targetcore = outmsgdata[outmsgindex++];
3444 calCoords(targetcore, &target_y, &target_x);
3445 // Build the message header
3446 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3448 target_y, target_x);
3449 isMsgSending = true;
3450 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3452 raw_test_pass(0xbbbb);
3453 raw_test_pass(0xb000 + targetcore); // targetcore
3455 while(outmsgleft-- > 0) {
3456 gdn_send(outmsgdata[outmsgindex++]);
3458 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3462 raw_test_pass(0xffff);
3464 isMsgSending = false;
3466 raw_user_interrupts_off();
3468 // check if there are still msg hanging
3469 if(outmsgindex == outmsglast) {
3471 outmsgindex = outmsglast = 0;
3472 isMsgHanging = false;
3475 raw_user_interrupts_on();
3479 #elif defined THREADSIMULATE
3480 int numofcore = pthread_getspecific(key);
3482 int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3483 printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3487 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3488 // no locks for this object
3489 // first time to operate on this shared object
3490 // create a lock for it
3491 rc = pthread_rwlock_unlock(&rwlock_tbl);
3492 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3493 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3494 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3495 rc = pthread_rwlock_init(rwlock, NULL);
3496 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3497 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3498 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3500 pthread_rwlock_destroy(rwlock);
3504 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3506 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3508 pthread_rwlock_destroy(rwlock);
3510 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3512 rc = pthread_rwlock_unlock(&rwlock_tbl);
3513 printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3515 rc = pthread_rwlock_trywrlock(rwlock);
3516 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3523 pthread_rwlock_t* rwlock_obj = NULL;
3524 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3525 rc = pthread_rwlock_unlock(&rwlock_tbl);
3526 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3527 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
3528 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3538 void releasewritelock(void * ptr) {
3541 int self_y, self_x, target_y, target_x;
3543 // for 32 bit machine, the size is always 4 words
3547 if(((struct ___Object___ *)ptr)->lock == NULL) {
3548 reallock = (int)ptr;
3550 reallock = (int)(((struct ___Object___ *)ptr)->lock);
3552 targetcore = (reallock >> 5) % TOTALCORE;
3555 raw_test_pass(0xe661);
3556 raw_test_pass_reg((int)ptr);
3557 raw_test_pass_reg(reallock);
3558 raw_test_pass_reg(targetcore);
3561 if(targetcore == corenum) {
3563 raw_user_interrupts_off();
3565 // reside on this core
3566 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3567 // no locks for this object, something is wrong
3568 raw_test_done(0xa013);
3571 struct LockValue * lockvalue = NULL;
3573 raw_test_pass(0xe662);
3575 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3576 lockvalue = (struct LockValue *)rwlock_obj;
3578 raw_test_pass_reg(lockvalue->value);
3582 raw_test_pass_reg(lockvalue->value);
3586 raw_user_interrupts_on();
3592 raw_test_pass(0xe663);
3594 calCoords(corenum, &self_y, &self_x);
3595 calCoords(targetcore, &target_y, &target_x);
3596 // Build the message header
3597 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3599 target_y, target_x);
3600 // start sending the msg, set send msg flag
3601 isMsgSending = true;
3602 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3604 raw_test_pass(0xbbbb);
3605 raw_test_pass(0xb000 + targetcore);
3607 gdn_send(5); // lock release
3611 gdn_send(1); // write lock
3615 gdn_send((int)ptr); // obj pointer
3617 raw_test_pass_reg(ptr);
3619 gdn_send(reallock); // lock
3621 raw_test_pass_reg(reallock);
3622 raw_test_pass(0xffff);
3624 // end of sending this msg, set sand msg flag false
3625 isMsgSending = false;
3626 // check if there are pending msgs
3627 while(isMsgHanging) {
3628 // get the msg from outmsgdata[]
3629 // length + target + msg
3630 outmsgleft = outmsgdata[outmsgindex++];
3631 targetcore = outmsgdata[outmsgindex++];
3632 calCoords(targetcore, &target_y, &target_x);
3633 // Build the message header
3634 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3636 target_y, target_x);
3637 isMsgSending = true;
3638 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3640 raw_test_pass(0xbbbb);
3641 raw_test_pass(0xb000 + targetcore); // targetcore
3643 while(outmsgleft-- > 0) {
3644 gdn_send(outmsgdata[outmsgindex++]);
3646 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3650 raw_test_pass(0xffff);
3652 isMsgSending = false;
3654 raw_user_interrupts_off();
3656 // check if there are still msg hanging
3657 if(outmsgindex == outmsglast) {
3659 outmsgindex = outmsglast = 0;
3660 isMsgHanging = false;
3663 raw_user_interrupts_on();
3666 #elif defined THREADSIMULATE
3667 int numofcore = pthread_getspecific(key);
3668 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3669 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3670 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3671 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3674 pthread_rwlock_t* rwlock_obj = NULL;
3675 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3676 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3677 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3678 rc = pthread_rwlock_unlock(&rwlock_tbl);
3679 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3683 void releasewritelock_r(void * lock, void * redirectlock) {
3686 int self_y, self_x, target_y, target_x;
3688 // for 32 bit machine, the size is always 4 words
3691 int reallock = (int)lock;
3692 targetcore = (reallock >> 5) % TOTALCORE;
3695 raw_test_pass(0xe671);
3696 raw_test_pass_reg((int)lock);
3697 raw_test_pass_reg(reallock);
3698 raw_test_pass_reg(targetcore);
3701 if(targetcore == corenum) {
3703 raw_user_interrupts_off();
3705 // reside on this core
3706 if(!RuntimeHashcontainskey(locktbl, reallock)) {
3707 // no locks for this object, something is wrong
3708 raw_test_done(0xa014);
3711 struct LockValue * lockvalue = NULL;
3713 raw_test_pass(0xe672);
3715 RuntimeHashget(locktbl, reallock, &rwlock_obj);
3716 lockvalue = (struct LockValue *)rwlock_obj;
3718 raw_test_pass_reg(lockvalue->value);
3721 lockvalue->redirectlock = (int)redirectlock;
3723 raw_test_pass_reg(lockvalue->value);
3727 raw_user_interrupts_on();
3733 raw_test_pass(0xe673);
3735 calCoords(corenum, &self_y, &self_x);
3736 calCoords(targetcore, &target_y, &target_x);
3737 // Build the message header
3738 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3740 target_y, target_x);
3741 // start sending the msg, set send msg flag
3742 isMsgSending = true;
3745 raw_test_pass(0xbbbb);
3746 raw_test_pass(0xb000 + targetcore);
3748 gdn_send(0xb); // lock release with redirect info
3752 gdn_send(1); // write lock
3756 gdn_send((int)lock); // lock
3758 raw_test_pass_reg(lock);
3760 gdn_send((int)redirectlock); // redirect lock
3762 raw_test_pass_reg(redirectlock);
3763 raw_test_pass(0xffff);
3765 // end of sending this msg, set sand msg flag false
3766 isMsgSending = false;
3767 // check if there are pending msgs
3768 while(isMsgHanging) {
3769 // get the msg from outmsgdata[]
3770 // length + target + msg
3771 outmsgleft = outmsgdata[outmsgindex++];
3772 targetcore = outmsgdata[outmsgindex++];
3773 calCoords(targetcore, &target_y, &target_x);
3774 // Build the message header
3775 msgHdr = construct_dyn_hdr(0, outmsgleft, 0, // msgsize word sent.
3777 target_y, target_x);
3778 isMsgSending = true;
3779 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
3781 raw_test_pass(0xbbbb);
3782 raw_test_pass(0xb000 + targetcore); // targetcore
3784 while(outmsgleft-- > 0) {
3785 gdn_send(outmsgdata[outmsgindex++]);
3787 raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3791 raw_test_pass(0xffff);
3793 isMsgSending = false;
3795 raw_user_interrupts_off();
3797 // check if there are still msg hanging
3798 if(outmsgindex == outmsglast) {
3800 outmsgindex = outmsglast = 0;
3801 isMsgHanging = false;
3804 raw_user_interrupts_on();
3807 #elif defined THREADSIMULATE
3808 // TODO, need modification according to alias lock
3809 int numofcore = pthread_getspecific(key);
3810 int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3811 printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3812 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3813 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3816 pthread_rwlock_t* rwlock_obj = NULL;
3817 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3818 int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3819 printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3820 rc = pthread_rwlock_unlock(&rwlock_tbl);
3821 printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3826 bool getwritelock_I(void * ptr) {
3828 int self_y, self_x, target_y, target_x;
3830 // for 32 bit machine, the size is always 5 words
3834 if(((struct ___Object___ *)ptr)->lock == NULL) {
3835 lock2require = lockobj;
3837 lock2require = (int)(((struct ___Object___ *)ptr)->lock);
3839 targetcore = (lock2require >> 5) % TOTALCORE;
3847 raw_test_pass(0xe561);
3848 raw_test_pass_reg(lockobj);
3849 raw_test_pass_reg(lock2require);
3850 raw_test_pass_reg(targetcore);
3853 if(targetcore == corenum) {
3854 // reside on this core
3856 if(!RuntimeHashcontainskey(locktbl, lock2require)) {
3857 // no locks for this object
3858 // first time to operate on this shared object
3859 // create a lock for it
3860 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3862 raw_test_pass(0xe562);
3864 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3865 lockvalue->redirectlock = 0;
3866 lockvalue->value = -1;
3867 RuntimeHashadd_I(locktbl, lock2require, (int)lockvalue);
3870 struct LockValue* lockvalue;
3871 RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3872 lockvalue = (struct LockValue*)rwlock_obj;
3874 raw_test_pass(0xe563);
3875 raw_test_pass_reg(lockvalue->value);
3877 if(lockvalue->redirectlock != 0) {
3878 // the lock is redirected
3880 raw_test_pass(0xe564);
3882 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, corenum, false);
3885 if(0 == lockvalue->value) {
3886 lockvalue->value = -1;
3893 raw_test_pass(0xe565);
3894 raw_test_pass_reg(lockresult);
3896 if(lockobj == (int)ptr) {
3913 // conflicts on lockresults
3914 raw_test_done(0xa015);
3920 raw_test_pass(0xe566);
3922 calCoords(corenum, &self_y, &self_x);
3923 calCoords(targetcore, &target_y, &target_x);
3924 // Build the message header
3925 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
3927 target_y, target_x);
3928 // start sending the msg, set send msg flag
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 gdn_send(2); // lock request
3938 gdn_send(1); // write lock
3942 gdn_send((int)ptr); // obj pointer
3944 raw_test_pass_reg(ptr);
3946 gdn_send(lock2require); // lock
3948 raw_test_pass_reg(lock2require);
3950 gdn_send(corenum); // request core
3952 raw_test_pass_reg(corenum);
3953 raw_test_pass(0xffff);
3958 // redirected lock request
3959 bool getwritelock_I_r(void * ptr, void * redirectlock, int core, bool cache) {
3961 int self_y, self_x, target_y, target_x;
3963 // for 32 bit machine, the size is always 6 words
3966 if(core == corenum) {
3968 lock2require = (int)redirectlock;
3975 targetcore = ((int)redirectlock >> 5) % TOTALCORE;
3978 raw_test_pass(0xe571);
3979 raw_test_pass_reg((int)ptr);
3980 raw_test_pass_reg((int)redirectlock);
3981 raw_test_pass_reg(core);
3982 raw_test_pass_reg((int)cache);
3983 raw_test_pass_reg(targetcore);
3987 if(targetcore == corenum) {
3988 // reside on this core
3990 if(!RuntimeHashcontainskey(locktbl, (int)redirectlock)) {
3991 // no locks for this object
3992 // first time to operate on this shared object
3993 // create a lock for it
3994 // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
3995 struct LockValue * lockvalue = (struct LockValue *)(RUNMALLOC_I(sizeof(struct LockValue)));
3996 lockvalue->redirectlock = 0;
3997 lockvalue->value = -1;
3998 RuntimeHashadd_I(locktbl, (int)redirectlock, (int)lockvalue);
4001 struct LockValue* lockvalue;
4002 RuntimeHashget(locktbl, (int)redirectlock, &rwlock_obj);
4003 lockvalue = (struct LockValue*)rwlock_obj;
4004 if(lockvalue->redirectlock != 0) {
4005 // the lock is redirected
4007 raw_test_pass(0xe572);
4009 getwritelock_I_r(ptr, (void *)lockvalue->redirectlock, core, cache);
4012 if(0 == lockvalue->value) {
4013 lockvalue->value = -1;
4019 if(core == corenum) {
4020 if(lockobj == (int)ptr) {
4025 RuntimeHashadd_I(objRedirectLockTbl, (int)ptr, (int)redirectlock);
4032 // conflicts on lockresults
4033 raw_test_done(0xa016);
4037 // send lock grant/deny request to the root requiring core
4038 // check if there is still some msg on sending
4040 if((!cache) || (cache && !isMsgSending)) {
4041 calCoords(corenum, &self_y, &self_x);
4042 calCoords(core, &target_y, &target_x);
4043 // Build the message header
4044 msgHdr = construct_dyn_hdr(0, msgsize1, 0, // msgsize word sent.
4046 target_y, target_x);
4047 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4049 raw_test_pass(0xbbbb);
4050 raw_test_pass(0xb000 + core); // targetcore
4054 gdn_send(0xa); // lock deny with redirected info
4060 gdn_send(9); // lock grant with redirected info
4065 gdn_send(1); // write lock
4069 gdn_send((int)ptr); // obj pointer
4071 raw_test_pass_reg(ptr);
4073 gdn_send((int)redirectlock); // redirected lock
4075 raw_test_pass_reg((int)redirectlock);
4076 raw_test_pass(0xffff);
4078 } else if(cache && isMsgSending) {
4079 isMsgHanging = true;
4080 // cache the msg in outmsgdata and send it later
4081 // msglength + target core + msg
4082 outmsgdata[outmsglast++] = msgsize1;
4083 outmsgdata[outmsglast++] = core;
4085 outmsgdata[outmsglast++] = 0xa; // deny
4087 outmsgdata[outmsglast++] = 9; // grant
4089 outmsgdata[outmsglast++] = 1;
4090 outmsgdata[outmsglast++] = (int)ptr;
4091 outmsgdata[outmsglast++] = (int)redirectlock;
4096 // check if there is still some msg on sending
4097 if((!cache) || (cache && !isMsgSending)) {
4098 calCoords(corenum, &self_y, &self_x);
4099 calCoords(targetcore, &target_y, &target_x);
4100 // Build the message header
4101 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4103 target_y, target_x);
4104 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4106 raw_test_pass(0xbbbb);
4107 raw_test_pass(0xb000 + targetcore); // targetcore
4109 gdn_send(8); // redirected lock request
4113 gdn_send(1); // write lock
4117 gdn_send((int)ptr); // obj pointer
4119 raw_test_pass_reg(ptr);
4121 gdn_send((int)redirectlock); // redirected lock
4123 raw_test_pass_reg((int)redirectlock);
4125 gdn_send(core); // root request core
4127 raw_test_pass_reg(core);
4129 gdn_send(corenum); // request core
4131 raw_test_pass_reg(corenum);
4132 raw_test_pass(0xffff);
4134 } else if(cache && isMsgSending) {
4135 isMsgHanging = true;
4136 // cache the msg in outmsgdata and send it later
4137 // msglength + target core + msg
4138 outmsgdata[outmsglast++] = msgsize;
4139 outmsgdata[outmsglast++] = targetcore;
4140 outmsgdata[outmsglast++] = 8;
4141 outmsgdata[outmsglast++] = 1;
4142 outmsgdata[outmsglast++] = (int)ptr;
4143 outmsgdata[outmsglast++] = (int)redirectlock;
4144 outmsgdata[outmsglast++] = core;
4145 outmsgdata[outmsglast++] = corenum;
4150 void releasewritelock_I(void * ptr) {
4152 int self_y, self_x, target_y, target_x;
4154 // for 32 bit machine, the size is always 4 words
4158 if(((struct ___Object___ *)ptr)->lock == NULL) {
4159 reallock = (int)ptr;
4161 reallock = (int)(((struct ___Object___ *)ptr)->lock);
4163 targetcore = (reallock >> 5) % TOTALCORE;
4166 raw_test_pass(0xe681);
4167 raw_test_pass_reg((int)ptr);
4168 raw_test_pass_reg(reallock);
4169 raw_test_pass_reg(targetcore);
4172 if(targetcore == corenum) {
4173 // reside on this core
4174 if(!RuntimeHashcontainskey(locktbl, reallock)) {
4175 // no locks for this object, something is wrong
4176 raw_test_done(0xa017);
4179 struct LockValue * lockvalue = NULL;
4180 RuntimeHashget(locktbl, reallock, &rwlock_obj);
4181 lockvalue = (struct LockValue *)rwlock_obj;
4187 calCoords(corenum, &self_y, &self_x);
4188 calCoords(targetcore, &target_y, &target_x);
4189 // Build the message header
4190 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4192 target_y, target_x);
4193 gdn_send(msgHdr); // Send the message header to EAST to handle fab(n - 1).
4195 raw_test_pass(0xbbbb);
4196 raw_test_pass(0xb000 + targetcore); // targetcore
4198 gdn_send(5); // lock release
4202 gdn_send(1); // write lock
4206 gdn_send((int)ptr); // obj pointer
4208 raw_test_pass_reg(ptr);
4210 gdn_send(reallock); // lock
4212 raw_test_pass_reg(reallock);
4213 raw_test_pass(0xffff);
4217 void releasewritelock_I_r(void * lock, void * redirectlock) {
4219 int self_y, self_x, target_y, target_x;
4221 // for 32 bit machine, the size is always 4 words
4224 int reallock = (int)lock;
4225 targetcore = (reallock >> 5) % TOTALCORE;
4228 raw_test_pass(0xe691);
4229 raw_test_pass_reg((int)lock);
4230 raw_test_pass_reg(reallock);
4231 raw_test_pass_reg(targetcore);
4234 if(targetcore == corenum) {
4235 // reside on this core
4236 if(!RuntimeHashcontainskey(locktbl, reallock)) {
4237 // no locks for this object, something is wrong
4238 raw_test_done(0xa018);
4241 struct LockValue * lockvalue = NULL;
4243 raw_test_pass(0xe672);
4245 RuntimeHashget(locktbl, reallock, &rwlock_obj);
4246 lockvalue = (struct LockValue *)rwlock_obj;
4248 raw_test_pass_reg(lockvalue->value);
4251 lockvalue->redirectlock = (int)redirectlock;
4253 raw_test_pass_reg(lockvalue->value);
4260 raw_test_pass(0xe673);
4262 calCoords(corenum, &self_y, &self_x);
4263 calCoords(targetcore, &target_y, &target_x);
4264 // Build the message header
4265 msgHdr = construct_dyn_hdr(0, msgsize, 0, // msgsize word sent.
4267 target_y, target_x);
4268 // start sending the msg, set send msg flag
4271 raw_test_pass(0xbbbb);
4272 raw_test_pass(0xb000 + targetcore);
4274 gdn_send(0xb); // lock release with redirect info
4278 gdn_send(1); // write lock
4282 gdn_send((int)lock); // lock
4284 raw_test_pass_reg(lock);
4286 gdn_send((int)redirectlock); // redirect lock
4288 raw_test_pass_reg(redirectlock);
4289 raw_test_pass(0xffff);
4294 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
4295 void * taskpointerarray[MAXTASKPARAMS];
4297 int numparams=parameter->task->numParameters;
4298 int numiterators=parameter->task->numTotal-1;
4303 struct taskdescriptor * task=parameter->task;
4305 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
4307 /* Add enqueued object to parameter vector */
4308 taskpointerarray[parameter->slot]=ptr;
4310 /* Reset iterators */
4311 for(j=0; j<numiterators; j++) {
4312 toiReset(¶meter->iterators[j]);
4315 /* Find initial state */
4316 for(j=0; j<numiterators; j++) {
4318 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4319 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4321 /* Need to backtrack */
4322 toiReset(¶meter->iterators[j]);
4326 /* Nothing to enqueue */
4333 /* Enqueue current state */
4335 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
4337 tpd->numParameters=numiterators+1;
4338 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
4339 for(j=0; j<=numiterators; j++) {
4340 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
4343 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
4344 genputtable(activetasks, tpd, tpd);
4346 RUNFREE(tpd->parameterArray);
4350 /* This loop iterates to the next parameter combination */
4351 if (numiterators==0)
4354 for(j=numiterators-1; j<numiterators; j++) {
4356 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4357 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4359 /* Need to backtrack */
4360 toiReset(¶meter->iterators[j]);
4364 /* Nothing more to enqueue */
4373 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
4374 void * taskpointerarray[MAXTASKPARAMS];
4376 int numparams=parameter->task->numParameters;
4377 int numiterators=parameter->task->numTotal-1;
4382 struct taskdescriptor * task=parameter->task;
4384 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL); //this add the object to parameterwrapper
4386 /* Add enqueued object to parameter vector */
4387 taskpointerarray[parameter->slot]=ptr;
4389 /* Reset iterators */
4390 for(j=0; j<numiterators; j++) {
4391 toiReset(¶meter->iterators[j]);
4394 /* Find initial state */
4395 for(j=0; j<numiterators; j++) {
4397 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4398 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4400 /* Need to backtrack */
4401 toiReset(¶meter->iterators[j]);
4405 /* Nothing to enqueue */
4411 /* Enqueue current state */
4413 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
4415 tpd->numParameters=numiterators+1;
4416 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
4417 for(j=0; j<=numiterators; j++) {
4418 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
4421 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
4422 genputtable_I(activetasks, tpd, tpd);
4424 RUNFREE(tpd->parameterArray);
4428 /* This loop iterates to the next parameter combination */
4429 if (numiterators==0)
4432 for(j=numiterators-1; j<numiterators; j++) {
4434 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
4435 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
4437 /* Need to backtrack */
4438 toiReset(¶meter->iterators[j]);
4442 /* Nothing more to enqueue */
4451 /* Handler for signals. The signals catch null pointer errors and
4452 arithmatic errors. */
4454 void myhandler(int sig, siginfo_t *info, void *uap) {
4457 printf("sig=%d\n",sig);
4460 sigemptyset(&toclear);
4461 sigaddset(&toclear, sig);
4462 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
4463 longjmp(error_handler,1);
4469 struct RuntimeHash *fdtoobject;
4471 void addreadfd(int fd) {
4474 FD_SET(fd, &readfds);
4477 void removereadfd(int fd) {
4478 FD_CLR(fd, &readfds);
4479 if (maxreadfd==(fd+1)) {
4481 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
4492 void executetasks() {
4493 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
4496 struct ___Object___ * tmpparam = NULL;
4497 struct parameterdescriptor * pd=NULL;
4498 struct parameterwrapper *pw=NULL;
4504 struct LockValue * locks[MAXTASKPARAMS];
4510 raw_test_pass(0xe991);
4513 for(j = 0; j < MAXTASKPARAMS; j++) {
4514 locks[j] = (struct LockValue *)(RUNMALLOC(sizeof(struct LockValue)));
4515 locks[j]->redirectlock = 0;
4516 locks[j]->value = 0;
4521 /* Set up signal handlers */
4522 struct sigaction sig;
4523 sig.sa_sigaction=&myhandler;
4524 sig.sa_flags=SA_SIGINFO;
4525 sigemptyset(&sig.sa_mask);
4527 /* Catch bus errors, segmentation faults, and floating point exceptions*/
4528 sigaction(SIGBUS,&sig,0);
4529 sigaction(SIGSEGV,&sig,0);
4530 sigaction(SIGFPE,&sig,0);
4531 sigaction(SIGPIPE,&sig,0);
4540 fdtoobject=allocateRuntimeHash(100);
4544 /* Map first block of memory to protected, anonymous page */
4545 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
4549 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
4553 raw_test_pass(0xe992);
4556 /* Check if any filedescriptors have IO pending */
4559 struct timeval timeout={0,0};
4563 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
4565 /* Process ready fd's */
4567 for(fd=0; fd<maxreadfd; fd++) {
4568 if (FD_ISSET(fd, &tmpreadfds)) {
4569 /* Set ready flag on object */
4571 // printf("Setting fd %d\n",fd);
4572 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
4573 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
4574 enqueueObject(objptr, NULL, 0);
4583 /* See if there are any active tasks */
4584 if (hashsize(activetasks)>0) {
4587 if(!taskInfoOverflow) {
4588 TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
4589 taskInfoArray[taskInfoIndex] = checkTaskInfo;
4590 checkTaskInfo->taskName = "tpd checking";
4591 checkTaskInfo->startTime = raw_get_cycle();
4592 checkTaskInfo->endTime = -1;
4593 checkTaskInfo->exitIndex = -1;
4594 checkTaskInfo->newObjs = NULL;
4597 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
4598 genfreekey(activetasks, currtpd);
4600 numparams=currtpd->task->numParameters;
4601 numtotal=currtpd->task->numTotal;
4603 #ifdef THREADSIMULATE
4604 int isolateflags[numparams];
4607 // clear the lockRedirectTbl (TODO, this table should be empty after all locks are released)
4609 // get all required locks
4611 // check which locks are needed
4612 for(i = 0; i < numparams; i++) {
4613 void * param = currtpd->parameterArray[i];
4617 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
4619 taskpointerarray[i+OFFSET]=param;
4622 if(((struct ___Object___ *)param)->lock == NULL) {
4623 tmplock = (int)param;
4625 tmplock = (int)(((struct ___Object___ *)param)->lock);
4627 // insert into the locks array
4628 for(j = 0; j < locklen; j++) {
4629 if(locks[j]->value == tmplock) {
4632 } else if(locks[j]->value > tmplock) {
4639 locks[h]->redirectlock = locks[h-1]->redirectlock;
4640 locks[h]->value = locks[h-1]->value;
4642 locks[j]->value = tmplock;
4643 locks[j]->redirectlock = (int)param;
4647 // grab these required locks
4648 for(i = 0; i < locklen; i++) {
4649 int * lock = (int *)(locks[i]->redirectlock);
4651 // require locks for this parameter if it is not a startup object
4653 raw_test_pass(0xe993);
4654 raw_test_pass_reg((int)lock);
4655 raw_test_pass_reg((int)(locks[i]->value));
4660 raw_user_interrupts_off();
4663 //isInterrupt = false;
4670 while(receiveObject() != -1) {
4674 grount = lockresult;
4684 //isInterrupt = true;
4687 raw_user_interrupts_on();
4693 raw_test_pass(0xe994);
4695 // can not get the lock, try later
4696 // releas all grabbed locks for previous parameters
4697 for(j = 0; j < i; ++j) {
4698 lock = (int*)(locks[j]->redirectlock);
4699 releasewritelock(lock);
4701 genputtable(activetasks, currtpd, currtpd);
4702 if(hashsize(activetasks) == 1) {
4703 // only one task right now, wait a little while before next try
4709 // fail, set the end of the checkTaskInfo
4710 if(!taskInfoOverflow) {
4711 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4713 if(taskInfoIndex == TASKINFOLENGTH) {
4714 taskInfoOverflow = true;
4721 #elif defined THREADSIMULATE
4722 // TODO: need modification according to added alias locks
4725 /* Make sure that the parameters are still in the queues */
4726 for(i=0; i<numparams; i++) {
4727 void * parameter=currtpd->parameterArray[i];
4730 raw_test_pass(0xe995);
4735 raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
4738 raw_user_interrupts_off();
4740 /*if(RuntimeHashcontainskey(objRedirectLockTbl, (int)parameter)) {
4741 int redirectlock_r = 0;
4742 RuntimeHashget(objRedirectLockTbl, (int)parameter, &redirectlock_r);
4743 ((struct ___Object___ *)parameter)->lock = redirectlock_r;
4744 RuntimeHashremovekey(objRedirectLockTbl, (int)parameter);
4747 raw_user_interrupts_on();
4750 tmpparam = (struct ___Object___ *)parameter;
4751 #ifdef THREADSIMULATE
4752 if(0 == tmpparam->isolate) {
4753 isolateflags[i] = 0;
4754 // shared object, need to flush with current value
4755 // TODO: need modification according to added alias locks
4756 if(!getwritelock(tmpparam->original)) {
4757 // fail to get write lock, release all obtained locks and try this task later
4759 for(j = 0; j < i; ++j) {
4760 if(0 == isolateflags[j]) {
4761 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
4764 genputtable(activetasks, currtpd, currtpd);
4767 if(tmpparam->version != tmpparam->original->version) {
4768 // release all obtained locks
4770 for(j = 0; j < i; ++j) {
4771 if(0 == isolateflags[j]) {
4772 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
4775 releasewritelock(tmpparam->original);
4777 // dequeue this object
4778 int numofcore = pthread_getspecific(key);
4779 struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
4780 int length = numqueues[numofcore][tmpparam->type];
4781 for(j = 0; j < length; ++j) {
4782 struct parameterwrapper * pw = queues[j];
4783 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
4785 int UNUSED, UNUSED2;
4787 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
4788 ObjectHashremove(pw->objectset, (int)tmpparam);
4789 if (enterflags!=NULL)
4793 // Free up task parameter descriptor
4794 RUNFREE(currtpd->parameterArray);
4799 isolateflags[i] = 1;
4802 pd=currtpd->task->descriptorarray[i];
4803 pw=(struct parameterwrapper *) pd->queue;
4804 /* Check that object is still in queue */
4806 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
4808 raw_test_pass(0xe996);
4810 // release grabbed locks
4812 for(j = 0; j < locklen; ++j) {
4813 int * lock = (int *)(locks[j]->redirectlock);
4814 releasewritelock(lock);
4816 #elif defined THREADSIMULATE
4818 RUNFREE(currtpd->parameterArray);
4824 /* Check if the object's flags still meets requirements */
4828 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
4829 andmask=pw->intarray[tmpi*2];
4830 checkmask=pw->intarray[tmpi*2+1];
4832 raw_test_pass(0xdd000000 + andmask);
4833 raw_test_pass_reg((int)parameter);
4834 raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
4835 raw_test_pass(0xdd000000 + checkmask);
4837 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
4843 // flags are never suitable
4844 // remove this obj from the queue
4846 int UNUSED, UNUSED2;
4849 raw_test_pass(0xe997);
4851 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
4852 ObjectHashremove(pw->objectset, (int)parameter);
4853 if (enterflags!=NULL)
4855 // release grabbed locks
4856 for(j = 0; j < locklen; ++j) {
4857 int * lock = (int *)(locks[j]->redirectlock);
4858 releasewritelock(lock);
4860 RUNFREE(currtpd->parameterArray);
4863 // fail, set the end of the checkTaskInfo
4864 if(!taskInfoOverflow) {
4865 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4867 if(taskInfoIndex == TASKINFOLENGTH) {
4868 taskInfoOverflow = true;
4878 /* Check that object still has necessary tags */
4879 for(j=0; j<pd->numbertags; j++) {
4880 int slotid=pd->tagarray[2*j]+numparams;
4881 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
4882 if (!containstag(parameter, tagd)) {
4884 raw_test_pass(0xe998);
4886 RUNFREE(currtpd->parameterArray);
4892 taskpointerarray[i+OFFSET]=parameter;
4895 for(; i<numtotal; i++) {
4896 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
4899 #ifdef THREADSIMULATE
4900 for(i = 0; i < numparams; ++i) {
4901 if(0 == isolateflags[i]) {
4902 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
4903 if(tmpparam != tmpparam->original) {
4904 taskpointerarray[i+OFFSET] = tmpparam->original;
4913 /* Checkpoint the state */
4914 forward=allocateRuntimeHash(100);
4915 reverse=allocateRuntimeHash(100);
4916 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
4919 if (x=setjmp(error_handler)) {
4924 printf("Fatal Error=%d, Recovering!\n",x);
4928 genputtable(failedtasks,currtpd,currtpd);
4929 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
4931 freeRuntimeHash(forward);
4932 freeRuntimeHash(reverse);
4940 raw_test_pass_reg(x);
4942 raw_test_pass_reg(x);
4943 raw_test_done(0xa019);
4948 /*if (injectfailures) {
4949 if ((((double)random())/RAND_MAX)<failurechance) {
4950 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
4951 longjmp(error_handler,10);
4954 /* Actually call task */
4956 ((int *)taskpointerarray)[0]=currtpd->numParameters;
4957 taskpointerarray[1]=NULL;
4962 // check finish, set the end of the checkTaskInfo
4963 if(!taskInfoOverflow) {
4964 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
4966 if(taskInfoIndex == TASKINFOLENGTH) {
4967 taskInfoOverflow = true;
4971 if(!taskInfoOverflow) {
4972 // new a taskInfo for the task execution
4973 TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
4974 taskInfoArray[taskInfoIndex] = taskInfo;
4975 taskInfo->taskName = currtpd->task->name;
4976 taskInfo->startTime = raw_get_cycle();
4977 taskInfo->endTime = -1;
4978 taskInfo->exitIndex = -1;
4979 taskInfo->newObjs = NULL;
4985 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
4987 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
4989 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
4993 raw_test_pass(0xe999);
4995 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
4998 // task finish, set the end of the checkTaskInfo
4999 if(!taskInfoOverflow) {
5000 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5002 if(taskInfoIndex == TASKINFOLENGTH) {
5003 taskInfoOverflow = true;
5006 // new a PostTaskInfo for the post-task execution
5007 if(!taskInfoOverflow) {
5008 TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
5009 taskInfoArray[taskInfoIndex] = postTaskInfo;
5010 postTaskInfo->taskName = "post task execution";
5011 postTaskInfo->startTime = raw_get_cycle();
5012 postTaskInfo->endTime = -1;
5013 postTaskInfo->exitIndex = -1;
5014 postTaskInfo->newObjs = NULL;
5018 raw_test_pass(0xe99a);
5019 raw_test_pass_reg(islock);
5024 for(i = 0; i < locklen; ++i) {
5025 void * ptr = (void *)(locks[i]->redirectlock);
5026 int * lock = (int *)(locks[i]->value);
5028 raw_test_pass(0xe99b);
5029 raw_test_pass_reg((int)ptr);
5030 raw_test_pass_reg((int)lock);
5032 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
5034 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
5035 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
5036 releasewritelock_r(lock, (int *)redirectlock);
5038 releasewritelock(ptr);
5041 #elif defined THREADSIMULATE
5042 // TODO : need modification for alias lock
5043 for(i = 0; i < numparams; ++i) {
5045 if(0 == isolateflags[i]) {
5046 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
5047 if(tmpparam->lock == NULL) {
5048 lock = (int*)tmpparam;
5050 lock = tmpparam->lock;
5052 releasewritelock(lock);
5059 // post task execution finish, set the end of the postTaskInfo
5060 if(!taskInfoOverflow) {
5061 taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
5063 if(taskInfoIndex == TASKINFOLENGTH) {
5064 taskInfoOverflow = true;
5071 freeRuntimeHash(forward);
5072 freeRuntimeHash(reverse);
5076 // Free up task parameter descriptor
5077 RUNFREE(currtpd->parameterArray);
5086 raw_test_pass(0xe99c);
5089 raw_test_pass(0xe99c);
5097 raw_test_pass(0xe99d);
5101 /* This function processes an objects tags */
5102 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
5105 for(i=0; i<pd->numbertags; i++) {
5106 int slotid=pd->tagarray[2*i];
5107 int tagid=pd->tagarray[2*i+1];
5109 if (statusarray[slotid+numparams]==0) {
5110 parameter->iterators[*iteratorcount].istag=1;
5111 parameter->iterators[*iteratorcount].tagid=tagid;
5112 parameter->iterators[*iteratorcount].slot=slotid+numparams;
5113 parameter->iterators[*iteratorcount].tagobjectslot=index;
5114 statusarray[slotid+numparams]=1;
5121 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
5124 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
5126 parameter->iterators[*iteratorcount].istag=0;
5127 parameter->iterators[*iteratorcount].slot=index;
5128 parameter->iterators[*iteratorcount].objectset=objectset;
5129 statusarray[index]=1;
5131 for(i=0; i<pd->numbertags; i++) {
5132 int slotid=pd->tagarray[2*i];
5133 int tagid=pd->tagarray[2*i+1];
5134 if (statusarray[slotid+numparams]!=0) {
5135 /* This tag has already been enqueued, use it to narrow search */
5136 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
5140 parameter->iterators[*iteratorcount].numtags=tagcount;
5145 /* This function builds the iterators for a task & parameter */
5147 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
5148 int statusarray[MAXTASKPARAMS];
5150 int numparams=task->numParameters;
5151 int iteratorcount=0;
5152 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
5154 statusarray[index]=1; /* Initial parameter */
5155 /* Process tags for initial iterator */
5157 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
5161 /* Check for objects with existing tags */
5162 for(i=0; i<numparams; i++) {
5163 if (statusarray[i]==0) {
5164 struct parameterdescriptor *pd=task->descriptorarray[i];
5166 for(j=0; j<pd->numbertags; j++) {
5167 int slotid=pd->tagarray[2*j];
5168 if(statusarray[slotid+numparams]!=0) {
5169 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5170 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5177 /* Next do objects w/ unbound tags*/
5179 for(i=0; i<numparams; i++) {
5180 if (statusarray[i]==0) {
5181 struct parameterdescriptor *pd=task->descriptorarray[i];
5182 if (pd->numbertags>0) {
5183 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5184 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5190 /* Nothing with a tag enqueued */
5192 for(i=0; i<numparams; i++) {
5193 if (statusarray[i]==0) {
5194 struct parameterdescriptor *pd=task->descriptorarray[i];
5195 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
5196 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
5209 #ifdef THREADSIMULATE
5210 int numofcore = pthread_getspecific(key);
5211 for(i=0; i<numtasks[numofcore]; i++) {
5212 struct taskdescriptor * task=taskarray[numofcore][i];
5215 if(corenum > NUMCORES - 1) {
5219 for(i=0; i<numtasks[corenum]; i++) {
5220 struct taskdescriptor * task=taskarray[corenum][i];
5223 printf("%s\n", task->name);
5225 for(j=0; j<task->numParameters; j++) {
5226 struct parameterdescriptor *param=task->descriptorarray[j];
5227 struct parameterwrapper *parameter=param->queue;
5228 struct ObjectHash * set=parameter->objectset;
5229 struct ObjectIterator objit;
5231 printf(" Parameter %d\n", j);
5233 ObjectHashiterator(set, &objit);
5234 while(ObjhasNext(&objit)) {
5235 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
5236 struct ___Object___ * tagptr=obj->___tags___;
5237 int nonfailed=Objdata4(&objit);
5238 int numflags=Objdata3(&objit);
5239 int flags=Objdata2(&objit);
5242 printf(" Contains %lx\n", obj);
5243 printf(" flag=%d\n", obj->flag);
5246 } else if (tagptr->type==TAGTYPE) {
5248 printf(" tag=%lx\n",tagptr);
5253 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
5254 for(; tagindex<ao->___cachedCode___; tagindex++) {
5256 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
5266 /* This function processes the task information to create queues for
5267 each parameter type. */
5269 void processtasks() {
5272 if(corenum > NUMCORES - 1) {
5276 #ifdef THREADSIMULATE
5277 int numofcore = pthread_getspecific(key);
5278 for(i=0; i<numtasks[numofcore]; i++) {
5279 struct taskdescriptor *task=taskarray[numofcore][i];
5281 for(i=0; i<numtasks[corenum]; i++) {
5282 struct taskdescriptor * task=taskarray[corenum][i];
5286 /* Build objectsets */
5287 for(j=0; j<task->numParameters; j++) {
5288 struct parameterdescriptor *param=task->descriptorarray[j];
5289 struct parameterwrapper *parameter=param->queue;
5290 parameter->objectset=allocateObjectHash(10);
5291 parameter->task=task;
5294 /* Build iterators for parameters */
5295 for(j=0; j<task->numParameters; j++) {
5296 struct parameterdescriptor *param=task->descriptorarray[j];
5297 struct parameterwrapper *parameter=param->queue;
5298 builditerators(task, j, parameter);
5303 void toiReset(struct tagobjectiterator * it) {
5306 } else if (it->numtags>0) {
5309 ObjectHashiterator(it->objectset, &it->it);
5313 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
5316 /* Get object with tags */
5317 struct ___Object___ *obj=objectarray[it->tagobjectslot];
5318 struct ___Object___ *tagptr=obj->___tags___;
5319 if (tagptr->type==TAGTYPE) {
5320 if ((it->tagobjindex==0)&& /* First object */
5321 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
5326 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
5327 int tagindex=it->tagobjindex;
5328 for(; tagindex<ao->___cachedCode___; tagindex++) {
5329 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
5330 if (td->flag==it->tagid) {
5331 it->tagobjindex=tagindex; /* Found right type of tag */
5337 } else if (it->numtags>0) {
5338 /* Use tags to locate appropriate objects */
5339 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
5340 struct ___Object___ *objptr=tag->flagptr;
5342 if (objptr->type!=OBJECTARRAYTYPE) {
5343 if (it->tagobjindex>0)
5345 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
5347 for(i=1; i<it->numtags; i++) {
5348 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
5349 if (!containstag(objptr,tag2))
5354 struct ArrayObject *ao=(struct ArrayObject *) objptr;
5357 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
5358 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
5359 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
5361 for(i=1; i<it->numtags; i++) {
5362 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
5363 if (!containstag(objptr,tag2))
5366 it->tagobjindex=tagindex;
5371 it->tagobjindex=tagindex;
5375 return ObjhasNext(&it->it);
5379 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
5381 struct ___Object___ * objptr=tag->flagptr;
5382 if (objptr->type==OBJECTARRAYTYPE) {
5383 struct ArrayObject *ao=(struct ArrayObject *)objptr;
5384 for(j=0; j<ao->___cachedCode___; j++) {
5385 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
5393 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
5394 /* hasNext has all of the intelligence */
5397 /* Get object with tags */
5398 struct ___Object___ *obj=objectarray[it->tagobjectslot];
5399 struct ___Object___ *tagptr=obj->___tags___;
5400 if (tagptr->type==TAGTYPE) {
5402 objectarray[it->slot]=tagptr;
5404 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
5405 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
5407 } else if (it->numtags>0) {
5408 /* Use tags to locate appropriate objects */
5409 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
5410 struct ___Object___ *objptr=tag->flagptr;
5411 if (objptr->type!=OBJECTARRAYTYPE) {
5413 objectarray[it->slot]=objptr;
5415 struct ArrayObject *ao=(struct ArrayObject *) objptr;
5416 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
5419 /* Iterate object */
5420 objectarray[it->slot]=(void *)Objkey(&it->it);