add profile codes for multicore version
[IRC.git] / Robust / src / Runtime / multicoretask.c
1 #ifdef TASK
2 #include "runtime.h"
3 #ifndef RAW
4 #include "structdefs.h"
5 #include "mem.h"
6 #include "checkpoint.h"
7 #include "Queue.h"
8 #include "SimpleHash.h"
9 #include "GenericHashtable.h"
10 #include <sys/select.h>
11 #include <sys/types.h>
12 #include <sys/mman.h>
13 #include <string.h>
14 #include <signal.h>
15 #include <assert.h>
16 #include <errno.h>
17 #endif
18 #ifdef RAW
19 #ifdef RAWPROFILE
20 #include "stdio.h"
21 #include "string.h"
22 #endif
23 #include <raw.h>
24 #include <raw_compiler_defs.h>
25 #elif defined THREADSIMULATE
26 // use POSIX message queue
27 // for each core, its message queue named as
28 // /msgqueue_corenum
29 #include <mqueue.h>
30 #include <sys/stat.h>
31 #endif
32 /*
33    extern int injectfailures;
34    extern float failurechance;
35  */
36 extern int debugtask;
37 extern int instaccum;
38
39 #ifdef RAW
40 #define TOTALCORE raw_get_num_tiles()
41 #endif
42
43 #ifdef CONSCHECK
44 #include "instrument.h"
45 #endif
46
47 struct genhashtable * activetasks;
48 struct genhashtable * failedtasks;
49 struct taskparamdescriptor * currtpd;
50 #ifndef RAW
51 struct RuntimeHash * forward;
52 struct RuntimeHash * reverse;
53 #endif
54
55 int corestatus[NUMCORES]; // records status of each core
56                           // 1: running tasks
57 // 0: stall
58 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
59 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
60 #ifdef RAW
61 struct RuntimeHash locktable;
62 static struct RuntimeHash* locktbl = &locktable;
63 void * curr_heapbase=0;
64 void * curr_heaptop=0;
65 int self_numsendobjs;
66 int self_numreceiveobjs;
67 int lockobj;
68 int lockresult;
69 bool lockflag;
70 #ifndef INTERRUPT
71 bool reside;
72 #endif
73 struct Queue objqueue;
74 int msgdata[30];
75 int msgtype;
76 int msgdataindex;
77 int msglength;
78 int outmsgdata[30];
79 int outmsgindex;
80 int outmsglast;
81 int outmsgleft;
82 bool isMsgHanging;
83 bool isMsgSending;
84 void calCoords(int core_num, int* coordY, int* coordX);
85 #elif defined THREADSIMULATE
86 static struct RuntimeHash* locktbl;
87 struct thread_data {
88   int corenum;
89   int argc;
90   char** argv;
91   int numsendobjs;
92   int numreceiveobjs;
93 };
94 struct thread_data thread_data_array[NUMCORES];
95 mqd_t mqd[NUMCORES];
96 static pthread_key_t key;
97 static pthread_rwlock_t rwlock_tbl;
98 static pthread_rwlock_t rwlock_init;
99
100 void run(void * arg);
101 #endif
102
103 bool transStallMsg(int targetcore);
104 void transTerminateMsg(int targetcore);
105 int receiveObject();
106 bool getreadlock(void* ptr);
107 void releasereadlock(void* ptr);
108 #ifdef RAW
109 bool getreadlock_I(void* ptr);
110 void releasereadlock_I(void* ptr);
111 #endif
112 bool getwritelock(void* ptr);
113 void releasewritelock(void* ptr);
114
115 // profiling mode of RAW version
116 #ifdef RAWPROFILE
117 //#include "stdio.h"
118 //#include "string.h"
119
120 #define TASKINFOLENGTH 150
121 #define INTERRUPTINFOLENGTH 500
122
123 bool stall;
124 bool isInterrupt;
125 int totalexetime;
126
127 typedef struct task_info {
128   char* taskName;
129   int startTime;
130   int endTime;
131 } TaskInfo;
132
133 typedef struct interrupt_info {
134   int startTime;
135   int endTime;
136 } InterruptInfo;
137
138 TaskInfo * taskInfoArray[TASKINFOLENGTH];
139 int taskInfoIndex;
140 bool taskInfoOverflow;
141 InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
142 int interruptInfoIndex;
143 bool interruptInfoOverflow;
144 int profilestatus[NUMCORES]; // records status of each core
145                              // 1: running tasks
146 // 0: stall
147 bool transProfileRequestMsg(int targetcore);
148 void outputProfileData();
149 #endif
150
151 #ifdef RAW
152 #ifdef RAWPROFILE
153 int main(void) {
154 #else
155 void begin() {
156 #endif
157 #else
158 int main(int argc, char **argv) {
159 #endif
160 #ifdef RAW
161   int i = 0;
162   int argc = 1;
163   char ** argv = NULL;
164   bool sendStall = false;
165   bool isfirst = true;
166   bool tocontinue = false;
167   struct QueueItem * objitem = NULL;
168   struct transObjInfo * objInfo = NULL;
169   int grount = 0;
170   bool allStall = true;
171   int sumsendobj = 0;
172
173 #ifdef RAWDEBUG
174   raw_test_pass(0xee01);
175 #endif
176   corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
177
178   // initialize the arrays
179   if(STARTUPCORE == corenum) {
180     // startup core to initialize corestatus[]
181     for(i = 0; i < NUMCORES; ++i) {
182       corestatus[i] = 1;
183       numsendobjs[i] = 0;                   // assume all variables in RAW are local variables! MAY BE WRONG!!!
184       numreceiveobjs[i] = 0;
185     }
186 #ifdef RAWPROFILE
187     for(i = 0; i < NUMCORES; ++i) {
188       profilestatus[i] = 1;
189     }
190 #endif
191   }
192   self_numsendobjs = 0;
193   self_numreceiveobjs = 0;
194   for(i = 0; i < 30; ++i) {
195     msgdata[i] = -1;
196   }
197   //msgdata = NULL;
198   msgtype = -1;
199   msgdataindex = 0;
200   msglength = 30;
201
202   for(i = 0; i < 30; ++i) {
203     outmsgdata[i] = -1;
204   }
205   outmsgindex = 0;
206   outmsglast = 0;
207   outmsgleft = 0;
208   isMsgHanging = false;
209   isMsgSending = false;
210 #ifdef RAWDEBUG
211   raw_test_pass(0xee02);
212 #endif
213
214   // create the lock table, lockresult table and obj queue
215   locktable.size = 20;
216   locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
217   /* Set allocation blocks*/
218   locktable.listhead=NULL;
219   locktable.listtail=NULL;
220   /*Set data counts*/
221   locktable.numelements = 0;
222   lockobj = 0;
223   lockresult = 0;
224   lockflag = false;
225 #ifndef INTERRUPT
226   reside = false;
227 #endif
228   objqueue.head = NULL;
229   objqueue.tail = NULL;
230 #ifdef RAWDEBUG
231   raw_test_pass(0xee03);
232 #endif
233
234 #ifdef RAWPROFILE
235   stall = false;
236   isInterrupt = true;
237   totalexetime = -1;
238   taskInfoIndex = 0;
239   interruptInfoIndex = 0;
240   taskInfoOverflow = false;
241   interruptInfoOverflow = false;
242 #endif
243
244 #ifdef INTERRUPT
245   if (corenum < NUMCORES) {
246     // set up interrupts
247     setup_ints();
248     //setup_interrupts();
249     //start_gdn_avail_ints(recvMsg);
250     raw_user_interrupts_on();
251 #ifdef RAWDEBUG
252     raw_test_pass(0xee04);
253 #endif
254   }
255 #endif
256
257 #elif defined THREADSIMULATE
258   errno = 0;
259   int tids[NUMCORES];
260   int rc[NUMCORES];
261   pthread_t threads[NUMCORES];
262   int i = 0;
263
264   // initialize three arrays and msg queue array
265   char * pathhead = "/msgqueue_";
266   int targetlen = strlen(pathhead);
267   for(i = 0; i < NUMCORES; ++i) {
268     corestatus[i] = 1;
269     numsendobjs[i] = 0;
270     numreceiveobjs[i] = 0;
271
272     char corenumstr[3];
273     int sourcelen = 0;
274     if(i < 10) {
275       corenumstr[0] = i + '0';
276       corenumstr[1] = '\0';
277       sourcelen = 1;
278     } else if(i < 100) {
279       corenumstr[1] = i %10 + '0';
280       corenumstr[0] = (i / 10) + '0';
281       corenumstr[2] = '\0';
282       sourcelen = 2;
283     } else {
284       printf("Error: i >= 100\n");
285       fflush(stdout);
286       exit(-1);
287     }
288     char path[targetlen + sourcelen + 1];
289     strcpy(path, pathhead);
290     strncat(path, corenumstr, sourcelen);
291     int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
292     int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
293     mq_unlink(path);
294     mqd[i]= mq_open(path, oflags, omodes, NULL);
295     if(mqd[i] == -1) {
296       printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
297       exit(-1);
298     } else {
299       printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
300     }
301   }
302
303   // create the key
304   pthread_key_create(&key, NULL);
305
306   // create the lock table and initialize its mutex
307   locktbl = allocateRuntimeHash(20);
308   int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
309   printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
310
311   for(i = 0; i < NUMCORES; ++i) {
312     thread_data_array[i].corenum = i;
313     thread_data_array[i].argc = argc;
314     thread_data_array[i].argv = argv;
315     thread_data_array[i].numsendobjs = 0;
316     thread_data_array[i].numreceiveobjs = 0;
317     printf("[main] creating thread %d\n", i);
318     rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
319     if (rc[i]) {
320       printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
321       fflush(stdout);
322       exit(-1);
323     }
324   }
325
326   //pthread_exit(NULL);
327   while(true) {
328   }
329 }
330
331 void run(void* arg) {
332   struct thread_data * my_tdata = (struct thread_data *)arg;
333   pthread_setspecific(key, (void *)my_tdata->corenum);
334   int argc = my_tdata->argc;
335   char** argv = my_tdata->argv;
336   printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
337   fflush(stdout);
338
339 #endif
340
341 #ifdef BOEHM_GC
342   GC_init(); // Initialize the garbage collector
343 #endif
344 #ifdef CONSCHECK
345   initializemmap();
346 #endif
347 #ifndef RAW
348   processOptions();
349 #endif
350   initializeexithandler();
351 #ifdef RAWDEBUG
352   raw_test_pass(0xee05);
353 #endif
354   /* Create table for failed tasks */
355 #ifdef RAW
356   if(corenum > NUMCORES - 1) {
357     failedtasks = NULL;
358     activetasks = NULL;
359 /*#ifdef RAWPROFILE
360         raw_test_pass(0xee01);
361         raw_test_pass_reg(taskInfoIndex);
362         raw_test_pass_reg(taskInfoOverflow);
363         if(!taskInfoOverflow) {
364         TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
365         taskInfoArray[taskInfoIndex] = taskInfo;
366         taskInfo->taskName = "msg handling";
367         taskInfo->startTime = raw_get_cycle();
368         taskInfo->endTime = -1;
369         }
370  #endif*/
371 #ifdef RAWPROFILE
372     isInterrupt = false;
373 #endif
374     while(true) {
375       receiveObject();
376     }
377   } else {
378 #ifdef RAWDEBUG
379     raw_test_pass(0xee06);
380 #endif
381 #endif
382   /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
383                                    (int (*)(void *,void *)) &comparetpd);*/
384   failedtasks = NULL;
385 #ifdef RAWDEBUG
386   raw_test_pass(0xee07);
387 #endif
388   /* Create queue of active tasks */
389   activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
390                                    (int(*) (void *,void *)) &comparetpd);
391 #ifdef RAWDEBUG
392   raw_test_pass(0xee08);
393 #endif
394
395   /* Process task information */
396   processtasks();
397 #ifdef RAWDEBUG
398   raw_test_pass(0xee09);
399 #endif
400
401   if(STARTUPCORE == corenum) {
402     /* Create startup object */
403     createstartupobject(argc, argv);
404   }
405 #ifdef RAWDEBUG
406   raw_test_pass(0xee0a);
407 #endif
408
409 #ifdef RAW
410 #ifdef RAWDEBUG
411   raw_test_pass(0xee0b);
412 #endif
413
414   while(true) {
415 /*#ifndef INTERRUPT
416           while(receiveObject() != -1) {
417           }
418  #endif*/
419
420     // check if there are new active tasks can be executed
421     executetasks();
422
423 #ifndef INTERRUPT
424     while(receiveObject() != -1) {
425     }
426 #endif
427
428 #ifdef RAWDEBUG
429     raw_test_pass(0xee0c);
430 #endif
431
432     // check if there are some pending objects, if yes, enqueue them and executetasks again
433     tocontinue = false;
434 #ifdef RAWDEBUG
435     raw_test_pass(0xee0d);
436 #endif
437 #ifdef RAWPROFILE
438     {
439       bool isChecking = false;
440       if(!isEmpty(&objqueue)) {
441         if(!taskInfoOverflow) {
442           TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
443           taskInfoArray[taskInfoIndex] = taskInfo;
444           taskInfo->taskName = "objqueue checking";
445           taskInfo->startTime = raw_get_cycle();
446           taskInfo->endTime = -1;
447         }
448         isChecking = true;
449       }
450 #endif
451     while(!isEmpty(&objqueue)) {
452       void * obj = NULL;
453 #ifdef INTERRUPT
454       raw_user_interrupts_off();
455 #endif
456 #ifdef RAWPROFILE
457       isInterrupt = false;
458 #endif
459 #ifdef RAWDEBUG
460       raw_test_pass(0xeee1);
461 #endif
462       sendStall = false;
463       tocontinue = true;
464       objitem = getTail(&objqueue);
465       //obj = objitem->objectptr;
466       objInfo = (struct transObjInfo *)objitem->objectptr;
467       obj = objInfo->objptr;
468 #ifdef RAWDEBUG
469       raw_test_pass_reg((int)obj);
470 #endif
471       // grab lock and flush the obj
472       getreadlock_I(obj);
473       while(!lockflag) {
474         receiveObject();
475       }
476       grount = lockresult;
477 #ifdef RAWDEBUG
478       raw_test_pass_reg(grount);
479 #endif
480
481       lockresult = 0;
482       lockobj = 0;
483       lockflag = false;
484 #ifndef INTERRUPT
485       reside = false;
486 #endif
487
488       if(grount == 1) {
489         int k = 0;
490         raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
491         // flush the obj
492         /*for(k = 0; k < classsize[((struct ___Object___ *)obj)->type]; ++k) {
493                 invalidateAddr(obj + k);
494            }*/
495         // enqueue the object
496         for(k = 0; k < objInfo->length; ++k) {
497           int taskindex = objInfo->queues[2 * k];
498           int paramindex = objInfo->queues[2 * k + 1];
499           struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
500 #ifdef RAWDEBUG
501           raw_test_pass_reg(taskindex);
502           raw_test_pass_reg(paramindex);
503 #endif
504           enqueueObject_I(obj, queues, 1);
505         }
506         removeItem(&objqueue, objitem);
507         releasereadlock_I(obj);
508         RUNFREE(objInfo->queues);
509         RUNFREE(objInfo);
510         /*enqueueObject_I(obj, NULL, 0);
511            removeItem(&objqueue, objitem);
512            releasereadlock_I(obj);*/
513       } else {
514         // can not get lock
515         // put it at the end of the queue
516         // and try to execute active tasks already enqueued first
517         removeItem(&objqueue, objitem);
518         addNewItem_I(&objqueue, objInfo);
519 #ifdef RAWPROFILE
520         isInterrupt = true;
521 #endif
522 #ifdef INTERRUPT
523         raw_user_interrupts_on();
524 #endif
525         break;
526       }
527 #ifdef INTERRUPT
528       raw_user_interrupts_on();
529 #endif
530 #ifdef RAWDEBUG
531       raw_test_pass(0xee0e);
532 #endif
533     }
534 #ifdef RAWPROFILE
535     if(isChecking && (!taskInfoOverflow)) {
536       taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
537       taskInfoIndex++;
538       if(taskInfoIndex == TASKINFOLENGTH) {
539         taskInfoOverflow = true;
540       }
541     }
542   }
543 #endif
544 #ifdef RAWDEBUG
545     raw_test_pass(0xee0f);
546 #endif
547
548     if(!tocontinue) {
549       // check if stop
550       if(STARTUPCORE == corenum) {
551         if(isfirst) {
552 #ifdef RAWDEBUG
553           raw_test_pass(0xee10);
554 #endif
555           isfirst = false;
556         }
557 #ifdef INTERRUPT
558         raw_user_interrupts_off();
559 #endif
560         corestatus[corenum] = 0;
561         numsendobjs[corenum] = self_numsendobjs;
562         numreceiveobjs[corenum] = self_numreceiveobjs;
563         // check the status of all cores
564         allStall = true;
565 #ifdef RAWDEBUG
566         raw_test_pass_reg(NUMCORES);
567 #endif
568         for(i = 0; i < NUMCORES; ++i) {
569 #ifdef RAWDEBUG
570           raw_test_pass(0xe000 + corestatus[i]);
571 #endif
572           if(corestatus[i] != 0) {
573             allStall = false;
574             break;
575           }
576         }
577         if(allStall) {
578           // check if the sum of send objs and receive obj are the same
579           // yes->terminate; for profiling mode, yes->send request to all
580           // other cores to pour out profiling data
581           // no->go on executing
582           sumsendobj = 0;
583           for(i = 0; i < NUMCORES; ++i) {
584             sumsendobj += numsendobjs[i];
585 #ifdef RAWDEBUG
586             raw_test_pass(0xf000 + numsendobjs[i]);
587 #endif
588           }
589           for(i = 0; i < NUMCORES; ++i) {
590             sumsendobj -= numreceiveobjs[i];
591 #ifdef RAWDEBUG
592             raw_test_pass(0xf000 + numreceiveobjs[i]);
593 #endif
594           }
595           if(0 == sumsendobj) {
596             // terminate
597 #ifdef RAWDEBUG
598             raw_test_pass(0xee11);
599 #endif
600 #ifdef RAWPROFILE
601             totalexetime = raw_get_cycle();
602 #else
603             raw_test_pass(0xbbbbbbbb);
604             raw_test_pass(raw_get_cycle());
605 #endif
606
607             // profile mode, send msgs to other cores to request pouring
608             // out progiling data
609 #ifdef RAWPROFILE
610 #ifdef INTERRUPT
611             // reopen gdn_avail interrupts
612             raw_user_interrupts_on();
613 #endif
614             for(i = 1; i < NUMCORES; ++i) {
615               transProfileRequestMsg(i);
616             }
617             // pour profiling data on startup core
618             outputProfileData();
619             while(true) {
620 #ifdef INTERRUPT
621               raw_user_interrupts_off();
622 #endif
623               profilestatus[corenum] = 0;
624               // check the status of all cores
625               allStall = true;
626 #ifdef RAWDEBUG
627               raw_test_pass_reg(NUMCORES);
628 #endif
629               for(i = 0; i < NUMCORES; ++i) {
630 #ifdef RAWDEBUG
631                 raw_test_pass(0xe000 + profilestatus[i]);
632 #endif
633                 if(profilestatus[i] != 0) {
634                   allStall = false;
635                   break;
636                 }
637               }
638               if(!allStall) {
639                 int halt = 10000;
640 #ifdef INTERRUPT
641                 raw_user_interrupts_on();
642 #endif
643                 while(halt--) {
644                 }
645               } else {
646                 break;
647               }
648             }
649 #endif
650
651             raw_test_done(1);                                   // All done.
652           }
653         }
654 #ifdef INTERRUPT
655         raw_user_interrupts_on();
656 #endif
657       } else {
658         if(!sendStall) {
659 #ifdef RAWDEBUG
660           raw_test_pass(0xee12);
661 #endif
662 #ifdef RAWPROFILE
663           if(!stall) {
664 #endif
665           if(isfirst) {
666             // wait for some time
667             int halt = 10000;
668 #ifdef RAWDEBUG
669             raw_test_pass(0xee13);
670 #endif
671             while(halt--) {
672             }
673             isfirst = false;
674 #ifdef RAWDEBUG
675             raw_test_pass(0xee14);
676 #endif
677           } else {
678             // send StallMsg to startup core
679 #ifdef RAWDEBUG
680             raw_test_pass(0xee15);
681 #endif
682             sendStall = transStallMsg(STARTUPCORE);
683             isfirst = true;
684           }
685 #ifdef RAWPROFILE
686         }
687 #endif
688         } else {
689           isfirst = true;
690 #ifdef RAWDEBUG
691           raw_test_pass(0xee16);
692 #endif
693         }
694       }
695     }
696   }
697 }
698 #elif defined THREADSIMULATE
699   /* Start executing the tasks */
700   executetasks();
701
702   int i = 0;
703   // check if there are new objects coming
704   bool sendStall = false;
705
706   int numofcore = pthread_getspecific(key);
707   while(true) {
708     switch(receiveObject()) {
709     case 0: {
710       printf("[run, %d] receive an object\n", numofcore);
711       sendStall = false;
712       // received an object
713       // check if there are new active tasks can be executed
714       executetasks();
715       break;
716     }
717
718     case 1: {
719       //printf("[run, %d] no msg\n", numofcore);
720       // no msg received
721       if(STARTUPCORE == numofcore) {
722         corestatus[numofcore] = 0;
723         // check the status of all cores
724         bool allStall = true;
725         for(i = 0; i < NUMCORES; ++i) {
726           if(corestatus[i] != 0) {
727             allStall = false;
728             break;
729           }
730         }
731         if(allStall) {
732           // check if the sum of send objs and receive obj are the same
733           // yes->terminate
734           // no->go on executing
735           int sumsendobj = 0;
736           for(i = 0; i < NUMCORES; ++i) {
737             sumsendobj += numsendobjs[i];
738           }
739           for(i = 0; i < NUMCORES; ++i) {
740             sumsendobj -= numreceiveobjs[i];
741           }
742           if(0 == sumsendobj) {
743             // terminate
744
745             // release all locks
746             int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
747             printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
748             struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl);
749             while(0 != RunhasNext(it_lock)) {
750               int key = Runkey(it_lock);
751               pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
752               int rc_des = pthread_rwlock_destroy(rwlock_obj);
753               printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
754               RUNFREE(rwlock_obj);
755             }
756             freeRuntimeHash(locktbl);
757             locktbl = NULL;
758             RUNFREE(it_lock);
759
760             // destroy all message queues
761             char * pathhead = "/msgqueue_";
762             int targetlen = strlen(pathhead);
763             for(i = 0; i < NUMCORES; ++i) {
764               char corenumstr[3];
765               int sourcelen = 0;
766               if(i < 10) {
767                 corenumstr[0] = i + '0';
768                 corenumstr[1] = '\0';
769                 sourcelen = 1;
770               } else if(i < 100) {
771                 corenumstr[1] = i %10 + '0';
772                 corenumstr[0] = (i / 10) + '0';
773                 corenumstr[2] = '\0';
774                 sourcelen = 2;
775               } else {
776                 printf("Error: i >= 100\n");
777                 fflush(stdout);
778                 exit(-1);
779               }
780               char path[targetlen + sourcelen + 1];
781               strcpy(path, pathhead);
782               strncat(path, corenumstr, sourcelen);
783               mq_unlink(path);
784             }
785
786             printf("[run, %d] terminate!\n", numofcore);
787             fflush(stdout);
788             exit(0);
789           }
790         }
791       } else {
792         if(!sendStall) {
793           // send StallMsg to startup core
794           sendStall = transStallMsg(STARTUPCORE);
795         }
796       }
797       break;
798     }
799
800     case 2: {
801       printf("[run, %d] receive a stall msg\n", numofcore);
802       // receive a Stall Msg, do nothing
803       assert(STARTUPCORE == numofcore);                                     // only startup core can receive such msg
804       sendStall = false;
805       break;
806     }
807
808       /* case 3: {
809                                printf("[run, %d] receive a terminate msg\n", numofcore);
810                                // receive a terminate Msg
811                                assert(STARTUPCORE != corenum); // only non-startup core can receive such msg
812                                mq_close(mqd[corenum]);
813                                fflush(stdout);
814                                exit(0);
815                                break;
816                        }*/
817     default: {
818       printf("[run, %d] Error: invalid message type.\n", numofcore);
819       fflush(stdout);
820       exit(-1);
821       break;
822     }
823     }
824   }
825 #endif
826 }
827
828 void createstartupobject(int argc, char ** argv) {
829   int i;
830
831   /* Allocate startup object     */
832 #ifdef PRECISE_GC
833   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
834   struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
835 #else
836   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
837   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
838 #endif
839   /* Build array of strings */
840   startupobject->___parameters___=stringarray;
841   for(i=1; i<argc; i++) {
842     int length=strlen(argv[i]);
843 #ifdef PRECISE_GC
844     struct ___String___ *newstring=NewString(NULL, argv[i],length);
845 #else
846     struct ___String___ *newstring=NewString(argv[i],length);
847 #endif
848     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
849   }
850
851   startupobject->isolate = 1;
852   startupobject->version = 0;
853
854   /* Set initialized flag for startup object */
855   flagorandinit(startupobject,1,0xFFFFFFFF);
856   enqueueObject(startupobject, NULL, 0);
857 #ifdef RAW
858   //flushAll();
859   raw_flush_entire_cache();
860 #endif
861 }
862
863 int hashCodetpd(struct taskparamdescriptor *ftd) {
864   int hash=(int)ftd->task;
865   int i;
866   for(i=0; i<ftd->numParameters; i++) {
867     hash^=(int)ftd->parameterArray[i];
868   }
869   return hash;
870 }
871
872 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
873   int i;
874   if (ftd1->task!=ftd2->task)
875     return 0;
876   for(i=0; i<ftd1->numParameters; i++)
877     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
878       return 0;
879   return 1;
880 }
881
882 /* This function sets a tag. */
883 #ifdef PRECISE_GC
884 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
885 #else
886 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
887 #endif
888   struct ArrayObject * ao=NULL;
889   struct ___Object___ * tagptr=obj->___tags___;
890 #ifdef RAWDEBUG
891   raw_test_pass(0xebb0);
892 #endif
893   if (tagptr==NULL) {
894 #ifdef RAWDEBUG
895     raw_test_pass(0xebb1);
896 #endif
897     obj->___tags___=(struct ___Object___ *)tagd;
898   } else {
899     /* Have to check if it is already set */
900     if (tagptr->type==TAGTYPE) {
901       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
902 #ifdef RAWDEBUG
903       raw_test_pass(0xebb2);
904 #endif
905       if (td==tagd) {
906 #ifdef RAWDEBUG
907         raw_test_pass(0xebb3);
908 #endif
909         return;
910       }
911 #ifdef PRECISE_GC
912       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
913       struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
914       obj=(struct ___Object___ *)ptrarray[2];
915       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
916       td=(struct ___TagDescriptor___ *) obj->___tags___;
917 #else
918 #ifdef RAWDEBUG
919       raw_test_pass(0xebb4);
920 #endif
921       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
922 #endif
923 #ifdef RAWDEBUG
924       raw_test_pass(0xebb5);
925 #endif
926       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
927       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
928       obj->___tags___=(struct ___Object___ *) ao;
929       ao->___cachedCode___=2;
930 #ifdef RAWDEBUG
931       raw_test_pass(0xebb6);
932 #endif
933     } else {
934       /* Array Case */
935       int i;
936       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
937 #ifdef RAWDEBUG
938       raw_test_pass(0xebb7);
939 #endif
940       for(i=0; i<ao->___cachedCode___; i++) {
941         struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
942 #ifdef RAWDEBUG
943         raw_test_pass(0xebb8);
944 #endif
945         if (td==tagd) {
946 #ifdef RAWDEBUG
947           raw_test_pass(0xebb9);
948 #endif
949           return;
950         }
951       }
952       if (ao->___cachedCode___<ao->___length___) {
953 #ifdef RAWDEBUG
954         raw_test_pass(0xebba);
955 #endif
956         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
957         ao->___cachedCode___++;
958 #ifdef RAWDEBUG
959         raw_test_pass(0xebbb);
960 #endif
961       } else {
962 #ifdef PRECISE_GC
963         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
964         struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
965         obj=(struct ___Object___ *)ptrarray[2];
966         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
967         ao=(struct ArrayObject *)obj->___tags___;
968 #else
969         struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
970 #endif
971 #ifdef RAWDEBUG
972         raw_test_pass(0xebbc);
973 #endif
974         aonew->___cachedCode___=ao->___length___+1;
975         for(i=0; i<ao->___length___; i++) {
976 #ifdef RAWDEBUG
977           raw_test_pass(0xebbd);
978 #endif
979           ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
980         }
981 #ifdef RAWDEBUG
982         raw_test_pass(0xebbe);
983 #endif
984         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
985 #ifdef RAWDEBUG
986         raw_test_pass(0xebbf);
987 #endif
988       }
989     }
990   }
991
992   {
993     struct ___Object___ * tagset=tagd->flagptr;
994 #ifdef RAWDEBUG
995     raw_test_pass(0xb008);
996 #endif
997     if(tagset==NULL) {
998 #ifdef RAWDEBUG
999       raw_test_pass(0xb009);
1000 #endif
1001       tagd->flagptr=obj;
1002     } else if (tagset->type!=OBJECTARRAYTYPE) {
1003 #ifdef PRECISE_GC
1004       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1005       struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1006       obj=(struct ___Object___ *)ptrarray[2];
1007       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1008 #else
1009       struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1010 #endif
1011       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
1012       ARRAYSET(ao, struct ___Object___ *, 1, obj);
1013       ao->___cachedCode___=2;
1014       tagd->flagptr=(struct ___Object___ *)ao;
1015 #ifdef RAWDEBUG
1016       raw_test_pass(0xb00a);
1017 #endif
1018     } else {
1019       struct ArrayObject *ao=(struct ArrayObject *) tagset;
1020       if (ao->___cachedCode___<ao->___length___) {
1021 #ifdef RAWDEBUG
1022         raw_test_pass(0xb00b);
1023 #endif
1024         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
1025       } else {
1026         int i;
1027 #ifdef PRECISE_GC
1028         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
1029         struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
1030         obj=(struct ___Object___ *)ptrarray[2];
1031         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
1032         ao=(struct ArrayObject *)tagd->flagptr;
1033 #else
1034         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
1035 #endif
1036         aonew->___cachedCode___=ao->___cachedCode___+1;
1037         for(i=0; i<ao->___length___; i++) {
1038           ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
1039         }
1040         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
1041         tagd->flagptr=(struct ___Object___ *) aonew;
1042 #ifdef RAWDEBUG
1043         raw_test_pass(0xb00c);
1044 #endif
1045       }
1046     }
1047   }
1048 }
1049
1050 /* This function clears a tag. */
1051 #ifdef PRECISE_GC
1052 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1053 #else
1054 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
1055 #endif
1056   /* We'll assume that tag is alway there.
1057      Need to statically check for this of course. */
1058   struct ___Object___ * tagptr=obj->___tags___;
1059
1060   if (tagptr->type==TAGTYPE) {
1061     if ((struct ___TagDescriptor___ *)tagptr==tagd)
1062       obj->___tags___=NULL;
1063     else
1064 #ifndef RAW
1065       printf("ERROR 1 in tagclear\n");
1066 #endif
1067       ;
1068   } else {
1069     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1070     int i;
1071     for(i=0; i<ao->___cachedCode___; i++) {
1072       struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
1073       if (td==tagd) {
1074         ao->___cachedCode___--;
1075         if (i<ao->___cachedCode___)
1076           ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
1077         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
1078         if (ao->___cachedCode___==0)
1079           obj->___tags___=NULL;
1080         goto PROCESSCLEAR;
1081       }
1082     }
1083 #ifndef RAW
1084     printf("ERROR 2 in tagclear\n");
1085 #endif
1086     ;
1087   }
1088 PROCESSCLEAR:
1089   {
1090     struct ___Object___ *tagset=tagd->flagptr;
1091     if (tagset->type!=OBJECTARRAYTYPE) {
1092       if (tagset==obj)
1093         tagd->flagptr=NULL;
1094       else
1095 #ifndef RAW
1096         printf("ERROR 3 in tagclear\n");
1097 #endif
1098         ;
1099     } else {
1100       struct ArrayObject *ao=(struct ArrayObject *) tagset;
1101       int i;
1102       for(i=0; i<ao->___cachedCode___; i++) {
1103         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
1104         if (tobj==obj) {
1105           ao->___cachedCode___--;
1106           if (i<ao->___cachedCode___)
1107             ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
1108           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
1109           if (ao->___cachedCode___==0)
1110             tagd->flagptr=NULL;
1111           goto ENDCLEAR;
1112         }
1113       }
1114 #ifndef RAW
1115       printf("ERROR 4 in tagclear\n");
1116 #endif
1117     }
1118   }
1119 ENDCLEAR:
1120   return;
1121 }
1122
1123 /* This function allocates a new tag. */
1124 #ifdef PRECISE_GC
1125 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
1126   struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
1127 #else
1128 struct ___TagDescriptor___ * allocate_tag(int index) {
1129   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
1130 #endif
1131   v->type=TAGTYPE;
1132   v->flag=index;
1133   return v;
1134 }
1135
1136
1137
1138 /* This function updates the flag for object ptr.  It or's the flag
1139    with the or mask and and's it with the andmask. */
1140
1141 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
1142
1143 int flagcomp(const int *val1, const int *val2) {
1144   return (*val1)-(*val2);
1145 }
1146
1147 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
1148   {
1149     int oldflag=((int *)ptr)[1];
1150     int flag=ormask|oldflag;
1151     flag&=andmask;
1152 #ifdef RAWDEBUG
1153     raw_test_pass_reg((int)ptr);
1154     raw_test_pass(0xaa000000 + oldflag);
1155     raw_test_pass(0xaa000000 + flag);
1156 #endif
1157     flagbody(ptr, flag, queues, length, false);
1158   }
1159 }
1160
1161 bool intflagorand(void * ptr, int ormask, int andmask) {
1162   {
1163     int oldflag=((int *)ptr)[1];
1164     int flag=ormask|oldflag;
1165     flag&=andmask;
1166     if (flag==oldflag)   /* Don't do anything */
1167       return false;
1168     else {
1169       flagbody(ptr, flag, NULL, 0, false);
1170       return true;
1171     }
1172   }
1173 }
1174
1175 void flagorandinit(void * ptr, int ormask, int andmask) {
1176   int oldflag=((int *)ptr)[1];
1177   int flag=ormask|oldflag;
1178   flag&=andmask;
1179 #ifdef RAWDEBUG
1180   raw_test_pass(0xaa100000 + oldflag);
1181   raw_test_pass(0xaa100000 + flag);
1182 #endif
1183   flagbody(ptr,flag,NULL,0,true);
1184 }
1185
1186 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
1187   struct parameterwrapper * flagptr = NULL;
1188   int i = 0;
1189   struct parameterwrapper ** queues = vqueues;
1190   int length = vlength;
1191   int next;
1192   int UNUSED, UNUSED2;
1193   int * enterflags = NULL;
1194   if((!isnew) && (queues == NULL)) {
1195 #ifdef THREADSIMULATE
1196     int numofcore = pthread_getspecific(key);
1197     queues = objectqueues[numofcore][ptr->type];
1198     length = numqueues[numofcore][ptr->type];
1199 #else
1200 #ifdef RAW
1201     if(corenum < NUMCORES) {
1202 #endif
1203     queues = objectqueues[corenum][ptr->type];
1204     length = numqueues[corenum][ptr->type];
1205 #ifdef RAW
1206   } else {
1207     return;
1208   }
1209 #endif
1210 #endif
1211   }
1212   ptr->flag=flag;
1213 #ifdef RAWDEBUG
1214   raw_test_pass(0xbb000000 + ptr->flag);
1215 #endif
1216
1217   /*Remove object from all queues */
1218   for(i = 0; i < length; ++i) {
1219     flagptr = queues[i];
1220     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1221     ObjectHashremove(flagptr->objectset, (int)ptr);
1222     if (enterflags!=NULL)
1223       RUNFREE(enterflags);
1224   }
1225 }
1226
1227 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1228   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1229
1230   {
1231     struct QueueItem *tmpptr;
1232     struct parameterwrapper * parameter=NULL;
1233     int j;
1234     int i;
1235     struct parameterwrapper * prevptr=NULL;
1236     struct ___Object___ *tagptr=NULL;
1237     struct parameterwrapper ** queues = vqueues;
1238     int length = vlength;
1239 #ifdef RAW
1240     if(corenum > NUMCORES - 1) {
1241       return;
1242     }
1243 #endif
1244     if(queues == NULL) {
1245 #ifdef THREADSIMULATE
1246       int numofcore = pthread_getspecific(key);
1247       queues = objectqueues[numofcore][ptr->type];
1248       length = numqueues[numofcore][ptr->type];
1249 #else
1250       queues = objectqueues[corenum][ptr->type];
1251       length = numqueues[corenum][ptr->type];
1252 #endif
1253     }
1254     tagptr=ptr->___tags___;
1255
1256     /* Outer loop iterates through all parameter queues an object of
1257        this type could be in.  */
1258     for(j = 0; j < length; ++j) {
1259       parameter = queues[j];
1260       /* Check tags */
1261       if (parameter->numbertags>0) {
1262         if (tagptr==NULL)
1263           goto nextloop; //that means the object has no tag but that param needs tag
1264         else if(tagptr->type==TAGTYPE) { //one tag
1265           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1266           for(i=0; i<parameter->numbertags; i++) {
1267             //slotid is parameter->tagarray[2*i];
1268             int tagid=parameter->tagarray[2*i+1];
1269             if (tagid!=tagptr->flag)
1270               goto nextloop; /*We don't have this tag */
1271           }
1272         } else { //multiple tags
1273           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1274           for(i=0; i<parameter->numbertags; i++) {
1275             //slotid is parameter->tagarray[2*i];
1276             int tagid=parameter->tagarray[2*i+1];
1277             int j;
1278             for(j=0; j<ao->___cachedCode___; j++) {
1279               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1280                 goto foundtag;
1281             }
1282             goto nextloop;
1283 foundtag:
1284             ;
1285           }
1286         }
1287       }
1288
1289       /* Check flags */
1290       for(i=0; i<parameter->numberofterms; i++) {
1291         int andmask=parameter->intarray[i*2];
1292         int checkmask=parameter->intarray[i*2+1];
1293         if ((ptr->flag&andmask)==checkmask) {
1294 #ifdef RAWDEBUG
1295           raw_test_pass(0xcc000000 + andmask);
1296           raw_test_pass_reg((int)ptr);
1297           raw_test_pass(0xcc000000 + ptr->flag);
1298           raw_test_pass(0xcc000000 + checkmask);
1299 #endif
1300           enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1301           prevptr=parameter;
1302           break;
1303         }
1304       }
1305 nextloop:
1306       ;
1307     }
1308   }
1309 }
1310
1311 #ifdef RAW
1312 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1313   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1314
1315   {
1316     struct QueueItem *tmpptr;
1317     struct parameterwrapper * parameter=NULL;
1318     int j;
1319     int i;
1320     struct parameterwrapper * prevptr=NULL;
1321     struct ___Object___ *tagptr=NULL;
1322     struct parameterwrapper ** queues = vqueues;
1323     int length = vlength;
1324 #ifdef RAW
1325     if(corenum > NUMCORES - 1) {
1326       return;
1327     }
1328 #endif
1329     if(queues == NULL) {
1330 #ifdef THREADSIMULATE
1331       int numofcore = pthread_getspecific(key);
1332       queues = objectqueues[numofcore][ptr->type];
1333       length = numqueues[numofcore][ptr->type];
1334 #else
1335       queues = objectqueues[corenum][ptr->type];
1336       length = numqueues[corenum][ptr->type];
1337 #endif
1338     }
1339 #ifdef RAWDEBUG
1340     raw_test_pass(0xeaa1);
1341     raw_test_pass_reg(queues);
1342     raw_test_pass_reg(length);
1343 #endif
1344     tagptr=ptr->___tags___;
1345
1346     /* Outer loop iterates through all parameter queues an object of
1347        this type could be in.  */
1348     for(j = 0; j < length; ++j) {
1349       parameter = queues[j];
1350       /* Check tags */
1351       if (parameter->numbertags>0) {
1352 #ifdef RAWDEBUG
1353         raw_test_pass(0xeaa2);
1354         raw_test_pass_reg(tagptr);
1355 #endif
1356         if (tagptr==NULL)
1357           goto nextloop; //that means the object has no tag but that param needs tag
1358         else if(tagptr->type==TAGTYPE) { //one tag
1359           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1360 #ifdef RAWDEBUG
1361           raw_test_pass(0xeaa3);
1362 #endif
1363           for(i=0; i<parameter->numbertags; i++) {
1364             //slotid is parameter->tagarray[2*i];
1365             int tagid=parameter->tagarray[2*i+1];
1366             if (tagid!=tagptr->flag) {
1367 #ifdef RAWDEBUG
1368               raw_test_pass(0xeaa4);
1369 #endif
1370               goto nextloop; /*We don't have this tag */
1371             }
1372           }
1373         } else { //multiple tags
1374           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1375 #ifdef RAWDEBUG
1376           raw_test_pass(0xeaa5);
1377 #endif
1378           for(i=0; i<parameter->numbertags; i++) {
1379             //slotid is parameter->tagarray[2*i];
1380             int tagid=parameter->tagarray[2*i+1];
1381             int j;
1382             for(j=0; j<ao->___cachedCode___; j++) {
1383               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1384                 goto foundtag;
1385               }
1386             }
1387 #ifdef RAWDEBUG
1388             raw_test_pass(0xeaa6);
1389 #endif
1390             goto nextloop;
1391 foundtag:
1392             ;
1393           }
1394         }
1395       }
1396
1397       /* Check flags */
1398       for(i=0; i<parameter->numberofterms; i++) {
1399         int andmask=parameter->intarray[i*2];
1400         int checkmask=parameter->intarray[i*2+1];
1401 #ifdef RAWDEBUG
1402         raw_test_pass(0xeaa7);
1403         raw_test_pass(0xcc000000 + andmask);
1404         raw_test_pass_reg(ptr);
1405         raw_test_pass(0xcc000000 + ptr->flag);
1406         raw_test_pass(0xcc000000 + checkmask);
1407 #endif
1408         if ((ptr->flag&andmask)==checkmask) {
1409 #ifdef RAWDEBUG
1410           raw_test_pass(0xeaa8);
1411 #endif
1412           enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1413           prevptr=parameter;
1414           break;
1415         }
1416       }
1417 nextloop:
1418       ;
1419     }
1420   }
1421 }
1422
1423 // helper function to compute the coordinates of a core from the core number
1424 void calCoords(int core_num, int* coordY, int* coordX) {
1425   *coordX = core_num % 4;
1426   *coordY = core_num / 4;
1427 }
1428 #endif
1429
1430 /* Message format for RAW version:
1431  *      type + Msgbody
1432  * type: 0 -- transfer object
1433  *       1 -- transfer stall msg
1434  *       2 -- lock request
1435  *       3 -- lock grount
1436  *       4 -- lock deny
1437  *       5 -- lock release
1438  *       6 -- transfer profile output msg
1439  *       7 -- transfer profile ouput finish msg
1440  *
1441  * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1442  * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1443  * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
1444  *          3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
1445  *          lock type: 0 -- read; 1 -- write
1446  * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
1447  *             7 + corenum (size is always 2 * sizeof(int))
1448  */
1449
1450 // transfer an object to targetcore
1451 // format: object
1452 void transferObject(struct transObjInfo * transObj) {
1453   void * obj = transObj->objptr;
1454   int type=((int *)obj)[0];
1455   int size=classsize[type];
1456   int targetcore = transObj->targetcore;
1457   //assert(type < NUMCLASSES); // can only transfer normal object
1458
1459 #ifdef RAW
1460   unsigned msgHdr;
1461   int self_y, self_x, target_y, target_x;
1462   //int isshared = 0;
1463   // for 32 bit machine, the size of fixed part is always 3 words
1464   //int msgsize = sizeof(int) * 2 + sizeof(void *);
1465   int msgsize = 3 + transObj->length * 2;
1466   int i = 0;
1467
1468   struct ___Object___ * newobj = (struct ___Object___ *)obj;
1469   /*if(0 == newobj->isolate) {
1470           isshared = 1;
1471      }*/
1472
1473   calCoords(corenum, &self_y, &self_x);
1474   calCoords(targetcore, &target_y, &target_x);
1475   // Build the message header
1476   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
1477                              self_y, self_x,
1478                              target_y, target_x);
1479   // start sending msg, set sand msg flag
1480   isMsgSending = true;
1481   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
1482 #ifdef RAWDEBUG
1483   raw_test_pass(0xbbbb);
1484   raw_test_pass(0xb000 + targetcore);       // targetcore
1485 #endif
1486   gdn_send(0);
1487 #ifdef RAWDEBUG
1488   raw_test_pass(0);
1489 #endif
1490   gdn_send(msgsize);
1491 #ifdef RAWDEBUG
1492   raw_test_pass_reg(msgsize);
1493 #endif
1494   gdn_send(obj);
1495 #ifdef RAWDEBUG
1496   raw_test_pass_reg(obj);
1497 #endif
1498   for(i = 0; i < transObj->length; ++i) {
1499     int taskindex = transObj->queues[2*i];
1500     int paramindex = transObj->queues[2*i+1];
1501     gdn_send(taskindex);
1502 #ifdef RAWDEBUG
1503     raw_test_pass_reg(taskindex);
1504 #endif
1505     gdn_send(paramindex);
1506 #ifdef RAWDEBUG
1507     raw_test_pass_reg(paramindex);
1508 #endif
1509   }
1510 #ifdef RAWDEBUG
1511   raw_test_pass(0xffff);
1512 #endif
1513   ++(self_numsendobjs);
1514   // end of sending this msg, set sand msg flag false
1515   isMsgSending = false;
1516   // check if there are pending msgs
1517   while(isMsgHanging) {
1518     // get the msg from outmsgdata[]
1519     // length + target + msg
1520     outmsgleft = outmsgdata[outmsgindex++];
1521     targetcore = outmsgdata[outmsgindex++];
1522     calCoords(targetcore, &target_y, &target_x);
1523     // Build the message header
1524     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
1525                                self_y, self_x,
1526                                target_y, target_x);
1527     isMsgSending = true;
1528     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
1529 #ifdef RAWDEBUG
1530     raw_test_pass(0xbbbb);
1531     raw_test_pass(0xb000 + targetcore);             // targetcore
1532 #endif
1533     while(outmsgleft-- > 0) {
1534       gdn_send(outmsgdata[outmsgindex++]);
1535 #ifdef RAWDEBUG
1536       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1537 #endif
1538     }
1539 #ifdef RAWDEBUG
1540     raw_test_pass(0xffff);
1541 #endif
1542     isMsgSending = false;
1543 #ifdef INTERRUPT
1544     raw_user_interrupts_off();
1545 #endif
1546     // check if there are still msg hanging
1547     if(outmsgindex == outmsglast) {
1548       // no more msgs
1549       outmsgindex = outmsglast = 0;
1550       isMsgHanging = false;
1551     }
1552 #ifdef INTERRUPT
1553     raw_user_interrupts_on();
1554 #endif
1555   }
1556 #elif defined THREADSIMULATE
1557   int numofcore = pthread_getspecific(key);
1558
1559   // use POSIX message queue to transfer objects between cores
1560   mqd_t mqdnum;
1561   char corenumstr[3];
1562   int sourcelen = 0;
1563   if(targetcore < 10) {
1564     corenumstr[0] = targetcore + '0';
1565     corenumstr[1] = '\0';
1566     sourcelen = 1;
1567   } else if(targetcore < 100) {
1568     corenumstr[1] = targetcore % 10 + '0';
1569     corenumstr[0] = (targetcore / 10) + '0';
1570     corenumstr[2] = '\0';
1571     sourcelen = 2;
1572   } else {
1573     printf("Error: targetcore >= 100\n");
1574     fflush(stdout);
1575     exit(-1);
1576   }
1577   char * pathhead = "/msgqueue_";
1578   int targetlen = strlen(pathhead);
1579   char path[targetlen + sourcelen + 1];
1580   strcpy(path, pathhead);
1581   strncat(path, corenumstr, sourcelen);
1582   int oflags = O_WRONLY|O_NONBLOCK;
1583   int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1584   mqdnum = mq_open(path, oflags, omodes, NULL);
1585   if(mqdnum==-1) {
1586     printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1587     fflush(stdout);
1588     exit(-1);
1589   }
1590   /*struct ___Object___ * newobj = (struct ___Object___ *)obj;
1591      if(0 == newobj->isolate) {
1592           newobj = RUNMALLOC(size);
1593           memcpy(newobj, obj, size);
1594           newobj->original=obj;
1595      }*/
1596   struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1597   memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1598   int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1599   memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1600   tmptransObj->queues = tmpqueue;
1601   struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1602   newobj->type = ((struct ___Object___ *)obj)->type;
1603   newobj->original = (struct ___Object___ *)tmptransObj;
1604   int ret;
1605   do {
1606     ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0);             // send the object into the queue
1607     if(ret != 0) {
1608       printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1609     }
1610   } while(ret!=0);
1611   RUNFREE(newobj);
1612   if(numofcore == STARTUPCORE) {
1613     ++numsendobjs[numofcore];
1614   } else {
1615     ++(thread_data_array[numofcore].numsendobjs);
1616   }
1617   printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1618 #endif
1619 }
1620
1621 // send terminate message to targetcore
1622 // format: -1
1623 bool transStallMsg(int targetcore) {
1624 #ifdef RAW
1625   unsigned msgHdr;
1626   int self_y, self_x, target_y, target_x;
1627   // for 32 bit machine, the size is always 4 words
1628   //int msgsize = sizeof(int) * 4;
1629   int msgsize = 4;
1630
1631   calCoords(corenum, &self_y, &self_x);
1632   calCoords(targetcore, &target_y, &target_x);
1633   // Build the message header
1634   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
1635                              self_y, self_x,
1636                              target_y, target_x);
1637   // start sending msgs, set msg sending flag
1638   isMsgSending = true;
1639   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
1640 #ifdef RAWDEBUG
1641   raw_test_pass(0xbbbb);
1642   raw_test_pass(0xb000 + targetcore);       // targetcore
1643 #endif
1644   gdn_send(1);
1645 #ifdef RAWDEBUG
1646   raw_test_pass(1);
1647 #endif
1648   gdn_send(corenum);
1649 #ifdef RAWDEBUG
1650   raw_test_pass_reg(corenum);
1651 #endif
1652   gdn_send(self_numsendobjs);
1653 #ifdef RAWDEBUG
1654   raw_test_pass_reg(self_numsendobjs);
1655 #endif
1656   gdn_send(self_numreceiveobjs);
1657 #ifdef RAWDEBUG
1658   raw_test_pass_reg(self_numreceiveobjs);
1659   raw_test_pass(0xffff);
1660 #endif
1661   // end of sending this msg, set sand msg flag false
1662   isMsgSending = false;
1663   // check if there are pending msgs
1664   while(isMsgHanging) {
1665     // get the msg from outmsgdata[]
1666     // length + target + msg
1667     outmsgleft = outmsgdata[outmsgindex++];
1668     targetcore = outmsgdata[outmsgindex++];
1669     calCoords(targetcore, &target_y, &target_x);
1670     // Build the message header
1671     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
1672                                self_y, self_x,
1673                                target_y, target_x);
1674     isMsgSending = true;
1675     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
1676 #ifdef RAWDEBUG
1677     raw_test_pass(0xbbbb);
1678     raw_test_pass(0xb000 + targetcore);             // targetcore
1679 #endif
1680     while(outmsgleft-- > 0) {
1681       gdn_send(outmsgdata[outmsgindex++]);
1682 #ifdef RAWDEBUG
1683       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1684 #endif
1685     }
1686 #ifdef RAWDEBUG
1687     raw_test_pass(0xffff);
1688 #endif
1689     isMsgSending = false;
1690 #ifdef INTERRUPT
1691     raw_user_interrupts_off();
1692 #endif
1693     // check if there are still msg hanging
1694     if(outmsgindex == outmsglast) {
1695       // no more msgs
1696       outmsgindex = outmsglast = 0;
1697       isMsgHanging = false;
1698     }
1699 #ifdef INTERRUPT
1700     raw_user_interrupts_on();
1701 #endif
1702   }
1703   return true;
1704 #elif defined THREADSIMULATE
1705   struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1706   // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1707   newobj->type = -1;
1708   int numofcore = pthread_getspecific(key);
1709   newobj->flag = numofcore;
1710   newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1711   newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1712
1713   // use POSIX message queue to send stall msg to startup core
1714   assert(targetcore == STARTUPCORE);
1715   mqd_t mqdnum;
1716   char corenumstr[3];
1717   int sourcelen = 0;
1718   if(targetcore < 10) {
1719     corenumstr[0] = targetcore + '0';
1720     corenumstr[1] = '\0';
1721     sourcelen = 1;
1722   } else if(targetcore < 100) {
1723     corenumstr[1] = targetcore % 10 + '0';
1724     corenumstr[0] = (targetcore / 10) + '0';
1725     corenumstr[2] = '\0';
1726     sourcelen = 2;
1727   } else {
1728     printf("Error: targetcore >= 100\n");
1729     fflush(stdout);
1730     exit(-1);
1731   }
1732   char * pathhead = "/msgqueue_";
1733   int targetlen = strlen(pathhead);
1734   char path[targetlen + sourcelen + 1];
1735   strcpy(path, pathhead);
1736   strncat(path, corenumstr, sourcelen);
1737   int oflags = O_WRONLY|O_NONBLOCK;
1738   int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1739   mqdnum = mq_open(path, oflags, omodes, NULL);
1740   if(mqdnum==-1) {
1741     printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1742     fflush(stdout);
1743     exit(-1);
1744   }
1745   int ret;
1746   ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0);       // send the object into the queue
1747   if(ret != 0) {
1748     printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1749     RUNFREE(newobj);
1750     return false;
1751   } else {
1752     printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1753     printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1754     RUNFREE(newobj);
1755     return true;
1756   }
1757 #endif
1758 }
1759
1760 #ifdef RAWPROFILE
1761 // send profile request message to targetcore
1762 // format: 6
1763 bool transProfileRequestMsg(int targetcore) {
1764   unsigned msgHdr;
1765   int self_y, self_x, target_y, target_x;
1766   // for 32 bit machine, the size is always 4 words
1767   //int msgsize = sizeof(int) * 4;
1768   int msgsize = 2;
1769
1770   calCoords(corenum, &self_y, &self_x);
1771   calCoords(targetcore, &target_y, &target_x);
1772   // Build the message header
1773   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
1774                              self_y, self_x,
1775                              target_y, target_x);
1776   // start sending msgs, set msg sending flag
1777   isMsgSending = true;
1778   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
1779 #ifdef RAWDEBUG
1780   raw_test_pass(0xbbbb);
1781   raw_test_pass(0xb000 + targetcore);       // targetcore
1782 #endif
1783   gdn_send(6);
1784 #ifdef RAWDEBUG
1785   raw_test_pass(6);
1786 #endif
1787   gdn_send(totalexetime);
1788 #ifdef RAWDEBUG
1789   raw_test_pass_reg(totalexetime);
1790   raw_test_pass(0xffff);
1791 #endif
1792   // end of sending this msg, set sand msg flag false
1793   isMsgSending = false;
1794   // check if there are pending msgs
1795   while(isMsgHanging) {
1796     // get the msg from outmsgdata[]
1797     // length + target + msg
1798     outmsgleft = outmsgdata[outmsgindex++];
1799     targetcore = outmsgdata[outmsgindex++];
1800     calCoords(targetcore, &target_y, &target_x);
1801     // Build the message header
1802     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
1803                                self_y, self_x,
1804                                target_y, target_x);
1805     isMsgSending = true;
1806     gdn_send(msgHdr);
1807 #ifdef RAWDEBUG
1808     raw_test_pass(0xbbbb);
1809     raw_test_pass(0xb000 + targetcore);             // targetcore
1810 #endif
1811     while(outmsgleft-- > 0) {
1812       gdn_send(outmsgdata[outmsgindex++]);
1813 #ifdef RAWDEBUG
1814       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
1815 #endif
1816     }
1817 #ifdef RAWDEBUG
1818     raw_test_pass(0xffff);
1819 #endif
1820     isMsgSending = false;
1821 #ifdef INTERRUPT
1822     raw_user_interrupts_off();
1823 #endif
1824     // check if there are still msg hanging
1825     if(outmsgindex == outmsglast) {
1826       // no more msgs
1827       outmsgindex = outmsglast = 0;
1828       isMsgHanging = false;
1829     }
1830 #ifdef INTERRUPT
1831     raw_user_interrupts_on();
1832 #endif
1833   }
1834   return true;
1835 }
1836
1837 // output the profiling data
1838 void outputProfileData() {
1839   FILE * fp;
1840   char fn[50];
1841   int self_y, self_x;
1842   char c_y, c_x;
1843   int i;
1844   int totaltasktime = 0;
1845   int preprocessingtime = 0;
1846   int objqueuecheckingtime = 0;
1847   int postprocessingtime = 0;
1848   //int interruptiontime = 0;
1849   int other = 0;
1850   int averagetasktime = 0;
1851   int tasknum = 0;
1852
1853   for(i = 0; i < 50; i++) {
1854     fn[i] = 0;
1855   }
1856
1857   calCoords(corenum, &self_y, &self_x);
1858   c_y = (char)self_y + '0';
1859   c_x = (char)self_x + '0';
1860   strcat(fn, "profile_");
1861   strcat(fn, &c_x);
1862   strcat(fn, "_");
1863   strcat(fn, &c_y);
1864   strcat(fn, ".rst");
1865
1866   if((fp = fopen(fn, "w+")) == NULL) {
1867     fprintf(stderr, "fopen error\n");
1868     return -1;
1869   }
1870
1871   fprintf(fp, "Task Name, Start Time, End Time, Duration\n");
1872   // output task related info
1873   for(i = 0; i < taskInfoIndex; i++) {
1874     TaskInfo* tmpTInfo = taskInfoArray[i];
1875     int duration = tmpTInfo->endTime - tmpTInfo->startTime;
1876     fprintf(fp, "%s, %d, %d, %d\n", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration);
1877     if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
1878       preprocessingtime += duration;
1879     } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
1880       postprocessingtime += duration;
1881     } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
1882       objqueuecheckingtime += duration;
1883     } else {
1884       totaltasktime += duration;
1885       averagetasktime += duration;
1886       tasknum++;
1887     }
1888   }
1889
1890   if(taskInfoOverflow) {
1891     fprintf(stderr, "Caution: task info overflow!\n");
1892   }
1893
1894   other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
1895   averagetasktime /= tasknum;
1896
1897   fprintf(fp, "\nTotal time: %d\n", totalexetime);
1898   fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
1899   fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
1900   fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
1901   fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
1902   fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
1903
1904   fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
1905
1906   fclose(fp);
1907
1908   /*
1909      int i = 0;
1910      int j = 0;
1911
1912      raw_test_pass(0xdddd);
1913      // output task related info
1914      for(i= 0; i < taskInfoIndex; i++) {
1915           TaskInfo* tmpTInfo = taskInfoArray[i];
1916           char* tmpName = tmpTInfo->taskName;
1917           int nameLen = strlen(tmpName);
1918           raw_test_pass(0xddda);
1919           for(j = 0; j < nameLen; j++) {
1920                   raw_test_pass_reg(tmpName[j]);
1921           }
1922           raw_test_pass(0xdddb);
1923           raw_test_pass_reg(tmpTInfo->startTime);
1924           raw_test_pass_reg(tmpTInfo->endTime);
1925           raw_test_pass(0xdddc);
1926      }
1927
1928      if(taskInfoOverflow) {
1929           raw_test_pass(0xefee);
1930      }
1931
1932      // output interrupt related info
1933      for(i = 0; i < interruptInfoIndex; i++) {
1934           InterruptInfo* tmpIInfo = interruptInfoArray[i];
1935           raw_test_pass(0xddde);
1936           raw_test_pass_reg(tmpIInfo->startTime);
1937           raw_test_pass_reg(tmpIInfo->endTime);
1938           raw_test_pass(0xdddf);
1939      }
1940
1941      if(interruptInfoOverflow) {
1942           raw_test_pass(0xefef);
1943      }
1944
1945      raw_test_pass(0xeeee);
1946    */
1947 }
1948 #endif
1949
1950 // receive object transferred from other cores
1951 // or the terminate message from other cores
1952 // NOTICE: following format is for threadsimulate version only
1953 //         RAW version please see previous description
1954 // format: type + object
1955 // type: -1--stall msg
1956 //      !-1--object
1957 // return value: 0--received an object
1958 //               1--received nothing
1959 //               2--received a Stall Msg
1960 //               3--received a lock Msg
1961 //               RAW version: -1 -- received nothing
1962 //                            otherwise -- received msg type
1963 int receiveObject() {
1964 #ifdef RAW
1965   bool deny = false;
1966   unsigned msgHdr;
1967   int self_y, self_x, target_y, target_x;
1968   int targetcore = 0;
1969   if(gdn_input_avail() == 0) {
1970 #ifdef RAWDEBUG
1971     if(corenum < NUMCORES) {
1972       raw_test_pass(0xd001);
1973     }
1974 #endif
1975     return -1;
1976   }
1977 #ifdef RAWPROFILE
1978   if(isInterrupt && (!interruptInfoOverflow)) {
1979     // raw_test_pass(0xffff);
1980     interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
1981     interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
1982     interruptInfoArray[interruptInfoIndex]->endTime = -1;
1983   }
1984 #endif
1985 msg:
1986 #ifdef RAWDEBUG
1987   raw_test_pass(0xcccc);
1988 #endif
1989   while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
1990     msgdata[msgdataindex] = gdn_receive();
1991     if(msgdataindex == 0) {
1992       if(msgdata[0] == 7) {
1993         msglength = 2;
1994       } else if(msgdata[0] == 6) {
1995         msglength = 2;
1996       } else if(msgdata[0] > 2) {
1997         msglength = 3;
1998       } else if(msgdata[0] > 0) {
1999         msglength = 4;
2000       }
2001     } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
2002       msglength = msgdata[msgdataindex];
2003     }
2004 #ifdef RAWDEBUG
2005     raw_test_pass_reg(msgdata[msgdataindex]);
2006 #endif
2007     msgdataindex++;
2008
2009     /*if(msgdataindex == 0) {
2010             // type
2011             msgtype = gdn_receive();
2012             if(msgtype > 2) {
2013                     msglength = 3;
2014             } else {
2015                     msglength = 4;
2016             }
2017             if(msgtype != 0) {
2018                     msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
2019                     msgdata[msgdataindex] = msgtype;
2020             }
2021      #ifdef RAWDEBUG
2022             raw_test_pass_reg(msgtype);
2023      #endif
2024        } else if((msgdataindex == 1) && (msgtype == 0)) {
2025             // object transfer msg
2026             msglength = gdn_receive();
2027             msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
2028             msgdata[0] = msgtype;
2029             msgdata[msgdataindex] = msglength;
2030      #ifdef RAWDEBUG
2031             raw_test_pass_reg(msgdata[msgdataindex]);
2032      #endif
2033        } else {
2034             msgdata[msgdataindex] = gdn_receive();
2035      #ifdef RAWDEBUG
2036             raw_test_pass_reg(msgdata[msgdataindex]);
2037      #endif
2038        }
2039        msgdataindex++;*/
2040   }
2041 #ifdef RAWDEBUG
2042   raw_test_pass(0xffff);
2043 #endif
2044   if(msgdataindex == msglength) {
2045     // received a whole msg
2046     int type, data1, data2;             // will receive at least 3 words including type
2047     type = msgdata[0];
2048     data1 = msgdata[1];
2049     data2 = msgdata[2];
2050     switch(type) {
2051     case 0: {
2052       // receive a object transfer msg
2053       struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
2054       int k = 0;
2055       if(corenum > NUMCORES - 1) {
2056         raw_test_done(0xa00a);
2057       }
2058       // store the object and its corresponding queue info, enqueue it later
2059       transObj->objptr = (void *)data2;                                           // data1 is now size of the msg
2060       transObj->length = (msglength - 3) / 2;
2061       transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
2062       for(k = 0; k < transObj->length; ++k) {
2063         transObj->queues[2*k] = msgdata[3+2*k];
2064 #ifdef RAWDEBUG
2065         raw_test_pass_reg(transObj->queues[2*k]);
2066 #endif
2067         transObj->queues[2*k+1] = msgdata[3+2*k+1];
2068 #ifdef RAWDEBUG
2069         raw_test_pass_reg(transObj->queues[2*k+1]);
2070 #endif
2071       }
2072       // check if there is an existing duplicate item
2073       {
2074         struct QueueItem * qitem = getTail(&objqueue);
2075         struct QueueItem * prev = NULL;
2076         while(qitem != NULL) {
2077           struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
2078           if(tmpinfo->objptr == transObj->objptr) {
2079             // the same object, remove outdate one
2080             removeItem(&objqueue, qitem);
2081           } else {
2082             prev = qitem;
2083           }
2084           if(prev == NULL) {
2085             qitem = getTail(&objqueue);
2086           } else {
2087             qitem = getNext(prev);
2088           }
2089         }
2090         //memcpy(transObj->queues, msgdata[3], sizeof(int)*(msglength - 3));
2091         addNewItem_I(&objqueue, (void *)transObj);
2092       }
2093       ++(self_numreceiveobjs);
2094 #ifdef RAWDEBUG
2095       raw_test_pass(0xe881);
2096 #endif
2097       /*
2098          addNewItem_I(&objqueue, (void *)data2);
2099        ++(self_numreceiveobjs);
2100        #ifdef RAWDEBUG
2101          raw_test_pass(0xe881);
2102        #endif
2103        */
2104       break;
2105     }
2106
2107     case 1: {
2108       // receive a stall msg
2109       if(corenum != STARTUPCORE) {
2110         // non startup core can not receive stall msg
2111         // return -1
2112         raw_test_done(0xa001);
2113       }
2114       if(data1 < NUMCORES) {
2115 #ifdef RAWDEBUG
2116         raw_test_pass(0xe882);
2117 #endif
2118         corestatus[data1] = 0;
2119         numsendobjs[data1] = data2;
2120         numreceiveobjs[data1] = msgdata[3];
2121       }
2122       break;
2123     }
2124
2125     case 2: {
2126       // receive lock request msg
2127       // for 32 bit machine, the size is always 3 words
2128       //int msgsize = sizeof(int) * 3;
2129       int msgsize = 3;
2130       // lock request msg, handle it right now
2131       // check to see if there is a lock exist in locktbl for the required obj
2132       int data3 = msgdata[3];
2133       deny = false;
2134       if(!RuntimeHashcontainskey(locktbl, data2)) {
2135         // no locks for this object
2136         // first time to operate on this shared object
2137         // create a lock for it
2138         // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2139 #ifdef RAWDEBUG
2140         raw_test_pass(0xe883);
2141 #endif
2142         if(data1 == 0) {
2143           RuntimeHashadd_I(locktbl, data2, 1);
2144         } else {
2145           RuntimeHashadd_I(locktbl, data2, -1);
2146         }
2147       } else {
2148         int rwlock_obj = 0;
2149 #ifdef RAWDEBUG
2150         raw_test_pass(0xe884);
2151 #endif
2152         RuntimeHashget(locktbl, data2, &rwlock_obj);
2153 #ifdef RAWDEBUG
2154         raw_test_pass_reg(rwlock_obj);
2155 #endif
2156         if(0 == rwlock_obj) {
2157           if(data1 == 0) {
2158             rwlock_obj = 1;
2159           } else {
2160             rwlock_obj = -1;
2161           }
2162           RuntimeHashremovekey(locktbl, data2);
2163           RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2164         } else if((rwlock_obj > 0) && (data1 == 0)) {
2165           // read lock request and there are only read locks
2166           rwlock_obj++;
2167           RuntimeHashremovekey(locktbl, data2);
2168           RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2169         } else {
2170           deny = true;
2171         }
2172 #ifdef RAWDEBUG
2173         raw_test_pass_reg(rwlock_obj);
2174 #endif
2175       }
2176       targetcore = data3;
2177       // check if there is still some msg on sending
2178       if(isMsgSending) {
2179 #ifdef RAWDEBUG
2180         raw_test_pass(0xe885);
2181 #endif
2182         isMsgHanging = true;
2183         // cache the msg in outmsgdata and send it later
2184         // msglength + target core + msg
2185         outmsgdata[outmsglast++] = msgsize;
2186         outmsgdata[outmsglast++] = targetcore;
2187         if(deny == true) {
2188           outmsgdata[outmsglast++] = 4;
2189         } else {
2190           outmsgdata[outmsglast++] = 3;
2191         }
2192         outmsgdata[outmsglast++] = data1;
2193         outmsgdata[outmsglast++] = data2;
2194       } else {
2195 #ifdef RAWDEBUG
2196         raw_test_pass(0xe886);
2197 #endif
2198         // no msg on sending, send it out
2199         calCoords(corenum, &self_y, &self_x);
2200         calCoords(targetcore, &target_y, &target_x);
2201         // Build the message header
2202         msgHdr = construct_dyn_hdr(0, msgsize, 0,                                                               // msgsize word sent.
2203                                    self_y, self_x,
2204                                    target_y, target_x);
2205         gdn_send(msgHdr);                                                               // Send the message header to EAST to handle fab(n - 1).
2206 #ifdef RAWDEBUG
2207         raw_test_pass(0xbbbb);
2208         raw_test_pass(0xb000 + targetcore);                                                 // targetcore
2209 #endif
2210         if(deny == true) {
2211           // deny the lock request
2212           gdn_send(4);                                                       // lock request
2213 #ifdef RAWDEBUG
2214           raw_test_pass(4);
2215 #endif
2216         } else {
2217           // grount the lock request
2218           gdn_send(3);                                                       // lock request
2219 #ifdef RAWDEBUG
2220           raw_test_pass(3);
2221 #endif
2222         }
2223         gdn_send(data1);                                                 // lock type
2224 #ifdef RAWDEBUG
2225         raw_test_pass_reg(data1);
2226 #endif
2227         gdn_send(data2);                                                 // lock target
2228 #ifdef RAWDEBUG
2229         raw_test_pass_reg(data2);
2230         raw_test_pass(0xffff);
2231 #endif
2232       }
2233       break;
2234     }
2235
2236     case 3: {
2237       // receive lock grount msg
2238       if(corenum > NUMCORES - 1) {
2239         raw_test_done(0xa00b);
2240       }
2241       if(lockobj == data2) {
2242         lockresult = 1;
2243         lockflag = true;
2244 #ifndef INTERRUPT
2245         reside = false;
2246 #endif
2247       } else {
2248         // conflicts on lockresults
2249         raw_test_done(0xa002);
2250       }
2251       break;
2252     }
2253
2254     case 4: {
2255       // receive lock grount/deny msg
2256       if(corenum > NUMCORES - 1) {
2257         raw_test_done(0xa00c);
2258       }
2259       if(lockobj == data2) {
2260         lockresult = 0;
2261         lockflag = true;
2262 #ifndef INTERRUPT
2263         reside = false;
2264 #endif
2265       } else {
2266         // conflicts on lockresults
2267         raw_test_done(0xa003);
2268       }
2269       break;
2270     }
2271
2272     case 5: {
2273       // receive lock release msg
2274       if(!RuntimeHashcontainskey(locktbl, data2)) {
2275         // no locks for this object, something is wrong
2276         raw_test_done(0xa004);
2277       } else {
2278         int rwlock_obj = 0;
2279         RuntimeHashget(locktbl, data2, &rwlock_obj);
2280 #ifdef RAWDEBUG
2281         raw_test_pass(0xe887);
2282         raw_test_pass_reg(rwlock_obj);
2283 #endif
2284         if(data1 == 0) {
2285           rwlock_obj--;
2286         } else {
2287           rwlock_obj++;
2288         }
2289         RuntimeHashremovekey(locktbl, data2);
2290         RuntimeHashadd_I(locktbl, data2, rwlock_obj);
2291 #ifdef RAWDEBUG
2292         raw_test_pass_reg(rwlock_obj);
2293 #endif
2294       }
2295       break;
2296     }
2297
2298 #ifdef RAWPROFILE
2299     case 6: {
2300       // receive an output request msg
2301       if(corenum == STARTUPCORE) {
2302         // startup core can not receive profile output finish msg
2303         // return -1
2304         raw_test_done(0xa00a);
2305       }
2306       {
2307         int msgsize = 2;
2308         stall = true;
2309         totalexetime = data1;
2310         outputProfileData();
2311         /*if(data1 >= NUMCORES) {
2312                 raw_test_pass(0xee04);
2313            raw_test_pass_reg(taskInfoIndex);
2314            raw_test_pass_reg(taskInfoOverflow);
2315                 if(!taskInfoOverflow) {
2316                         taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
2317                         taskInfoIndex++;
2318                         if(taskInfoIndex == TASKINFOLENGTH) {
2319                                 taskInfoOverflow = true;
2320                         }
2321                 }
2322            }*/
2323         // no msg on sending, send it out
2324         targetcore = STARTUPCORE;
2325         calCoords(corenum, &self_y, &self_x);
2326         calCoords(targetcore, &target_y, &target_x);
2327         // Build the message header
2328         msgHdr = construct_dyn_hdr(0, msgsize, 0,                                                               // msgsize word sent.
2329                                    self_y, self_x,
2330                                    target_y, target_x);
2331         gdn_send(msgHdr);
2332 #ifdef RAWDEBUG
2333         raw_test_pass(0xbbbb);
2334         raw_test_pass(0xb000 + targetcore);                                                 // targetcore
2335 #endif
2336         gdn_send(7);
2337 #ifdef RAWDEBUG
2338         raw_test_pass(7);
2339 #endif
2340         gdn_send(corenum);
2341 #ifdef RAWDEBUG
2342         raw_test_pass_reg(corenum);
2343         raw_test_pass(0xffff);
2344 #endif
2345       }
2346       break;
2347     }
2348
2349     case 7: {
2350       // receive a profile output finish msg
2351       if(corenum != STARTUPCORE) {
2352         // non startup core can not receive profile output finish msg
2353         // return -1
2354         raw_test_done(0xa00b);
2355       }
2356       profilestatus[data1] = 0;
2357       break;
2358     }
2359 #endif
2360
2361     default:
2362       break;
2363     }
2364     //RUNFREE(msgdata);
2365     //msgdata = NULL;
2366     for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
2367       msgdata[msgdataindex] = -1;
2368     }
2369     msgtype = -1;
2370     //msgdataindex = 0;
2371     msglength = 30;
2372 #ifdef RAWDEBUG
2373     raw_test_pass(0xe888);
2374 #endif
2375     if(gdn_input_avail() != 0) {
2376       goto msg;
2377     }
2378 #ifdef RAWPROFILE
2379     if(isInterrupt && (!interruptInfoOverflow)) {
2380       interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2381       interruptInfoIndex++;
2382       if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2383         interruptInfoOverflow = true;
2384       }
2385     }
2386 #endif
2387     return type;
2388   } else {
2389     // not a whole msg
2390 #ifdef RAWDEBUG
2391     raw_test_pass(0xe889);
2392 #endif
2393 #ifdef RAWPROFILE
2394     if(isInterrupt && (!interruptInfoOverflow)) {
2395       interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
2396       interruptInfoIndex++;
2397       if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2398         interruptInfoOverflow = true;
2399       }
2400     }
2401 #endif
2402     return -2;
2403   }
2404 #elif defined THREADSIMULATE
2405   int numofcore = pthread_getspecific(key);
2406   // use POSIX message queue to transfer object
2407   int msglen = 0;
2408   struct mq_attr mqattr;
2409   mq_getattr(mqd[numofcore], &mqattr);
2410   void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
2411   msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL);       // receive the object into the queue
2412   if(-1 == msglen) {
2413     // no msg
2414     free(msgptr);
2415     return 1;
2416   }
2417   //printf("msg: %s\n",msgptr);
2418   if(((int*)msgptr)[0] == -1) {
2419     // StallMsg
2420     struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2421     int index = tmpptr->flag;
2422     corestatus[index] = 0;
2423     numsendobjs[index] = tmpptr->___cachedHash___;
2424     numreceiveobjs[index] = tmpptr->___cachedCode___;
2425     printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
2426     free(msgptr);
2427     return 2;
2428   }       /*else if(((int*)msgptr)[0] == -2) {
2429                 // terminate msg
2430                 return 3;
2431              } */
2432   else {
2433     // an object
2434     if(numofcore == STARTUPCORE) {
2435       ++(numreceiveobjs[numofcore]);
2436     } else {
2437       ++(thread_data_array[numofcore].numreceiveobjs);
2438     }
2439     struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
2440     struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
2441     tmpptr = (struct ___Object___ *)(transObj->objptr);
2442     int type = tmpptr->type;
2443     int size=classsize[type];
2444     struct ___Object___ * newobj=RUNMALLOC(size);
2445     memcpy(newobj, tmpptr, size);
2446     if(0 == newobj->isolate) {
2447       newobj->original=tmpptr;
2448     }
2449     RUNFREE(msgptr);
2450     tmpptr = NULL;
2451     int k = 0;
2452     for(k = 0; k < transObj->length; ++k) {
2453       int taskindex = transObj->queues[2 * k];
2454       int paramindex = transObj->queues[2 * k + 1];
2455       struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
2456       enqueueObject(newobj, queues, 1);
2457     }
2458     RUNFREE(transObj->queues);
2459     RUNFREE(transObj);
2460     return 0;
2461   }
2462 #endif
2463 }
2464
2465 bool getreadlock(void * ptr) {
2466 #ifdef RAW
2467   unsigned msgHdr;
2468   int self_y, self_x, target_y, target_x;
2469   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
2470   // for 32 bit machine, the size is always 4 words
2471   //int msgsize = sizeof(int) * 4;
2472   int msgsize = 4;
2473   int tc = TOTALCORE;
2474 #ifdef INTERRUPT
2475   raw_user_interrupts_off();
2476 #endif
2477   targetcore = ((int)ptr >> 5) % tc;
2478 #ifdef INTERRUPT
2479   raw_user_interrupts_on();
2480 #endif
2481
2482   lockobj = (int)ptr;
2483   lockflag = false;
2484 #ifndef INTERRUPT
2485   reside = false;
2486 #endif
2487   lockresult = 0;
2488
2489   if(targetcore == corenum) {
2490     // reside on this core
2491     bool deny = false;
2492 #ifdef INTERRUPT
2493     raw_user_interrupts_off();
2494 #endif
2495     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2496       // no locks for this object
2497       // first time to operate on this shared object
2498       // create a lock for it
2499       // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2500       RuntimeHashadd_I(locktbl, (int)ptr, 1);
2501     } else {
2502       int rwlock_obj = 0;
2503       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2504       if(-1 != rwlock_obj) {
2505         rwlock_obj++;
2506         RuntimeHashremovekey(locktbl, (int)ptr);
2507         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2508       } else {
2509         deny = true;
2510       }
2511     }
2512 #ifdef INTERRUPT
2513     raw_user_interrupts_on();
2514 #endif
2515     if(lockobj == (int)ptr) {
2516       if(deny) {
2517         lockresult = 0;
2518       } else {
2519         lockresult = 1;
2520       }
2521       lockflag = true;
2522 #ifndef INTERRUPT
2523       reside = true;
2524 #endif
2525     } else {
2526       // conflicts on lockresults
2527       raw_test_done(0xa005);
2528     }
2529     return true;
2530   }
2531
2532   calCoords(corenum, &self_y, &self_x);
2533   calCoords(targetcore, &target_y, &target_x);
2534   // Build the message header
2535   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
2536                              self_y, self_x,
2537                              target_y, target_x);
2538   // start sending the msg, set send msg flag
2539   isMsgSending = true;
2540   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
2541 #ifdef RAWDEBUG
2542   raw_test_pass(0xbbbb);
2543   raw_test_pass(0xb000 + targetcore);       // targetcore
2544 #endif
2545   gdn_send(2);   // lock request
2546  #ifdef RAWDEBUG
2547   raw_test_pass(2);
2548 #endif
2549   gdn_send(0);       // read lock
2550 #ifdef RAWDEBUG
2551   raw_test_pass(0);
2552 #endif
2553   gdn_send(ptr);
2554 #ifdef RAWDEBUG
2555   raw_test_pass_reg(ptr);
2556 #endif
2557   gdn_send(corenum);
2558 #ifdef RAWDEBUG
2559   raw_test_pass_reg(corenum);
2560   raw_test_pass(0xffff);
2561 #endif
2562   // end of sending this msg, set sand msg flag false
2563   isMsgSending = false;
2564   // check if there are pending msgs
2565   while(isMsgHanging) {
2566     // get the msg from outmsgdata[]
2567     // length + target + msg
2568     outmsgleft = outmsgdata[outmsgindex++];
2569     targetcore = outmsgdata[outmsgindex++];
2570     calCoords(targetcore, &target_y, &target_x);
2571     // Build the message header
2572     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
2573                                self_y, self_x,
2574                                target_y, target_x);
2575     isMsgSending = true;
2576     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
2577 #ifdef RAWDEBUG
2578     raw_test_pass(0xbbbb);
2579     raw_test_pass(0xb000 + targetcore);             // targetcore
2580 #endif
2581     while(outmsgleft-- > 0) {
2582       gdn_send(outmsgdata[outmsgindex++]);
2583 #ifdef RAWDEBUG
2584       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2585 #endif
2586     }
2587 #ifdef RAWDEBUG
2588     raw_test_pass(0xffff);
2589 #endif
2590     isMsgSending = false;
2591 #ifdef INTERRUPT
2592     raw_user_interrupts_off();
2593 #endif
2594     // check if there are still msg hanging
2595     if(outmsgindex == outmsglast) {
2596       // no more msgs
2597       outmsgindex = outmsglast = 0;
2598       isMsgHanging = false;
2599     }
2600 #ifdef INTERRUPT
2601     raw_user_interrupts_on();
2602 #endif
2603   }
2604   return true;
2605 #elif defined THREADSIMULATE
2606   int numofcore = pthread_getspecific(key);
2607
2608   int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2609   printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2610   if(0 != rc) {
2611     return false;
2612   }
2613   if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2614     // no locks for this object
2615     // first time to operate on this shared object
2616     // create a lock for it
2617     rc = pthread_rwlock_unlock(&rwlock_tbl);
2618     printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2619     pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2620     memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2621     rc = pthread_rwlock_init(rwlock, NULL);
2622     printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2623     rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2624     printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2625     if(0 != rc) {
2626       RUNFREE(rwlock);
2627       return false;
2628     } else {
2629       if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2630         // check again
2631         RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2632       } else {
2633         RUNFREE(rwlock);
2634         RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2635       }
2636       rc = pthread_rwlock_unlock(&rwlock_tbl);
2637       printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2638     }
2639     rc = pthread_rwlock_tryrdlock(rwlock);
2640     printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2641     if(0 != rc) {
2642       return false;
2643     } else {
2644       return true;
2645     }
2646   } else {
2647     pthread_rwlock_t* rwlock_obj = NULL;
2648     RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2649     rc = pthread_rwlock_unlock(&rwlock_tbl);
2650     printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2651     int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
2652     printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2653     if(0 != rc_obj) {
2654       return false;
2655     } else {
2656       return true;
2657     }
2658   }
2659 #endif
2660 }
2661
2662 void releasereadlock(void * ptr) {
2663 #ifdef RAW
2664   unsigned msgHdr;
2665   int self_y, self_x, target_y, target_x;
2666   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
2667   // for 32 bit machine, the size is always 3 words
2668   //int msgsize = sizeof(int) * 3;
2669   int msgsize = 3;
2670   int tc = TOTALCORE;
2671 #ifdef INTERRUPT
2672   raw_user_interrupts_off();
2673 #endif
2674   targetcore = ((int)ptr >> 5) % tc;
2675 #ifdef INTERRUPT
2676   raw_user_interrupts_on();
2677 #endif
2678
2679   if(targetcore == corenum) {
2680 #ifdef INTERRUPT
2681     raw_user_interrupts_off();
2682 #endif
2683     // reside on this core
2684     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2685       // no locks for this object, something is wrong
2686       raw_test_done(0xa006);
2687     } else {
2688       int rwlock_obj = 0;
2689       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2690       rwlock_obj--;
2691       RuntimeHashremovekey(locktbl, (int)ptr);
2692       RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2693     }
2694 #ifdef INTERRUPT
2695     raw_user_interrupts_on();
2696 #endif
2697     return;
2698   }
2699
2700   calCoords(corenum, &self_y, &self_x);
2701   calCoords(targetcore, &target_y, &target_x);
2702   // Build the message header
2703   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
2704                              self_y, self_x,
2705                              target_y, target_x);
2706   // start sending the msg, set send msg flag
2707   isMsgSending = true;
2708   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
2709 #ifdef RAWDEBUG
2710   raw_test_pass(0xbbbb);
2711   raw_test_pass(0xb000 + targetcore);       // targetcore
2712 #endif
2713   gdn_send(5);   // lock release
2714 #ifdef RAWDEBUG
2715   raw_test_pass(5);
2716 #endif
2717   gdn_send(0);       // read lock
2718 #ifdef RAWDEBUG
2719   raw_test_pass(0);
2720 #endif
2721   gdn_send(ptr);
2722 #ifdef RAWDEBUG
2723   raw_test_pass_reg(ptr);
2724   raw_test_pass(0xffff);
2725 #endif
2726   // end of sending this msg, set sand msg flag false
2727   isMsgSending = false;
2728   // check if there are pending msgs
2729   while(isMsgHanging) {
2730     // get the msg from outmsgdata[]
2731     // length + target + msg
2732     outmsgleft = outmsgdata[outmsgindex++];
2733     targetcore = outmsgdata[outmsgindex++];
2734     calCoords(targetcore, &target_y, &target_x);
2735     // Build the message header
2736     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
2737                                self_y, self_x,
2738                                target_y, target_x);
2739     isMsgSending = true;
2740     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
2741 #ifdef RAWDEBUG
2742     raw_test_pass(0xbbbb);
2743     raw_test_pass(0xb000 + targetcore);             // targetcore
2744 #endif
2745     while(outmsgleft-- > 0) {
2746       gdn_send(outmsgdata[outmsgindex++]);
2747 #ifdef RAWDEBUG
2748       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
2749 #endif
2750     }
2751 #ifdef RAWDEBUG
2752     raw_test_pass(0xffff);
2753 #endif
2754     isMsgSending = false;
2755 #ifdef INTERRUPT
2756     raw_user_interrupts_off();
2757 #endif
2758     // check if there are still msg hanging
2759     if(outmsgindex == outmsglast) {
2760       // no more msgs
2761       outmsgindex = outmsglast = 0;
2762       isMsgHanging = false;
2763     }
2764 #ifdef INTERRUPT
2765     raw_user_interrupts_on();
2766 #endif
2767   }
2768 #elif defined THREADSIMULATE
2769   int numofcore = pthread_getspecific(key);
2770   int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2771   printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2772   if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2773     printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2774     exit(-1);
2775   }
2776   pthread_rwlock_t* rwlock_obj = NULL;
2777   RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2778   int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2779   printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2780   rc = pthread_rwlock_unlock(&rwlock_tbl);
2781   printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2782 #endif
2783 }
2784
2785 #ifdef RAW
2786 bool getreadlock_I(void * ptr) {
2787   unsigned msgHdr;
2788   int self_y, self_x, target_y, target_x;
2789   int targetcore = ((int)ptr >> 5) % TOTALCORE;
2790   // for 32 bit machine, the size is always 4 words
2791   //int msgsize = sizeof(int) * 4;
2792   int msgsize = 4;
2793
2794   lockobj = (int)ptr;
2795   lockflag = false;
2796 #ifndef INTERRUPT
2797   reside = false;
2798 #endif
2799   lockresult = 0;
2800
2801   if(targetcore == corenum) {
2802     // reside on this core
2803     bool deny = false;
2804     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2805       // no locks for this object
2806       // first time to operate on this shared object
2807       // create a lock for it
2808       // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2809       RuntimeHashadd_I(locktbl, (int)ptr, 1);
2810     } else {
2811       int rwlock_obj = 0;
2812       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2813       if(-1 != rwlock_obj) {
2814         rwlock_obj++;
2815         RuntimeHashremovekey(locktbl, (int)ptr);
2816         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2817       } else {
2818         deny = true;
2819       }
2820     }
2821     if(lockobj == (int)ptr) {
2822       if(deny) {
2823         lockresult = 0;
2824       } else {
2825         lockresult = 1;
2826       }
2827       lockflag = true;
2828 #ifndef INTERRUPT
2829       reside = true;
2830 #endif
2831     } else {
2832       // conflicts on lockresults
2833       raw_test_done(0xa005);
2834     }
2835     return true;
2836   }
2837
2838   calCoords(corenum, &self_y, &self_x);
2839   calCoords(targetcore, &target_y, &target_x);
2840   // Build the message header
2841   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
2842                              self_y, self_x,
2843                              target_y, target_x);
2844   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
2845 #ifdef RAWDEBUG
2846   raw_test_pass(0xbbbb);
2847   raw_test_pass(0xb000 + targetcore);       // targetcore
2848 #endif
2849   gdn_send(2);   // lock request
2850 #ifdef RAWDEBUG
2851   raw_test_pass(2);
2852 #endif
2853   gdn_send(0);       // read lock
2854 #ifdef RAWDEBUG
2855   raw_test_pass(0);
2856 #endif
2857   gdn_send(ptr);
2858 #ifdef RAWDEBUG
2859   raw_test_pass_reg(ptr);
2860 #endif
2861   gdn_send(corenum);
2862 #ifdef RAWDEBUG
2863   raw_test_pass_reg(corenum);
2864   raw_test_pass(0xffff);
2865 #endif
2866   return true;
2867 }
2868
2869 void releasereadlock_I(void * ptr) {
2870   unsigned msgHdr;
2871   int self_y, self_x, target_y, target_x;
2872   int targetcore = ((int)ptr >> 5) % TOTALCORE;
2873   // for 32 bit machine, the size is always 3 words
2874   //int msgsize = sizeof(int) * 3;
2875   int msgsize = 3;
2876
2877   if(targetcore == corenum) {
2878     // reside on this core
2879     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2880       // no locks for this object, something is wrong
2881       raw_test_done(0xa006);
2882     } else {
2883       int rwlock_obj = 0;
2884       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2885       rwlock_obj--;
2886       RuntimeHashremovekey(locktbl, (int)ptr);
2887       RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2888     }
2889     return;
2890   }
2891
2892   calCoords(corenum, &self_y, &self_x);
2893   calCoords(targetcore, &target_y, &target_x);
2894   // Build the message header
2895   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
2896                              self_y, self_x,
2897                              target_y, target_x);
2898   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
2899 #ifdef RAWDEBUG
2900   raw_test_pass(0xbbbb);
2901   raw_test_pass(0xb000 + targetcore);       // targetcore
2902 #endif
2903   gdn_send(5);   // lock release
2904 #ifdef RAWDEBUG
2905   raw_test_pass(5);
2906 #endif
2907   gdn_send(0);       // read lock
2908 #ifdef RAWDEBUG
2909   raw_test_pass(0);
2910 #endif
2911   gdn_send(ptr);
2912 #ifdef RAWDEBUG
2913   raw_test_pass_reg(ptr);
2914   raw_test_pass(0xffff);
2915 #endif
2916 }
2917 #endif
2918
2919 // not reentrant
2920 bool getwritelock(void * ptr) {
2921 #ifdef RAW
2922   unsigned msgHdr;
2923   int self_y, self_x, target_y, target_x;
2924   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
2925   // for 32 bit machine, the size is always 4 words
2926   //int msgsize = sizeof(int) * 4;
2927   int msgsize= 4;
2928   int tc = TOTALCORE;
2929 #ifdef INTERRUPT
2930   raw_user_interrupts_off();
2931 #endif
2932   targetcore = ((int)ptr >> 5) % tc;
2933 #ifdef INTERRUPT
2934   raw_user_interrupts_on();
2935 #endif
2936
2937 #ifdef RAWDEBUG
2938   raw_test_pass(0xe551);
2939   raw_test_pass_reg(ptr);
2940   raw_test_pass_reg(targetcore);
2941   raw_test_pass_reg(tc);
2942 #endif
2943
2944   lockobj = (int)ptr;
2945   lockflag = false;
2946 #ifndef INTERRUPT
2947   reside = false;
2948 #endif
2949   lockresult = 0;
2950
2951   if(targetcore == corenum) {
2952     // reside on this core
2953     bool deny = false;
2954 #ifdef INTERRUPT
2955     raw_user_interrupts_off();
2956 #endif
2957     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2958       // no locks for this object
2959       // first time to operate on this shared object
2960       // create a lock for it
2961       // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2962 #ifdef RAWDEBUG
2963       raw_test_pass(0xe552);
2964 #endif
2965       RuntimeHashadd_I(locktbl, (int)ptr, -1);
2966     } else {
2967       int rwlock_obj = 0;
2968       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2969 #ifdef RAWDEBUG
2970       raw_test_pass(0xe553);
2971       raw_test_pass_reg(rwlock_obj);
2972 #endif
2973       if(0 == rwlock_obj) {
2974         rwlock_obj = -1;
2975         RuntimeHashremovekey(locktbl, (int)ptr);
2976         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2977       } else {
2978         deny = true;
2979       }
2980     }
2981 #ifdef INTERRUPT
2982     raw_user_interrupts_on();
2983 #endif
2984 #ifdef RAWDEBUG
2985     raw_test_pass(0xe554);
2986     raw_test_pass_reg(lockresult);
2987 #endif
2988     if(lockobj == (int)ptr) {
2989       if(deny) {
2990         lockresult = 0;
2991 #ifdef RAWDEBUG
2992         raw_test_pass(0);
2993 #endif
2994       } else {
2995         lockresult = 1;
2996 #ifdef RAWDEBUG
2997         raw_test_pass(1);
2998 #endif
2999       }
3000       lockflag = true;
3001 #ifndef INTERRUPT
3002       reside = true;
3003 #endif
3004     } else {
3005       // conflicts on lockresults
3006       raw_test_done(0xa007);
3007     }
3008     return true;
3009   }
3010
3011 #ifdef RAWDEBUG
3012   raw_test_pass(0xe555);
3013 #endif
3014   calCoords(corenum, &self_y, &self_x);
3015   calCoords(targetcore, &target_y, &target_x);
3016   // Build the message header
3017   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
3018                              self_y, self_x,
3019                              target_y, target_x);
3020   // start sending the msg, set send msg flag
3021   isMsgSending = true;
3022   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
3023 #ifdef RAWDEBUG
3024   raw_test_pass(0xbbbb);
3025   raw_test_pass(0xb000 + targetcore);       // targetcore
3026 #endif
3027   gdn_send(2);   // lock request
3028 #ifdef RAWDEBUG
3029   raw_test_pass(2);
3030 #endif
3031   gdn_send(1);       // write lock
3032 #ifdef RAWDEBUG
3033   raw_test_pass(1);
3034 #endif
3035   gdn_send(ptr);
3036 #ifdef RAWDEBUG
3037   raw_test_pass_reg(ptr);
3038 #endif
3039   gdn_send(corenum);
3040 #ifdef RAWDEBUG
3041   raw_test_pass_reg(corenum);
3042   raw_test_pass(0xffff);
3043 #endif
3044   // end of sending this msg, set sand msg flag false
3045   isMsgSending = false;
3046   // check if there are pending msgs
3047   while(isMsgHanging) {
3048     // get the msg from outmsgdata[]
3049     // length + target + msg
3050     outmsgleft = outmsgdata[outmsgindex++];
3051     targetcore = outmsgdata[outmsgindex++];
3052     calCoords(targetcore, &target_y, &target_x);
3053     // Build the message header
3054     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
3055                                self_y, self_x,
3056                                target_y, target_x);
3057     isMsgSending = true;
3058     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
3059 #ifdef RAWDEBUG
3060     raw_test_pass(0xbbbb);
3061     raw_test_pass(0xb000 + targetcore);             // targetcore
3062 #endif
3063     while(outmsgleft-- > 0) {
3064       gdn_send(outmsgdata[outmsgindex++]);
3065 #ifdef RAWDEBUG
3066       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3067 #endif
3068     }
3069 #ifdef RAWDEBUG
3070     raw_test_pass(0xffff);
3071 #endif
3072     isMsgSending = false;
3073 #ifdef INTERRUPT
3074     raw_user_interrupts_off();
3075 #endif
3076     // check if there are still msg hanging
3077     if(outmsgindex == outmsglast) {
3078       // no more msgs
3079       outmsgindex = outmsglast = 0;
3080       isMsgHanging = false;
3081     }
3082 #ifdef INTERRUPT
3083     raw_user_interrupts_on();
3084 #endif
3085   }
3086   return true;
3087 #elif defined THREADSIMULATE
3088   int numofcore = pthread_getspecific(key);
3089
3090   int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
3091   printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3092   if(0 != rc) {
3093     return false;
3094   }
3095   if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3096     // no locks for this object
3097     // first time to operate on this shared object
3098     // create a lock for it
3099     rc = pthread_rwlock_unlock(&rwlock_tbl);
3100     printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3101     pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
3102     memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
3103     rc = pthread_rwlock_init(rwlock, NULL);
3104     printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3105     rc = pthread_rwlock_trywrlock(&rwlock_tbl);
3106     printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3107     if(0 != rc) {
3108       pthread_rwlock_destroy(rwlock);
3109       RUNFREE(rwlock);
3110       return false;
3111     } else {
3112       if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3113         // check again
3114         RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
3115       } else {
3116         pthread_rwlock_destroy(rwlock);
3117         RUNFREE(rwlock);
3118         RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
3119       }
3120       rc = pthread_rwlock_unlock(&rwlock_tbl);
3121       printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3122     }
3123     rc = pthread_rwlock_trywrlock(rwlock);
3124     printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
3125     if(0 != rc) {
3126       return false;
3127     } else {
3128       return true;
3129     }
3130   } else {
3131     pthread_rwlock_t* rwlock_obj = NULL;
3132     RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3133     rc = pthread_rwlock_unlock(&rwlock_tbl);
3134     printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3135     int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
3136     printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3137     if(0 != rc_obj) {
3138       return false;
3139     } else {
3140       return true;
3141     }
3142   }
3143
3144 #endif
3145 }
3146
3147 void releasewritelock(void * ptr) {
3148 #ifdef RAW
3149   unsigned msgHdr;
3150   int self_y, self_x, target_y, target_x;
3151   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
3152   // for 32 bit machine, the size is always 3 words
3153   //int msgsize = sizeof(int) * 3;
3154   int msgsize = 3;
3155   int tc = TOTALCORE;
3156 #ifdef INTERRUPT
3157   raw_user_interrupts_off();
3158 #endif
3159   targetcore = ((int)ptr >> 5) % tc;
3160 #ifdef INTERRUPT
3161   raw_user_interrupts_on();
3162 #endif
3163
3164   if(targetcore == corenum) {
3165 #ifdef INTERRUPT
3166     raw_user_interrupts_off();
3167 #endif
3168     // reside on this core
3169     if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3170       // no locks for this object, something is wrong
3171       raw_test_done(0xa008);
3172     } else {
3173       int rwlock_obj = 0;
3174 #ifdef RAWDEBUG
3175       raw_test_pass(0xe662);
3176 #endif
3177       RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
3178 #ifdef RAWDEBUG
3179       raw_test_pass_reg(rwlock_obj);
3180 #endif
3181       rwlock_obj++;
3182       RuntimeHashremovekey(locktbl, (int)ptr);
3183       RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
3184 #ifdef RAWDEBUG
3185       raw_test_pass_reg(rwlock_obj);
3186 #endif
3187     }
3188 #ifdef INTERRUPT
3189     raw_user_interrupts_on();
3190 #endif
3191     return;
3192   }
3193
3194 #ifdef RAWDEBUG
3195   raw_test_pass(0xe663);
3196 #endif
3197   calCoords(corenum, &self_y, &self_x);
3198   calCoords(targetcore, &target_y, &target_x);
3199   // Build the message header
3200   msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
3201                              self_y, self_x,
3202                              target_y, target_x);
3203   // start sending the msg, set send msg flag
3204   isMsgSending = true;
3205   gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
3206 #ifdef RAWDEBUG
3207   raw_test_pass(0xbbbb);
3208   raw_test_pass(0xb000 + targetcore);
3209 #endif
3210   gdn_send(5);   // lock release
3211  #ifdef RAWDEBUG
3212   raw_test_pass(5);
3213 #endif
3214   gdn_send(1);       // write lock
3215 #ifdef RAWDEBUG
3216   raw_test_pass(1);
3217 #endif
3218   gdn_send(ptr);
3219 #ifdef RAWDEBUG
3220   raw_test_pass_reg(ptr);
3221   raw_test_pass(0xffff);
3222 #endif
3223   // end of sending this msg, set sand msg flag false
3224   isMsgSending = false;
3225   // check if there are pending msgs
3226   while(isMsgHanging) {
3227     // get the msg from outmsgdata[]
3228     // length + target + msg
3229     outmsgleft = outmsgdata[outmsgindex++];
3230     targetcore = outmsgdata[outmsgindex++];
3231     calCoords(targetcore, &target_y, &target_x);
3232     // Build the message header
3233     msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
3234                                self_y, self_x,
3235                                target_y, target_x);
3236     isMsgSending = true;
3237     gdn_send(msgHdr);                           // Send the message header to EAST to handle fab(n - 1).
3238 #ifdef RAWDEBUG
3239     raw_test_pass(0xbbbb);
3240     raw_test_pass(0xb000 + targetcore);             // targetcore
3241 #endif
3242     while(outmsgleft-- > 0) {
3243       gdn_send(outmsgdata[outmsgindex++]);
3244 #ifdef RAWDEBUG
3245       raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
3246 #endif
3247     }
3248 #ifdef RAWDEBUG
3249     raw_test_pass(0xffff);
3250 #endif
3251     isMsgSending = false;
3252 #ifdef INTERRUPT
3253     raw_user_interrupts_off();
3254 #endif
3255     // check if there are still msg hanging
3256     if(outmsgindex == outmsglast) {
3257       // no more msgs
3258       outmsgindex = outmsglast = 0;
3259       isMsgHanging = false;
3260     }
3261 #ifdef INTERRUPT
3262     raw_user_interrupts_on();
3263 #endif
3264   }
3265 #elif defined THREADSIMULATE
3266   int numofcore = pthread_getspecific(key);
3267   int rc = pthread_rwlock_rdlock(&rwlock_tbl);
3268   printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3269   if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
3270     printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
3271     exit(-1);
3272   }
3273   pthread_rwlock_t* rwlock_obj = NULL;
3274   RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
3275   int rc_obj = pthread_rwlock_unlock(rwlock_obj);
3276   printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
3277   rc = pthread_rwlock_unlock(&rwlock_tbl);
3278   printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
3279 #endif
3280 }
3281
3282 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3283   void * taskpointerarray[MAXTASKPARAMS];
3284   int j;
3285   int numparams=parameter->task->numParameters;
3286   int numiterators=parameter->task->numTotal-1;
3287   int retval=1;
3288   int addnormal=1;
3289   int adderror=1;
3290
3291   struct taskdescriptor * task=parameter->task;
3292
3293   ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);      //this add the object to parameterwrapper
3294
3295   /* Add enqueued object to parameter vector */
3296   taskpointerarray[parameter->slot]=ptr;
3297
3298   /* Reset iterators */
3299   for(j=0; j<numiterators; j++) {
3300     toiReset(&parameter->iterators[j]);
3301   }
3302
3303   /* Find initial state */
3304   for(j=0; j<numiterators; j++) {
3305 backtrackinit:
3306     if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
3307       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
3308     else if (j>0) {
3309       /* Need to backtrack */
3310       toiReset(&parameter->iterators[j]);
3311       j--;
3312       goto backtrackinit;
3313     } else {
3314       /* Nothing to enqueue */
3315       return retval;
3316     }
3317   }
3318
3319
3320   while(1) {
3321     /* Enqueue current state */
3322     int launch = 0;
3323     struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
3324     tpd->task=task;
3325     tpd->numParameters=numiterators+1;
3326     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
3327     for(j=0; j<=numiterators; j++) {
3328       tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3329     }
3330     /* Enqueue task */
3331     if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3332       genputtable(activetasks, tpd, tpd);
3333     } else {
3334       RUNFREE(tpd->parameterArray);
3335       RUNFREE(tpd);
3336     }
3337
3338     /* This loop iterates to the next parameter combination */
3339     if (numiterators==0)
3340       return retval;
3341
3342     for(j=numiterators-1; j<numiterators; j++) {
3343 backtrackinc:
3344       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
3345         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
3346       else if (j>0) {
3347         /* Need to backtrack */
3348         toiReset(&parameter->iterators[j]);
3349         j--;
3350         goto backtrackinc;
3351       } else {
3352         /* Nothing more to enqueue */
3353         return retval;
3354       }
3355     }
3356   }
3357   return retval;
3358 }
3359
3360 #ifdef RAW
3361 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
3362   void * taskpointerarray[MAXTASKPARAMS];
3363   int j;
3364   int numparams=parameter->task->numParameters;
3365   int numiterators=parameter->task->numTotal-1;
3366   int retval=1;
3367   int addnormal=1;
3368   int adderror=1;
3369
3370   struct taskdescriptor * task=parameter->task;
3371
3372   ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);      //this add the object to parameterwrapper
3373
3374   /* Add enqueued object to parameter vector */
3375   taskpointerarray[parameter->slot]=ptr;
3376
3377   /* Reset iterators */
3378   for(j=0; j<numiterators; j++) {
3379     toiReset(&parameter->iterators[j]);
3380   }
3381
3382   /* Find initial state */
3383   for(j=0; j<numiterators; j++) {
3384 backtrackinit:
3385     if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
3386       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
3387     else if (j>0) {
3388       /* Need to backtrack */
3389       toiReset(&parameter->iterators[j]);
3390       j--;
3391       goto backtrackinit;
3392     } else {
3393       /* Nothing to enqueue */
3394       return retval;
3395     }
3396   }
3397
3398   while(1) {
3399     /* Enqueue current state */
3400     int launch = 0;
3401     struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
3402     tpd->task=task;
3403     tpd->numParameters=numiterators+1;
3404     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
3405     for(j=0; j<=numiterators; j++) {
3406       tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
3407     }
3408     /* Enqueue task */
3409     if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
3410       genputtable_I(activetasks, tpd, tpd);
3411     } else {
3412       RUNFREE(tpd->parameterArray);
3413       RUNFREE(tpd);
3414     }
3415
3416     /* This loop iterates to the next parameter combination */
3417     if (numiterators==0)
3418       return retval;
3419
3420     for(j=numiterators-1; j<numiterators; j++) {
3421 backtrackinc:
3422       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
3423         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
3424       else if (j>0) {
3425         /* Need to backtrack */
3426         toiReset(&parameter->iterators[j]);
3427         j--;
3428         goto backtrackinc;
3429       } else {
3430         /* Nothing more to enqueue */
3431         return retval;
3432       }
3433     }
3434   }
3435   return retval;
3436 }
3437 #endif
3438
3439 /* Handler for signals. The signals catch null pointer errors and
3440    arithmatic errors. */
3441 #ifndef RAW
3442 void myhandler(int sig, siginfo_t *info, void *uap) {
3443   sigset_t toclear;
3444 #ifdef DEBUG
3445   printf("sig=%d\n",sig);
3446   printf("signal\n");
3447 #endif
3448   sigemptyset(&toclear);
3449   sigaddset(&toclear, sig);
3450   sigprocmask(SIG_UNBLOCK, &toclear,NULL);
3451   longjmp(error_handler,1);
3452 }
3453 #endif
3454
3455 fd_set readfds;
3456 int maxreadfd;
3457 struct RuntimeHash *fdtoobject;
3458
3459 void addreadfd(int fd) {
3460   if (fd>=maxreadfd)
3461     maxreadfd=fd+1;
3462   FD_SET(fd, &readfds);
3463 }
3464
3465 void removereadfd(int fd) {
3466   FD_CLR(fd, &readfds);
3467   if (maxreadfd==(fd+1)) {
3468     maxreadfd--;
3469     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
3470       maxreadfd--;
3471   }
3472 }
3473
3474 #ifdef PRECISE_GC
3475 #define OFFSET 2
3476 #else
3477 #define OFFSET 0
3478 #endif
3479
3480 void executetasks() {
3481   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
3482   int numparams=0;
3483   int numtotal=0;
3484   struct ___Object___ * tmpparam = NULL;
3485   struct parameterdescriptor * pd=NULL;
3486   struct parameterwrapper *pw=NULL;
3487   int j = 0;
3488   int x = 0;
3489   bool lock = true;
3490
3491 #ifdef RAW
3492   int grount = 0;
3493   int andmask=0;
3494   int checkmask=0;
3495 #ifdef RAWDEBUG
3496   raw_test_pass(0xe991);
3497 #endif
3498 #endif
3499
3500 #ifndef RAW
3501   /* Set up signal handlers */
3502   struct sigaction sig;
3503   sig.sa_sigaction=&myhandler;
3504   sig.sa_flags=SA_SIGINFO;
3505   sigemptyset(&sig.sa_mask);
3506
3507   /* Catch bus errors, segmentation faults, and floating point exceptions*/
3508   sigaction(SIGBUS,&sig,0);
3509   sigaction(SIGSEGV,&sig,0);
3510   sigaction(SIGFPE,&sig,0);
3511   sigaction(SIGPIPE,&sig,0);
3512 #endif
3513
3514 #ifndef RAW
3515   /* Zero fd set */
3516   FD_ZERO(&readfds);
3517 #endif
3518   maxreadfd=0;
3519 #ifndef RAW
3520   fdtoobject=allocateRuntimeHash(100);
3521 #endif
3522
3523 #ifndef RAW
3524   /* Map first block of memory to protected, anonymous page */
3525   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
3526 #endif
3527
3528 newtask:
3529   while((hashsize(activetasks)>0)||(maxreadfd>0)) {
3530
3531 #ifdef RAW
3532 #ifdef RAWDEBUG
3533     raw_test_pass(0xe992);
3534 #endif
3535 #else
3536     /* Check if any filedescriptors have IO pending */
3537     if (maxreadfd>0) {
3538       int i;
3539       struct timeval timeout={0,0};
3540       fd_set tmpreadfds;
3541       int numselect;
3542       tmpreadfds=readfds;
3543       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
3544       if (numselect>0) {
3545         /* Process ready fd's */
3546         int fd;
3547         for(fd=0; fd<maxreadfd; fd++) {
3548           if (FD_ISSET(fd, &tmpreadfds)) {
3549             /* Set ready flag on object */
3550             void * objptr;
3551             //      printf("Setting fd %d\n",fd);
3552             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
3553               if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
3554                 enqueueObject(objptr, NULL, 0);
3555               }
3556             }
3557           }
3558         }
3559       }
3560     }
3561 #endif
3562
3563     /* See if there are any active tasks */
3564     if (hashsize(activetasks)>0) {
3565       int i;
3566 #ifdef RAWPROFILE
3567       if(!taskInfoOverflow) {
3568         TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
3569         taskInfoArray[taskInfoIndex] = checkTaskInfo;
3570         checkTaskInfo->taskName = "tpd checking";
3571         checkTaskInfo->startTime = raw_get_cycle();
3572         checkTaskInfo->endTime = -1;
3573       }
3574 #endif
3575       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
3576       genfreekey(activetasks, currtpd);
3577
3578       /* Check if this task has failed, allow a task that contains optional objects to fire */
3579       /*if (gencontains(failedtasks, currtpd)) {
3580          // Free up task parameter descriptor
3581          RUNFREE(currtpd->parameterArray);
3582          RUNFREE(currtpd);
3583          goto newtask;
3584          }*/
3585       numparams=currtpd->task->numParameters;
3586       numtotal=currtpd->task->numTotal;
3587
3588 #ifdef THREADSIMULATE
3589       int isolateflags[numparams];
3590 #endif
3591       /* Make sure that the parameters are still in the queues */
3592       for(i=0; i<numparams; i++) {
3593         void * parameter=currtpd->parameterArray[i];
3594 #ifdef RAW
3595 #ifdef RAWDEBUG
3596         raw_test_pass(0xe993);
3597 #endif
3598
3599         if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3600           lock = false;
3601           taskpointerarray[i+OFFSET]=parameter;
3602           goto execute;
3603         }
3604         lock = true;
3605         // require locks for this parameter if it is not a startup object
3606         getwritelock(parameter);
3607         grount = 0;
3608
3609 #ifdef INTERRUPT
3610         raw_user_interrupts_off();
3611 #endif
3612 #ifdef RAWPROFILE
3613         isInterrupt = false;
3614 #endif
3615         while(!lockflag) {
3616           receiveObject();
3617         }
3618 #ifndef INTERRUPT
3619         if(reside) {
3620           while(receiveObject() != -1) {
3621           }
3622         }
3623 #endif
3624         grount = lockresult;
3625
3626         lockresult = 0;
3627         lockobj = 0;
3628         lockflag = false;
3629 #ifndef INTERRUPT
3630         reside = false;
3631 #endif
3632 #ifdef RAWPROFILE
3633         isInterrupt = true;
3634 #endif
3635 #ifdef INTERRUPT
3636         raw_user_interrupts_on();
3637 #endif
3638
3639         if(grount == 0) {
3640 #ifdef RAWDEBUG
3641           raw_test_pass(0xe994);
3642 #endif
3643           // can not get the lock, try later
3644           for(j = 0; j < i; ++j) {
3645             releasewritelock(taskpointerarray[j+OFFSET]);
3646           }
3647           genputtable(activetasks, currtpd, currtpd);
3648           if(hashsize(activetasks) == 1) {
3649             // only one task right now, wait a little while before next try
3650             int halt = 10000;
3651             while(halt--) {
3652             }
3653           }
3654 #ifdef RAWPROFILE
3655           // fail, set the end of the checkTaskInfo
3656           if(!taskInfoOverflow) {
3657             taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3658             taskInfoIndex++;
3659             if(taskInfoIndex == TASKINFOLENGTH) {
3660               taskInfoOverflow = true;
3661             }
3662           }
3663 #endif
3664           goto newtask;
3665         }
3666         // flush the object
3667         {
3668           raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
3669           /*int tmp = 0;
3670              for(tmp = 0; tmp < classsize[((struct ___Object___ *)parameter)->type]; ++tmp) {
3671                   invalidateAddr(parameter + tmp);
3672              }*/
3673         }
3674 #endif
3675         tmpparam = (struct ___Object___ *)parameter;
3676 #ifdef THREADSIMULATE
3677         if(((struct ___Object___ *)parameter)->type == STARTUPTYPE) {
3678           lock = false;
3679           taskpointerarray[i+OFFSET]=parameter;
3680           goto execute;
3681         }
3682         lock = true;
3683         if(0 == tmpparam->isolate) {
3684           isolateflags[i] = 0;
3685           // shared object, need to flush with current value
3686           //if(!getreadlock(tmpparam->original)) {
3687           //    // fail to get read lock of the original object, try this task later
3688           if(!getwritelock(tmpparam->original)) {
3689             // fail to get write lock, release all obtained locks and try this task later
3690             int j = 0;
3691             for(j = 0; j < i; ++j) {
3692               if(0 == isolateflags[j]) {
3693                 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3694               }
3695             }
3696             genputtable(activetasks, currtpd, currtpd);
3697             goto newtask;
3698           }
3699           if(tmpparam->version != tmpparam->original->version) {
3700             // some task on another core has changed this object
3701             // flush this object
3702             //memcpy(tmpparam, tmpparam->original, classsize[tmpparam->type]);
3703             // release all obtained locks
3704             int j = 0;
3705             for(j = 0; j < i; ++j) {
3706               if(0 == isolateflags[j]) {
3707                 releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
3708               }
3709             }
3710             releasewritelock(tmpparam->original);
3711
3712             // dequeue this object
3713             int numofcore = pthread_getspecific(key);
3714             struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
3715             int length = numqueues[numofcore][tmpparam->type];
3716             for(j = 0; j < length; ++j) {
3717               struct parameterwrapper * pw = queues[j];
3718               if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
3719                 int next;
3720                 int UNUSED, UNUSED2;
3721                 int * enterflags;
3722                 ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3723                 ObjectHashremove(pw->objectset, (int)tmpparam);
3724                 if (enterflags!=NULL)
3725                   free(enterflags);
3726               }
3727             }
3728             // try to enqueue it again to check if it feeds other tasks;
3729             //enqueueObject(tmpparam, NULL, 0);
3730             // Free up task parameter descriptor
3731             RUNFREE(currtpd->parameterArray);
3732             RUNFREE(currtpd);
3733             goto newtask;
3734           }
3735         } else {
3736           isolateflags[i] = 1;
3737         }
3738 #endif
3739         pd=currtpd->task->descriptorarray[i];
3740         pw=(struct parameterwrapper *) pd->queue;
3741         /* Check that object is still in queue */
3742         {
3743           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
3744 #ifdef RAWDEBUG
3745             raw_test_pass(0xe995);
3746 #endif
3747             // release grabbed locks
3748             for(j = 0; j < i; ++j) {
3749               releasewritelock(taskpointerarray[j+OFFSET]);
3750             }
3751             releasewritelock(parameter);
3752             RUNFREE(currtpd->parameterArray);
3753             RUNFREE(currtpd);
3754             goto newtask;
3755           }
3756         }
3757 #ifdef RAW
3758         /* Check if the object's flags still meets requirements */
3759         {
3760           int tmpi = 0;
3761           bool ismet = false;
3762           for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
3763             andmask=pw->intarray[tmpi*2];
3764             checkmask=pw->intarray[tmpi*2+1];
3765 #ifdef RAWDEBUG
3766             raw_test_pass(0xdd000000 + andmask);
3767             raw_test_pass_reg((int)parameter);
3768             raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
3769             raw_test_pass(0xdd000000 + checkmask);
3770 #endif
3771             if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
3772               ismet = true;
3773               break;
3774             }
3775           }
3776           if (!ismet) {
3777             // flags are never suitable
3778             // remove this obj from the queue
3779             int next;
3780             int UNUSED, UNUSED2;
3781             int * enterflags;
3782 #ifdef RAWDEBUG
3783             raw_test_pass(0xe996);
3784 #endif
3785             ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
3786             ObjectHashremove(pw->objectset, (int)parameter);
3787             if (enterflags!=NULL)
3788               free(enterflags);
3789             // release grabbed locks
3790             for(j = 0; j < i; ++j) {
3791               releasewritelock(taskpointerarray[j+OFFSET]);
3792             }
3793             releasewritelock(parameter);
3794             RUNFREE(currtpd->parameterArray);
3795             RUNFREE(currtpd);
3796 #ifdef RAWPROFILE
3797             // fail, set the end of the checkTaskInfo
3798             if(!taskInfoOverflow) {
3799               taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3800               taskInfoIndex++;
3801               if(taskInfoIndex == TASKINFOLENGTH) {
3802                 taskInfoOverflow = true;
3803               }
3804             }
3805 #endif
3806             goto newtask;
3807           }
3808         }
3809 #endif
3810 parameterpresent:
3811         ;
3812         /* Check that object still has necessary tags */
3813         for(j=0; j<pd->numbertags; j++) {
3814           int slotid=pd->tagarray[2*j]+numparams;
3815           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
3816           if (!containstag(parameter, tagd)) {
3817 #ifdef RAWDEBUG
3818             raw_test_pass(0xe997);
3819 #endif
3820             RUNFREE(currtpd->parameterArray);
3821             RUNFREE(currtpd);
3822             goto newtask;
3823           }
3824         }
3825
3826         taskpointerarray[i+OFFSET]=parameter;
3827       }
3828       /* Copy the tags */
3829       for(; i<numtotal; i++) {
3830         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
3831       }
3832
3833 #ifdef THREADSIMULATE
3834       for(i = 0; i < numparams; ++i) {
3835         if(0 == isolateflags[i]) {
3836           struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3837           if(tmpparam != tmpparam->original) {
3838             taskpointerarray[i+OFFSET] = tmpparam->original;
3839           }
3840         }
3841       }
3842 #endif
3843
3844       {
3845 #if 0
3846 #ifndef RAW
3847         /* Checkpoint the state */
3848         forward=allocateRuntimeHash(100);
3849         reverse=allocateRuntimeHash(100);
3850         //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
3851 #endif
3852 #endif
3853         if (x=setjmp(error_handler)) {
3854           int counter;
3855           /* Recover */
3856 #ifndef RAW
3857 #ifdef DEBUG
3858           printf("Fatal Error=%d, Recovering!\n",x);
3859 #endif
3860 #endif
3861           /*
3862              genputtable(failedtasks,currtpd,currtpd);
3863              //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
3864
3865              freeRuntimeHash(forward);
3866              freeRuntimeHash(reverse);
3867              freemalloc();
3868              forward=NULL;
3869              reverse=NULL;
3870            */
3871           //fflush(stdout);
3872 #ifdef RAW
3873 #ifdef RAWDEBUG
3874           raw_test_pass_reg(x);
3875 #endif
3876           raw_test_done(0xa009);
3877 #else
3878           exit(-1);
3879 #endif
3880         } else {
3881           /*if (injectfailures) {
3882              if ((((double)random())/RAND_MAX)<failurechance) {
3883               printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
3884               longjmp(error_handler,10);
3885              }
3886              }*/
3887           /* Actually call task */
3888 #ifdef PRECISE_GC
3889                                                                             ((int *)taskpointerarray)[0]=currtpd->numParameters;
3890           taskpointerarray[1]=NULL;
3891 #endif
3892 execute:
3893 #ifdef RAWPROFILE
3894           {
3895             // check finish, set the end of the checkTaskInfo
3896             if(!taskInfoOverflow) {
3897               taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3898               taskInfoIndex++;
3899               if(taskInfoIndex == TASKINFOLENGTH) {
3900                 taskInfoOverflow = true;
3901               }
3902             }
3903           }
3904           if(!taskInfoOverflow) {
3905             // new a taskInfo for the task execution
3906             TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
3907             taskInfoArray[taskInfoIndex] = taskInfo;
3908             taskInfo->taskName = currtpd->task->name;
3909             taskInfo->startTime = raw_get_cycle();
3910             taskInfo->endTime = -1;
3911           }
3912 #endif
3913
3914           if(debugtask) {
3915 #ifndef RAW
3916             printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3917 #endif
3918             ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3919 #ifndef RAW
3920             printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
3921 #endif
3922           } else {
3923             ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
3924           }
3925 #ifdef RAWPROFILE
3926           // task finish, set the end of the checkTaskInfo
3927           if(!taskInfoOverflow) {
3928             taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3929             taskInfoIndex++;
3930             if(taskInfoIndex == TASKINFOLENGTH) {
3931               taskInfoOverflow = true;
3932             }
3933           }
3934           // new a PostTaskInfo for the post-task execution
3935           if(!taskInfoOverflow) {
3936             TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
3937             taskInfoArray[taskInfoIndex] = postTaskInfo;
3938             postTaskInfo->taskName = "post task execution";
3939             postTaskInfo->startTime = raw_get_cycle();
3940             postTaskInfo->endTime = -1;
3941           }
3942 #endif
3943 #ifdef RAWDEBUG
3944           raw_test_pass(0xe998);
3945           raw_test_pass_reg(lock);
3946 #endif
3947
3948           if(lock) {
3949 #ifdef RAW
3950             for(i = 0; i < numparams; ++i) {
3951               int j = 0;
3952               struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3953 #ifdef RAWDEBUG
3954               raw_test_pass(0xe999);
3955               raw_test_pass(0xdd100000 + tmpparam->flag);
3956 #endif
3957               releasewritelock(tmpparam);
3958             }
3959 #elif defined THREADSIMULATE
3960             for(i = 0; i < numparams; ++i) {
3961               if(0 == isolateflags[i]) {
3962                 struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
3963                 releasewritelock(tmpparam);
3964               }
3965             }
3966 #endif
3967           }
3968
3969 #ifdef RAWPROFILE
3970           // post task execution finish, set the end of the postTaskInfo
3971           if(!taskInfoOverflow) {
3972             taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
3973             taskInfoIndex++;
3974             if(taskInfoIndex == TASKINFOLENGTH) {
3975               taskInfoOverflow = true;
3976             }
3977           }
3978 #endif
3979
3980 #if 0
3981 #ifndef RAW
3982           freeRuntimeHash(forward);
3983           freeRuntimeHash(reverse);
3984           freemalloc();
3985 #endif
3986 #endif
3987           // Free up task parameter descriptor
3988           RUNFREE(currtpd->parameterArray);
3989           RUNFREE(currtpd);
3990 #if 0
3991 #ifndef RAW
3992           forward=NULL;
3993           reverse=NULL;
3994 #endif
3995 #endif
3996 #ifdef RAWDEBUG
3997           raw_test_pass(0xe99a);
3998 #endif
3999 #ifdef RAWPATH
4000           raw_test_pass(0xe99a);
4001 #endif
4002
4003         }
4004       }
4005     }
4006   }
4007 #ifdef RAWDEBUG
4008   raw_test_pass(0xe999);
4009 #endif
4010 }
4011
4012 /* This function processes an objects tags */
4013 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
4014   int i;
4015
4016   for(i=0; i<pd->numbertags; i++) {
4017     int slotid=pd->tagarray[2*i];
4018     int tagid=pd->tagarray[2*i+1];
4019
4020     if (statusarray[slotid+numparams]==0) {
4021       parameter->iterators[*iteratorcount].istag=1;
4022       parameter->iterators[*iteratorcount].tagid=tagid;
4023       parameter->iterators[*iteratorcount].slot=slotid+numparams;
4024       parameter->iterators[*iteratorcount].tagobjectslot=index;
4025       statusarray[slotid+numparams]=1;
4026       (*iteratorcount)++;
4027     }
4028   }
4029 }
4030
4031
4032 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
4033   int i;
4034   int tagcount=0;
4035   struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
4036
4037   parameter->iterators[*iteratorcount].istag=0;
4038   parameter->iterators[*iteratorcount].slot=index;
4039   parameter->iterators[*iteratorcount].objectset=objectset;
4040   statusarray[index]=1;
4041
4042   for(i=0; i<pd->numbertags; i++) {
4043     int slotid=pd->tagarray[2*i];
4044     int tagid=pd->tagarray[2*i+1];
4045     if (statusarray[slotid+numparams]!=0) {
4046       /* This tag has already been enqueued, use it to narrow search */
4047       parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
4048       tagcount++;
4049     }
4050   }
4051   parameter->iterators[*iteratorcount].numtags=tagcount;
4052
4053   (*iteratorcount)++;
4054 }
4055
4056 /* This function builds the iterators for a task & parameter */
4057
4058 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
4059   int statusarray[MAXTASKPARAMS];
4060   int i;
4061   int numparams=task->numParameters;
4062   int iteratorcount=0;
4063   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
4064
4065   statusarray[index]=1; /* Initial parameter */
4066   /* Process tags for initial iterator */
4067
4068   processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
4069
4070   while(1) {
4071 loopstart:
4072     /* Check for objects with existing tags */
4073     for(i=0; i<numparams; i++) {
4074       if (statusarray[i]==0) {
4075         struct parameterdescriptor *pd=task->descriptorarray[i];
4076         int j;
4077         for(j=0; j<pd->numbertags; j++) {
4078           int slotid=pd->tagarray[2*j];
4079           if(statusarray[slotid+numparams]!=0) {
4080             processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4081             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4082             goto loopstart;
4083           }
4084         }
4085       }
4086     }
4087
4088     /* Next do objects w/ unbound tags*/
4089
4090     for(i=0; i<numparams; i++) {
4091       if (statusarray[i]==0) {
4092         struct parameterdescriptor *pd=task->descriptorarray[i];
4093         if (pd->numbertags>0) {
4094           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4095           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4096           goto loopstart;
4097         }
4098       }
4099     }
4100
4101     /* Nothing with a tag enqueued */
4102
4103     for(i=0; i<numparams; i++) {
4104       if (statusarray[i]==0) {
4105         struct parameterdescriptor *pd=task->descriptorarray[i];
4106         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
4107         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
4108         goto loopstart;
4109       }
4110     }
4111
4112     /* Nothing left */
4113     return;
4114   }
4115 }
4116
4117 void printdebug() {
4118   int i;
4119   int j;
4120 #ifdef THREADSIMULATE
4121   int numofcore = pthread_getspecific(key);
4122   for(i=0; i<numtasks[numofcore]; i++) {
4123     struct taskdescriptor * task=taskarray[numofcore][i];
4124 #else
4125 #ifdef RAW
4126   if(corenum > NUMCORES - 1) {
4127     return;
4128   }
4129 #endif
4130   for(i=0; i<numtasks[corenum]; i++) {
4131     struct taskdescriptor * task=taskarray[corenum][i];
4132 #endif
4133 #ifndef RAW
4134     printf("%s\n", task->name);
4135 #endif
4136     for(j=0; j<task->numParameters; j++) {
4137       struct parameterdescriptor *param=task->descriptorarray[j];
4138       struct parameterwrapper *parameter=param->queue;
4139       struct ObjectHash * set=parameter->objectset;
4140       struct ObjectIterator objit;
4141 #ifndef RAW
4142       printf("  Parameter %d\n", j);
4143 #endif
4144       ObjectHashiterator(set, &objit);
4145       while(ObjhasNext(&objit)) {
4146         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
4147         struct ___Object___ * tagptr=obj->___tags___;
4148         int nonfailed=Objdata4(&objit);
4149         int numflags=Objdata3(&objit);
4150         int flags=Objdata2(&objit);
4151         Objnext(&objit);
4152 #ifndef RAW
4153         printf("    Contains %lx\n", obj);
4154         printf("      flag=%d\n", obj->flag);
4155 #endif
4156         if (tagptr==NULL) {
4157         } else if (tagptr->type==TAGTYPE) {
4158 #ifndef RAW
4159           printf("      tag=%lx\n",tagptr);
4160 #endif
4161           ;
4162         } else {
4163           int tagindex=0;
4164           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
4165           for(; tagindex<ao->___cachedCode___; tagindex++) {
4166 #ifndef RAW
4167             printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
4168 #endif
4169           }
4170         }
4171       }
4172     }
4173   }
4174 }
4175
4176
4177 /* This function processes the task information to create queues for
4178    each parameter type. */
4179
4180 void processtasks() {
4181   int i;
4182 #ifdef RAW
4183   if(corenum > NUMCORES - 1) {
4184     return;
4185   }
4186 #endif
4187 #ifdef THREADSIMULATE
4188   int numofcore = pthread_getspecific(key);
4189   for(i=0; i<numtasks[numofcore]; i++) {
4190     struct taskdescriptor *task=taskarray[numofcore][i];
4191 #else
4192   for(i=0; i<numtasks[corenum]; i++) {
4193     struct taskdescriptor * task=taskarray[corenum][i];
4194 #endif
4195     int j;
4196
4197     /* Build objectsets */
4198     for(j=0; j<task->numParameters; j++) {
4199       struct parameterdescriptor *param=task->descriptorarray[j];
4200       struct parameterwrapper *parameter=param->queue;
4201       parameter->objectset=allocateObjectHash(10);
4202       parameter->task=task;
4203     }
4204
4205     /* Build iterators for parameters */
4206     for(j=0; j<task->numParameters; j++) {
4207       struct parameterdescriptor *param=task->descriptorarray[j];
4208       struct parameterwrapper *parameter=param->queue;
4209       builditerators(task, j, parameter);
4210     }
4211   }
4212 }
4213
4214 void toiReset(struct tagobjectiterator * it) {
4215   if (it->istag) {
4216     it->tagobjindex=0;
4217   } else if (it->numtags>0) {
4218     it->tagobjindex=0;
4219   } else {
4220     ObjectHashiterator(it->objectset, &it->it);
4221   }
4222 }
4223
4224 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4225   if (it->istag) {
4226     /* Iterate tag */
4227     /* Get object with tags */
4228     struct ___Object___ *obj=objectarray[it->tagobjectslot];
4229     struct ___Object___ *tagptr=obj->___tags___;
4230     if (tagptr->type==TAGTYPE) {
4231       if ((it->tagobjindex==0)&& /* First object */
4232           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
4233         return 1;
4234       else
4235         return 0;
4236     } else {
4237       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4238       int tagindex=it->tagobjindex;
4239       for(; tagindex<ao->___cachedCode___; tagindex++) {
4240         struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
4241         if (td->flag==it->tagid) {
4242           it->tagobjindex=tagindex; /* Found right type of tag */
4243           return 1;
4244         }
4245       }
4246       return 0;
4247     }
4248   } else if (it->numtags>0) {
4249     /* Use tags to locate appropriate objects */
4250     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4251     struct ___Object___ *objptr=tag->flagptr;
4252     int i;
4253     if (objptr->type!=OBJECTARRAYTYPE) {
4254       if (it->tagobjindex>0)
4255         return 0;
4256       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4257         return 0;
4258       for(i=1; i<it->numtags; i++) {
4259         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4260         if (!containstag(objptr,tag2))
4261           return 0;
4262       }
4263       return 1;
4264     } else {
4265       struct ArrayObject *ao=(struct ArrayObject *) objptr;
4266       int tagindex;
4267       int i;
4268       for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
4269         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
4270         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
4271           continue;
4272         for(i=1; i<it->numtags; i++) {
4273           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
4274           if (!containstag(objptr,tag2))
4275             goto nexttag;
4276         }
4277         it->tagobjindex=tagindex;
4278         return 1;
4279 nexttag:
4280         ;
4281       }
4282       it->tagobjindex=tagindex;
4283       return 0;
4284     }
4285   } else {
4286     return ObjhasNext(&it->it);
4287   }
4288 }
4289
4290 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
4291   int j;
4292   struct ___Object___ * objptr=tag->flagptr;
4293   if (objptr->type==OBJECTARRAYTYPE) {
4294     struct ArrayObject *ao=(struct ArrayObject *)objptr;
4295     for(j=0; j<ao->___cachedCode___; j++) {
4296       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
4297         return 1;
4298     }
4299     return 0;
4300   } else
4301     return objptr==ptr;
4302 }
4303
4304 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
4305   /* hasNext has all of the intelligence */
4306   if(it->istag) {
4307     /* Iterate tag */
4308     /* Get object with tags */
4309     struct ___Object___ *obj=objectarray[it->tagobjectslot];
4310     struct ___Object___ *tagptr=obj->___tags___;
4311     if (tagptr->type==TAGTYPE) {
4312       it->tagobjindex++;
4313       objectarray[it->slot]=tagptr;
4314     } else {
4315       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
4316       objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
4317     }
4318   } else if (it->numtags>0) {
4319     /* Use tags to locate appropriate objects */
4320     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
4321     struct ___Object___ *objptr=tag->flagptr;
4322     if (objptr->type!=OBJECTARRAYTYPE) {
4323       it->tagobjindex++;
4324       objectarray[it->slot]=objptr;
4325     } else {
4326       struct ArrayObject *ao=(struct ArrayObject *) objptr;
4327       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
4328     }
4329   } else {
4330     /* Iterate object */
4331     objectarray[it->slot]=(void *)Objkey(&it->it);
4332     Objnext(&it->it);
4333   }
4334 }
4335 #endif