e00c5e4f03f5f7b9de9728a90474502f292172d2
[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 #include <raw.h>
20 #include <raw_compiler_defs.h>
21 //#include <libints.h>
22 #elif defined THREADSIMULATE
23 // use POSIX message queue
24 // for each core, its message queue named as
25 // /msgqueue_corenum
26 #include <mqueue.h>
27 #include <sys/stat.h>
28 #endif
29 /*
30 extern int injectfailures;
31 extern float failurechance;
32 */
33 extern int debugtask;
34 extern int instaccum;
35
36 #ifdef RAW
37 #define TOTALCORE raw_get_num_tiles()
38 #endif
39
40 #ifdef CONSCHECK
41 #include "instrument.h"
42 #endif
43
44 struct genhashtable * activetasks;
45 struct genhashtable * failedtasks;
46 struct taskparamdescriptor * currtpd;
47 #ifndef RAW
48 struct RuntimeHash * forward;
49 struct RuntimeHash * reverse;
50 #endif
51
52 int corestatus[NUMCORES]; // records status of each core
53                           // 1: running tasks
54                                                   // 0: stall
55 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
56 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
57 #ifdef RAW
58 struct RuntimeHash locktable;
59 static struct RuntimeHash* locktbl = &locktable;
60 void * curr_heapbase=0;
61 void * curr_heaptop=0;
62 int self_numsendobjs;
63 int self_numreceiveobjs;
64 int lockobj;
65 int lockresult;
66 bool lockflag;
67 #ifndef INTERRUPT
68 bool reside;
69 #endif
70 struct Queue objqueue;
71 int msgdata[30];
72 int msgtype;
73 int msgdataindex;
74 int msglength;
75 void calCoords(int core_num, int* coordY, int* coordX);
76 void recvMsg(void);
77 #elif defined THREADSIMULATE
78 static struct RuntimeHash* locktbl;
79 struct thread_data {
80         int corenum;
81         int argc;
82         char** argv;
83         int numsendobjs;
84         int numreceiveobjs;
85 };
86 struct thread_data thread_data_array[NUMCORES];
87 mqd_t mqd[NUMCORES];
88 static pthread_key_t key;
89 static pthread_rwlock_t rwlock_tbl;
90 static pthread_rwlock_t rwlock_init;
91
92 void run(void * arg);
93 #endif
94
95 bool transStallMsg(int targetcore);
96 void transTerminateMsg(int targetcore);
97 int receiveObject();
98 bool getreadlock(void* ptr);
99 void releasereadlock(void* ptr);
100 #ifdef RAW
101 bool getreadlock_I(void* ptr);
102 void releasereadlock_I(void* ptr);
103 #endif
104 bool getwritelock(void* ptr);
105 void releasewritelock(void* ptr);
106
107 void flushAll(void);
108
109 void flushAll(void) {
110 #ifdef RAW
111         int i = 0;
112 #ifdef INTERRUPT
113         raw_user_interrupts_off();
114 #endif
115         raw_test_pass(0xec00);
116         for(i = 0; i < 512; ++i) {
117                 int base = i << 5;
118                 int off1 = 1 << 14;
119                 flushCacheline(base);
120                 flushCacheline(base|off1);
121         }
122 #ifdef INTERRUPT
123         raw_user_interrupts_on();
124 #endif
125         raw_test_pass(0xec02);
126 #endif
127 }
128
129 #ifdef RAW
130 void recvMsg() {
131         raw_test_pass(0xefee);
132         raw_user_interrupts_off();
133         raw_test_pass(0xef00);
134         receiveObject();
135         raw_test_pass(0xefff);
136         raw_user_interrupts_on();
137         raw_test_pass(0xefef);
138 }
139
140 void begin() {
141 #else
142 int main(int argc, char **argv) {
143 #endif
144 #ifdef RAW
145         int i = 0;
146         int argc = 1;
147         char ** argv = NULL;
148         bool sendStall = false;
149         bool isfirst = true;
150         bool tocontinue = false;
151         struct QueueItem * objitem = NULL;
152         struct transObjInfo * objInfo = NULL;
153         int grount = 0;
154         bool allStall = true;
155         int sumsendobj = 0;
156
157         raw_test_pass_reg(&locktable);
158         raw_test_pass_reg(&msglength);
159         raw_test_pass_reg(&i);
160         raw_test_pass(0xee01);
161         corenum = raw_get_abs_pos_x() + 4 * raw_get_abs_pos_y();
162
163         // initialize the arrays
164         if(STARTUPCORE == corenum) {
165                 // startup core to initialize corestatus[]
166                 for(i = 0; i < NUMCORES; ++i) {
167                         corestatus[i] = 1;
168                         numsendobjs[i] = 0; // assume all variables in RAW are local variables! MAY BE WRONG!!!
169                         numreceiveobjs[i] = 0;
170                 }
171         }
172         self_numsendobjs = 0;
173         self_numreceiveobjs = 0;
174         for(i = 0; i < 30; ++i) {
175                 msgdata[i] = -1;
176         }
177         //msgdata = NULL;
178         msgtype = -1;
179         msgdataindex = 0;
180         msglength = 30;
181         raw_test_pass(0xee02);
182         
183         // create the lock table, lockresult table and obj queue
184         locktable.size = 20;
185     locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
186     /* Set allocation blocks*/
187     locktable.listhead=NULL;
188     locktable.listtail=NULL;
189     /*Set data counts*/
190     locktable.numelements = 0;
191         lockobj = 0;
192         lockresult = 0;
193         lockflag = false;
194 #ifndef INTERRUPT
195         reside = false;
196 #endif
197         objqueue.head = NULL;
198         objqueue.tail = NULL;
199         raw_test_pass(0xee03);
200
201 #ifdef INTERRUPT
202         if (corenum < NUMCORES) {
203         // set up interrupts
204         setup_ints();
205         //setup_interrupts();
206         //start_gdn_avail_ints(recvMsg);
207         raw_user_interrupts_on();
208         raw_test_pass(0xee04);
209         }
210 #endif
211
212 #elif defined THREADSIMULATE
213         errno = 0;
214         int tids[NUMCORES];
215         int rc[NUMCORES];
216         pthread_t threads[NUMCORES];
217         int i = 0;
218
219         // initialize three arrays and msg queue array
220         char * pathhead = "/msgqueue_";
221         int targetlen = strlen(pathhead);
222         for(i = 0; i < NUMCORES; ++i) {
223                 corestatus[i] = 1;
224                 numsendobjs[i] = 0;
225                 numreceiveobjs[i] = 0;
226
227                 char corenumstr[3];
228                 int sourcelen = 0;
229                 if(i < 10) {
230                         corenumstr[0] = i + '0';
231                         corenumstr[1] = '\0';
232                         sourcelen = 1;
233                 } else if(i < 100) {
234                         corenumstr[1] = i %10 + '0';
235                         corenumstr[0] = (i / 10) + '0';
236                         corenumstr[2] = '\0';
237                         sourcelen = 2;
238                 } else {
239                         printf("Error: i >= 100\n");
240                         fflush(stdout);
241                         exit(-1);
242                 }
243                 char path[targetlen + sourcelen + 1];
244                 strcpy(path, pathhead);
245                 strncat(path, corenumstr, sourcelen);
246                 int oflags = O_RDONLY|O_CREAT|O_NONBLOCK;
247                 int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
248                 mq_unlink(path);
249                 mqd[i]= mq_open(path, oflags, omodes, NULL);
250                 if(mqd[i] == -1) {
251                         printf("[Main] mq_open %s fails: %d, error: %s\n", path, mqd[i], strerror(errno));
252                         exit(-1);
253                 } else {
254                         printf("[Main] mq_open %s returns: %d\n", path, mqd[i]);
255                 }
256         }
257
258         // create the key
259         pthread_key_create(&key, NULL);
260
261         // create the lock table and initialize its mutex
262         locktbl = allocateRuntimeHash(20);
263         int rc_locktbl = pthread_rwlock_init(&rwlock_tbl, NULL);
264         printf("[Main] initialize the rwlock for lock table: %d error: \n", rc_locktbl, strerror(rc_locktbl));
265
266         for(i = 0; i < NUMCORES; ++i) {
267                 thread_data_array[i].corenum = i;
268                 thread_data_array[i].argc = argc;
269                 thread_data_array[i].argv = argv;
270                 thread_data_array[i].numsendobjs = 0;
271                 thread_data_array[i].numreceiveobjs = 0;
272                 printf("[main] creating thread %d\n", i);
273                 rc[i] = pthread_create(&threads[i], NULL, run, (void *)&thread_data_array[i]);
274         if (rc[i]){
275                         printf("[main] ERROR; return code from pthread_create() is %d\n", rc[i]);
276                         fflush(stdout);
277                         exit(-1);
278                 }
279         }
280         
281         //pthread_exit(NULL);
282         while(true) {}
283 }
284
285 void run(void* arg) {
286         struct thread_data * my_tdata = (struct thread_data *)arg;
287         pthread_setspecific(key, (void *)my_tdata->corenum);
288         int argc = my_tdata->argc;
289         char** argv = my_tdata->argv;
290         printf("[run, %d] Thread %d runs: %x\n", my_tdata->corenum, my_tdata->corenum, (int)pthread_self());
291         fflush(stdout);
292
293 #endif
294
295 #ifdef BOEHM_GC
296   GC_init(); // Initialize the garbage collector
297 #endif
298 #ifdef CONSCHECK
299   initializemmap();
300 #endif
301 #ifndef RAW
302   processOptions();
303 #endif
304   initializeexithandler();
305 #ifdef RAW
306   raw_test_pass(0xee05);
307 #endif
308   /* Create table for failed tasks */
309 #ifdef RAW
310   if(corenum > NUMCORES - 1) {
311           failedtasks = NULL;
312           activetasks = NULL;
313           while(true) {
314                   receiveObject();
315           }
316   } else {
317           raw_test_pass(0xee06);
318 #endif
319   /*failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
320                                    (int (*)(void *,void *)) &comparetpd);*/
321           failedtasks = NULL;
322 #ifdef RAW
323   raw_test_pass(0xee07);
324 #endif
325   /* Create queue of active tasks */
326   activetasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
327                                    (int (*)(void *,void *)) &comparetpd);
328 #ifdef RAW
329   raw_test_pass(0xee08);
330 #endif
331   
332   /* Process task information */
333   processtasks();
334 #ifdef RAW
335   raw_test_pass(0xee09);
336 #endif
337
338   /* Create startup object */
339   createstartupobject(argc, argv);
340 #ifdef RAW
341   raw_test_pass(0xee0a);
342 #endif
343
344 #ifdef RAW
345   raw_test_pass(0xee0b);
346         
347   while(true) {
348 /*#ifndef INTERRUPT
349           while(receiveObject() != -1) {
350           }
351 #endif*/
352
353           // check if there are new active tasks can be executed
354           executetasks();
355
356 #ifndef INTERRUPT
357           while(receiveObject() != -1) {
358           }
359 #endif
360
361           raw_test_pass(0xee0c);
362
363           // check if there are some pending objects, if yes, enqueue them and executetasks again
364           tocontinue = false;
365           raw_test_pass(0xee0d);
366           while(!isEmpty(&objqueue)) {
367                   void * obj = NULL;
368 #ifdef INTERRUPT
369                   raw_user_interrupts_off();
370 #endif
371                   raw_test_pass(0xeee1);
372                   sendStall = false;
373                   tocontinue = true;
374                   objitem = getTail(&objqueue);
375                   //obj = objitem->objectptr;
376                   objInfo = (struct transObjInfo *)objitem->objectptr;
377                   obj = objInfo->objptr;
378                   raw_test_pass_reg((int)obj);
379                   // grab lock and flush the obj
380                   getreadlock_I(obj);
381                   while(!lockflag) {
382                           receiveObject();
383                   }
384                   grount = lockresult;
385                   raw_test_pass_reg(grount);
386
387                   lockresult = 0;
388                   lockobj = 0;
389                   lockflag = false;
390 #ifndef INTERRUPT
391                   reside = false;
392 #endif
393
394                   if(grount == 1) {
395                           int k = 0;
396                           // flush the obj
397                           for(k = 0; k < classsize[((struct ___Object___ *)obj)->type]; ++k) {
398                                   invalidateAddr(obj + k);
399                           }
400                           // enqueue the object
401                           for(k = 0; k < objInfo->length; ++k) {
402                                   int taskindex = objInfo->queues[2 * k];
403                                   int paramindex = objInfo->queues[2 * k + 1];
404                                   struct parameterwrapper ** queues = &(paramqueues[corenum][taskindex][paramindex]);
405                                   raw_test_pass_reg(taskindex);
406                                   raw_test_pass_reg(paramindex);
407                                   enqueueObject_I(obj, queues, 1);
408                           }
409                           removeItem(&objqueue, objitem);
410                           releasereadlock_I(obj);
411                           RUNFREE(objInfo->queues);
412                           RUNFREE(objInfo);
413                           /*enqueueObject_I(obj, NULL, 0);
414                           removeItem(&objqueue, objitem);
415                           releasereadlock_I(obj);*/
416                   } else {
417                           // can not get lock
418                           // put it at the end of the queue
419                           // and try to execute active tasks already enqueued first
420                           removeItem(&objqueue, objitem);
421                           addNewItem_I(&objqueue, objInfo);
422                           break;
423                   }
424 #ifdef INTERRUPT
425                   raw_user_interrupts_on();
426 #endif
427                   raw_test_pass(0xee0e);
428           }
429           
430           if(!tocontinue) {
431                   // check if stop
432                   if(STARTUPCORE == corenum) {
433                           if(isfirst) {
434                                   raw_test_pass(0xee0f);
435                                   isfirst = false;
436                           }
437 #ifdef INTERRUPT
438                           raw_user_interrupts_off();
439 #endif
440                           corestatus[corenum] = 0;
441                           numsendobjs[corenum] = self_numsendobjs;
442                           numreceiveobjs[corenum] = self_numreceiveobjs;
443                           // check the status of all cores
444                           allStall = true;
445                           raw_test_pass_reg(NUMCORES);
446                           for(i = 0; i < NUMCORES; ++i) {
447                                   raw_test_pass(0xe000 + corestatus[i]);
448                                   if(corestatus[i] != 0) {
449                                           allStall = false;
450                                           break;
451                                   }
452                           }
453                           if(allStall) {
454                                   // check if the sum of send objs and receive obj are the same
455                                   // yes->terminate
456                                   // no->go on executing
457                                   sumsendobj = 0;
458                                   for(i = 0; i < NUMCORES; ++i) {
459                                           sumsendobj += numsendobjs[i];
460                                           raw_test_pass(0xf000 + numsendobjs[i]);
461                                   }
462                                   for(i = 0; i < NUMCORES; ++i) {
463                                           sumsendobj -= numreceiveobjs[i];
464                                           raw_test_pass(0xf000 + numreceiveobjs[i]);
465                                   }
466                                   if(0 == sumsendobj) {
467                                           // terminate 
468                                           raw_test_pass(0xee10);
469                                           raw_test_done(1);     // All done.
470                                   }
471                           }
472 #ifdef INTERRUPT
473                           raw_user_interrupts_on();
474 #endif
475                   } else {
476                           if(!sendStall) {
477                                   raw_test_pass(0xee11);
478                                   if(isfirst) {
479                                           // wait for some time
480                                           int halt = 10000;
481                                           raw_test_pass(0xee12);
482                                           while(halt--){}
483                                           isfirst = false;
484                                           raw_test_pass(0xee13);
485                                   } else {
486                                         // send StallMsg to startup core
487                                         raw_test_pass(0xee14);
488                                         sendStall = transStallMsg(STARTUPCORE);
489                                         isfirst = true;
490                                   }
491                           } else {
492                                   isfirst = true;
493                                   raw_test_pass(0xee15);
494                           }
495                   }
496           }
497   }
498   }
499 #elif defined THREADSIMULATE
500   /* Start executing the tasks */
501   executetasks();
502
503   int i = 0;
504   // check if there are new objects coming
505   bool sendStall = false;
506
507   int numofcore = pthread_getspecific(key);
508   while(true) {
509           switch(receiveObject()) {
510                   case 0: {
511                                           printf("[run, %d] receive an object\n", numofcore);
512                                           sendStall = false;
513                                           // received an object
514                                           // check if there are new active tasks can be executed
515                                           executetasks();
516                                           break;
517                                   }
518                   case 1: {
519                                           //printf("[run, %d] no msg\n", numofcore);
520                                           // no msg received
521                                           if(STARTUPCORE == numofcore) {
522                                                   corestatus[numofcore] = 0;
523                                                   // check the status of all cores
524                                                   bool allStall = true;
525                                                   for(i = 0; i < NUMCORES; ++i) {
526                                                           if(corestatus[i] != 0) {
527                                                                   allStall = false;
528                                                                   break;
529                                                           }
530                                                   }
531                                                   if(allStall) {
532                                                           // check if the sum of send objs and receive obj are the same
533                                                           // yes->terminate
534                                                           // no->go on executing
535                                                           int sumsendobj = 0;
536                                                           for(i = 0; i < NUMCORES; ++i) {
537                                                                   sumsendobj += numsendobjs[i];
538                                                           }
539                                                           for(i = 0; i < NUMCORES; ++i) {
540                                                                   sumsendobj -= numreceiveobjs[i];
541                                                           }
542                                                           if(0 == sumsendobj) {
543                                                                   // terminate
544                                                                   
545                                                                   // release all locks
546                                                                   int rc_tbl = pthread_rwlock_wrlock(&rwlock_tbl);
547                                                                   printf("[run, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc_tbl, strerror(rc_tbl));
548                                                                   struct RuntimeIterator* it_lock = RuntimeHashcreateiterator(locktbl); 
549                                                                   while(0 != RunhasNext(it_lock)) {
550                                                                           int key = Runkey(it_lock);
551                                                                           pthread_rwlock_t* rwlock_obj = (pthread_rwlock_t*)Runnext(it_lock);
552                                                                           int rc_des = pthread_rwlock_destroy(rwlock_obj);
553                                                                           printf("[run, %d] destroy the rwlock for object: %d error: \n", numofcore, key, strerror(rc_des));
554                                                                           RUNFREE(rwlock_obj);
555                                                                   }
556                                                                   freeRuntimeHash(locktbl);
557                                                                   locktbl = NULL;
558                                                                   RUNFREE(it_lock);
559
560                                                                   // destroy all message queues
561                                                                   char * pathhead = "/msgqueue_";
562                                                                   int targetlen = strlen(pathhead);
563                                                                   for(i = 0; i < NUMCORES; ++i) {
564                                                                           char corenumstr[3];
565                                                                           int sourcelen = 0;
566                                                                           if(i < 10) {
567                                                                                   corenumstr[0] = i + '0';
568                                                                                   corenumstr[1] = '\0';
569                                                                                   sourcelen = 1;
570                                                                           } else if(i < 100) {
571                                                                                   corenumstr[1] = i %10 + '0';
572                                                                                   corenumstr[0] = (i / 10) + '0';
573                                                                                   corenumstr[2] = '\0';
574                                                                                   sourcelen = 2;
575                                                                           } else {
576                                                                                   printf("Error: i >= 100\n");  
577                                                                                   fflush(stdout);
578                                                                                   exit(-1);
579                                                                           }
580                                                                           char path[targetlen + sourcelen + 1];
581                                                                           strcpy(path, pathhead);
582                                                                           strncat(path, corenumstr, sourcelen);
583                                                                           mq_unlink(path);
584                                                                   }
585
586                                                                   printf("[run, %d] terminate!\n", numofcore);
587                                                                   fflush(stdout);
588                                                                   exit(0);
589                                                           }
590                                                   }
591                                           } else {
592                                                   if(!sendStall) {
593                                                           // send StallMsg to startup core
594                                                           sendStall = transStallMsg(STARTUPCORE);
595                                                   }
596                                           }
597                                           break;
598                                   }
599                   case 2: {
600                                           printf("[run, %d] receive a stall msg\n", numofcore);
601                                           // receive a Stall Msg, do nothing
602                                           assert(STARTUPCORE == numofcore); // only startup core can receive such msg
603                                           sendStall = false;
604                                           break;
605                                   }
606                  /* case 3: {
607                                           printf("[run, %d] receive a terminate msg\n", numofcore);
608                                           // receive a terminate Msg
609                                           assert(STARTUPCORE != corenum); // only non-startup core can receive such msg
610                                           mq_close(mqd[corenum]);
611                                           fflush(stdout);
612                                           exit(0);
613                                           break;
614                                   }*/
615                   default: {
616                                            printf("[run, %d] Error: invalid message type.\n", numofcore);
617                                            fflush(stdout);
618                                            exit(-1);
619                                            break;
620                                    }
621           }
622   }
623 #endif
624 }
625
626 void createstartupobject(int argc, char ** argv) {
627   int i;
628   
629   /* Allocate startup object     */
630 #ifdef PRECISE_GC
631   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
632   struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1); 
633 #else
634   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
635   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1); 
636 #endif
637   /* Build array of strings */
638   startupobject->___parameters___=stringarray;
639   for(i=1;i<argc;i++) {
640     int length=strlen(argv[i]);
641 #ifdef PRECISE_GC
642     struct ___String___ *newstring=NewString(NULL, argv[i],length);
643 #else
644     struct ___String___ *newstring=NewString(argv[i],length);
645 #endif
646     ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
647   }
648   
649   startupobject->isolate = 1;
650   startupobject->version = 0;
651
652   /* Set initialized flag for startup object */ 
653   flagorandinit(startupobject,1,0xFFFFFFFF);
654   enqueueObject(startupobject, NULL, 0);
655 #ifdef RAW
656   flushAll();
657 #endif
658 }
659
660 int hashCodetpd(struct taskparamdescriptor *ftd) {
661   int hash=(int)ftd->task;
662   int i;
663   for(i=0;i<ftd->numParameters;i++){ 
664     hash^=(int)ftd->parameterArray[i];
665   }
666   return hash;
667 }
668
669 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
670   int i;
671   if (ftd1->task!=ftd2->task)
672     return 0;
673   for(i=0;i<ftd1->numParameters;i++)
674     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
675       return 0;
676   return 1;
677 }
678
679 /* This function sets a tag. */
680 #ifdef PRECISE_GC
681 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
682 #else
683 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
684 #endif
685         struct ArrayObject * ao=NULL;
686   struct ___Object___ * tagptr=obj->___tags___;
687 #ifdef RAW
688   raw_test_pass(0xebb0);
689 #endif
690   if (tagptr==NULL) {
691 #ifdef RAW
692           raw_test_pass(0xebb1);
693 #endif
694     obj->___tags___=(struct ___Object___ *)tagd;
695   } else {
696     /* Have to check if it is already set */
697     if (tagptr->type==TAGTYPE) {
698       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
699 #ifdef RAW
700           raw_test_pass(0xebb2);
701 #endif
702       if (td==tagd) {
703 #ifdef RAW
704                   raw_test_pass(0xebb3);
705 #endif
706         return;
707           }
708 #ifdef PRECISE_GC
709       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
710       struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
711       obj=(struct ___Object___ *)ptrarray[2];
712       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
713       td=(struct ___TagDescriptor___ *) obj->___tags___;
714 #else
715 #ifdef RAW
716           raw_test_pass(0xebb4);
717 #endif
718       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
719 #endif
720 #ifdef RAW
721           raw_test_pass(0xebb5);
722 #endif
723       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
724       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
725       obj->___tags___=(struct ___Object___ *) ao;
726       ao->___cachedCode___=2;
727 #ifdef RAW
728           raw_test_pass(0xebb6);
729 #endif
730     } else {
731       /* Array Case */
732       int i;
733       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
734 #ifdef RAW
735           raw_test_pass(0xebb7);
736 #endif
737       for(i=0;i<ao->___cachedCode___;i++) {
738         struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
739 #ifdef RAW
740                 raw_test_pass(0xebb8);
741 #endif
742         if (td==tagd) {
743 #ifdef RAW
744                 raw_test_pass(0xebb9);
745 #endif
746           return;
747         }
748       }
749       if (ao->___cachedCode___<ao->___length___) {
750 #ifdef RAW
751                 raw_test_pass(0xebba);
752 #endif
753         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
754         ao->___cachedCode___++;
755 #ifdef RAW
756         raw_test_pass(0xebbb);
757 #endif
758       } else {
759 #ifdef PRECISE_GC
760         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
761         struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
762         obj=(struct ___Object___ *)ptrarray[2];
763         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
764         ao=(struct ArrayObject *)obj->___tags___;
765 #else
766         struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
767 #endif
768 #ifdef RAW
769                 raw_test_pass(0xebbc);
770 #endif
771         aonew->___cachedCode___=ao->___length___+1;
772         for(i=0;i<ao->___length___;i++) {
773 #ifdef RAW
774                 raw_test_pass(0xebbd);
775 #endif
776           ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
777         }
778 #ifdef RAW
779                 raw_test_pass(0xebbe);
780 #endif
781         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
782 #ifdef RAW
783         raw_test_pass(0xebbf);
784 #endif
785       }
786     }
787   }
788
789   {
790     struct ___Object___ * tagset=tagd->flagptr;
791 #ifdef RAW
792         raw_test_pass(0xb008);
793 #endif
794     if(tagset==NULL) {
795 #ifdef RAW
796                 raw_test_pass(0xb009);
797 #endif
798       tagd->flagptr=obj;
799     } else if (tagset->type!=OBJECTARRAYTYPE) {
800 #ifdef PRECISE_GC
801       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
802       struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
803       obj=(struct ___Object___ *)ptrarray[2];
804       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
805 #else
806       struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
807 #endif
808       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
809       ARRAYSET(ao, struct ___Object___ *, 1, obj);
810       ao->___cachedCode___=2;
811       tagd->flagptr=(struct ___Object___ *)ao;
812 #ifdef RAW
813           raw_test_pass(0xb00a);
814 #endif
815     } else {
816       struct ArrayObject *ao=(struct ArrayObject *) tagset;
817       if (ao->___cachedCode___<ao->___length___) {
818 #ifdef RAW
819                   raw_test_pass(0xb00b);
820 #endif
821         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
822       } else {
823         int i;
824 #ifdef PRECISE_GC
825         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
826         struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
827         obj=(struct ___Object___ *)ptrarray[2];
828         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
829         ao=(struct ArrayObject *)tagd->flagptr;
830 #else
831         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
832 #endif
833         aonew->___cachedCode___=ao->___cachedCode___+1;
834         for(i=0;i<ao->___length___;i++) {
835           ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
836         }
837         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
838         tagd->flagptr=(struct ___Object___ *) aonew;
839 #ifdef RAW
840         raw_test_pass(0xb00c);
841 #endif
842       }
843     }
844   }
845 }
846
847 /* This function clears a tag. */
848 #ifdef PRECISE_GC
849 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
850 #else
851 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
852 #endif
853   /* We'll assume that tag is alway there.
854      Need to statically check for this of course. */
855   struct ___Object___ * tagptr=obj->___tags___;
856
857   if (tagptr->type==TAGTYPE) {
858     if ((struct ___TagDescriptor___ *)tagptr==tagd)
859       obj->___tags___=NULL;
860     else
861 #ifndef RAW
862       printf("ERROR 1 in tagclear\n");
863 #endif
864         ;
865   } else {
866     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
867     int i;
868     for(i=0;i<ao->___cachedCode___;i++) {
869       struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
870       if (td==tagd) {
871         ao->___cachedCode___--;
872         if (i<ao->___cachedCode___)
873           ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
874         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
875         if (ao->___cachedCode___==0)
876           obj->___tags___=NULL;
877         goto PROCESSCLEAR;
878       }
879     }
880 #ifndef RAW
881     printf("ERROR 2 in tagclear\n");
882 #endif
883         ;
884   }
885  PROCESSCLEAR:
886   {
887     struct ___Object___ *tagset=tagd->flagptr;
888     if (tagset->type!=OBJECTARRAYTYPE) {
889       if (tagset==obj)
890         tagd->flagptr=NULL;
891       else
892 #ifndef RAW
893         printf("ERROR 3 in tagclear\n");
894 #endif
895           ;
896     } else {
897       struct ArrayObject *ao=(struct ArrayObject *) tagset;
898       int i;
899       for(i=0;i<ao->___cachedCode___;i++) {
900         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
901         if (tobj==obj) {
902           ao->___cachedCode___--;
903           if (i<ao->___cachedCode___)
904             ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
905           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
906           if (ao->___cachedCode___==0)
907             tagd->flagptr=NULL;
908           goto ENDCLEAR;
909         }
910       }
911 #ifndef RAW
912       printf("ERROR 4 in tagclear\n");
913 #endif
914     }
915   }
916  ENDCLEAR:
917   return;
918 }
919  
920 /* This function allocates a new tag. */
921 #ifdef PRECISE_GC
922 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
923   struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
924 #else
925 struct ___TagDescriptor___ * allocate_tag(int index) {
926   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
927 #endif
928   v->type=TAGTYPE;
929   v->flag=index;
930   return v;
931
932
933
934
935 /* This function updates the flag for object ptr.  It or's the flag
936    with the or mask and and's it with the andmask. */
937
938 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
939  
940  int flagcomp(const int *val1, const int *val2) {
941    return (*val1)-(*val2);
942  } 
943
944 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
945     {
946       int oldflag=((int *)ptr)[1];
947       int flag=ormask|oldflag;
948       flag&=andmask;
949 #ifdef RAW
950           raw_test_pass(0xaa000000 + oldflag);
951           raw_test_pass(0xaa000000 + flag);
952 #endif
953           flagbody(ptr, flag, queues, length, false);
954     }
955 }
956  
957 bool intflagorand(void * ptr, int ormask, int andmask) {
958     {
959       int oldflag=((int *)ptr)[1];
960       int flag=ormask|oldflag;
961       flag&=andmask;
962       if (flag==oldflag) /* Don't do anything */
963         return false;
964       else {
965                  flagbody(ptr, flag, NULL, 0, false);
966                  return true;
967           }
968     }
969 }
970
971 void flagorandinit(void * ptr, int ormask, int andmask) {
972   int oldflag=((int *)ptr)[1];
973   int flag=ormask|oldflag;
974   flag&=andmask;
975 #ifdef RAW
976           raw_test_pass(0xaa100000 + oldflag);
977           raw_test_pass(0xaa100000 + flag);
978 #endif
979   flagbody(ptr,flag,NULL,0,true);
980 }
981
982 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
983   struct parameterwrapper * flagptr = NULL;
984   int i = 0;
985   struct parameterwrapper ** queues = vqueues;
986   int length = vlength;
987   int next;
988   int UNUSED, UNUSED2;
989   int * enterflags = NULL;
990   if((!isnew) && (queues == NULL)) {
991 #ifdef THREADSIMULATE
992           int numofcore = pthread_getspecific(key);
993           queues = objectqueues[numofcore][ptr->type];
994           length = numqueues[numofcore][ptr->type];
995 #else
996 #ifdef RAW
997           if(corenum < NUMCORES) {
998 #endif
999           queues = objectqueues[corenum][ptr->type];
1000           length = numqueues[corenum][ptr->type];
1001 #ifdef RAW
1002           } else {
1003                   return;
1004           }
1005 #endif
1006 #endif
1007   }
1008   ptr->flag=flag;
1009 #ifdef RAW
1010   raw_test_pass(0xbb000000 + ptr->flag);
1011 #endif
1012   
1013   /*Remove object from all queues */
1014   for(i = 0; i < length; ++i) {
1015           flagptr = queues[i];
1016     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
1017     ObjectHashremove(flagptr->objectset, (int)ptr);
1018     if (enterflags!=NULL)
1019       RUNFREE(enterflags);
1020   }
1021  }
1022
1023  void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1024    struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1025   
1026   {
1027     struct QueueItem *tmpptr;
1028         struct parameterwrapper * parameter=NULL;
1029         int j;
1030         int i;
1031     struct parameterwrapper * prevptr=NULL;
1032     struct ___Object___ *tagptr=NULL;
1033         struct parameterwrapper ** queues = vqueues;
1034         int length = vlength;
1035 #ifdef RAW
1036         if(corenum > NUMCORES - 1) {
1037                 return;
1038         }
1039 #endif
1040         if(queues == NULL) {
1041 #ifdef THREADSIMULATE
1042                 int numofcore = pthread_getspecific(key);
1043                 queues = objectqueues[numofcore][ptr->type];
1044                 length = numqueues[numofcore][ptr->type];
1045 #else
1046                 queues = objectqueues[corenum][ptr->type];
1047                 length = numqueues[corenum][ptr->type];
1048 #endif
1049         }
1050     tagptr=ptr->___tags___;
1051     
1052     /* Outer loop iterates through all parameter queues an object of
1053        this type could be in.  */
1054     for(j = 0; j < length; ++j) {
1055                 parameter = queues[j];
1056       /* Check tags */
1057       if (parameter->numbertags>0) {
1058         if (tagptr==NULL)
1059           goto nextloop;//that means the object has no tag but that param needs tag
1060         else if(tagptr->type==TAGTYPE) {//one tag
1061           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1062           for(i=0;i<parameter->numbertags;i++) {
1063             //slotid is parameter->tagarray[2*i];
1064             int tagid=parameter->tagarray[2*i+1];
1065             if (tagid!=tagptr->flag)
1066               goto nextloop; /*We don't have this tag */          
1067            }
1068         } else {//multiple tags
1069           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1070           for(i=0;i<parameter->numbertags;i++) {
1071             //slotid is parameter->tagarray[2*i];
1072             int tagid=parameter->tagarray[2*i+1];
1073             int j;
1074             for(j=0;j<ao->___cachedCode___;j++) {
1075               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1076                 goto foundtag;
1077             }
1078             goto nextloop;
1079           foundtag:
1080             ;
1081           }
1082         }
1083       }
1084       
1085       /* Check flags */
1086       for(i=0;i<parameter->numberofterms;i++) {
1087         int andmask=parameter->intarray[i*2];
1088         int checkmask=parameter->intarray[i*2+1];
1089         if ((ptr->flag&andmask)==checkmask) {
1090 #ifdef RAW
1091                 raw_test_pass(0xcc000000 + andmask);
1092                 raw_test_pass_reg((int)ptr);
1093                 raw_test_pass(0xcc000000 + ptr->flag);
1094                 raw_test_pass(0xcc000000 + checkmask);
1095 #endif
1096           enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1097           prevptr=parameter;
1098           break;
1099         }
1100       }
1101     nextloop:
1102           ;
1103     }
1104   }
1105 }
1106
1107 #ifdef RAW
1108 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
1109    struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1110   
1111   {
1112     struct QueueItem *tmpptr;
1113         struct parameterwrapper * parameter=NULL;
1114         int j;
1115         int i;
1116     struct parameterwrapper * prevptr=NULL;
1117     struct ___Object___ *tagptr=NULL;
1118         struct parameterwrapper ** queues = vqueues;
1119         int length = vlength;
1120 #ifdef RAW
1121         if(corenum > NUMCORES - 1) {
1122                 return;
1123         }
1124 #endif
1125         if(queues == NULL) {
1126 #ifdef THREADSIMULATE
1127                 int numofcore = pthread_getspecific(key);
1128                 queues = objectqueues[numofcore][ptr->type];
1129                 length = numqueues[numofcore][ptr->type];
1130 #else
1131                 queues = objectqueues[corenum][ptr->type];
1132                 length = numqueues[corenum][ptr->type];
1133 #endif
1134         }
1135 #ifdef RAW
1136         raw_test_pass(0xeaa1);
1137         raw_test_pass_reg(queues);
1138         raw_test_pass_reg(length);
1139 #endif
1140     tagptr=ptr->___tags___;
1141     
1142     /* Outer loop iterates through all parameter queues an object of
1143        this type could be in.  */
1144     for(j = 0; j < length; ++j) {
1145                 parameter = queues[j];
1146       /* Check tags */
1147       if (parameter->numbertags>0) {
1148 #ifdef RAW
1149         raw_test_pass(0xeaa2);
1150         raw_test_pass_reg(tagptr);
1151 #endif
1152         if (tagptr==NULL)
1153           goto nextloop;//that means the object has no tag but that param needs tag
1154         else if(tagptr->type==TAGTYPE) {//one tag
1155           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1156 #ifdef RAW
1157         raw_test_pass(0xeaa3);
1158 #endif
1159           for(i=0;i<parameter->numbertags;i++) {
1160             //slotid is parameter->tagarray[2*i];
1161             int tagid=parameter->tagarray[2*i+1];
1162             if (tagid!=tagptr->flag) {
1163 #ifdef RAW
1164         raw_test_pass(0xeaa4);
1165 #endif
1166               goto nextloop; /*We don't have this tag */
1167                 }
1168            }
1169         } else {//multiple tags
1170           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1171 #ifdef RAW
1172         raw_test_pass(0xeaa5);
1173 #endif
1174           for(i=0;i<parameter->numbertags;i++) {
1175             //slotid is parameter->tagarray[2*i];
1176             int tagid=parameter->tagarray[2*i+1];
1177             int j;
1178             for(j=0;j<ao->___cachedCode___;j++) {
1179               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag) {
1180                 goto foundtag;
1181                   }
1182             }
1183 #ifdef RAW
1184         raw_test_pass(0xeaa6);
1185 #endif
1186             goto nextloop;
1187           foundtag:
1188             ;
1189           }
1190         }
1191       }
1192       
1193       /* Check flags */
1194       for(i=0;i<parameter->numberofterms;i++) {
1195         int andmask=parameter->intarray[i*2];
1196         int checkmask=parameter->intarray[i*2+1];
1197 #ifdef RAW
1198         raw_test_pass(0xeaa7);
1199         raw_test_pass(0xcc000000 + andmask);
1200         raw_test_pass_reg(ptr);
1201         raw_test_pass(0xcc000000 + ptr->flag);
1202         raw_test_pass(0xcc000000 + checkmask);
1203 #endif
1204         if ((ptr->flag&andmask)==checkmask) {
1205 #ifdef RAW
1206         raw_test_pass(0xeaa8);
1207 #endif
1208           enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1209           prevptr=parameter;
1210           break;
1211         }
1212       }
1213     nextloop:
1214           ;
1215     }
1216   }
1217 }
1218
1219 // helper function to compute the coordinates of a core from the core number
1220 void calCoords(int core_num, int* coordY, int* coordX) {
1221         *coordX = core_num % 4;
1222         *coordY = core_num / 4;
1223 }
1224 #endif
1225
1226 /* Message format for RAW version:
1227  *      type + Msgbody 
1228  * type: 0 -- transfer object
1229  *       1 -- transfer stall msg
1230  *       2 -- lock request
1231  *       3 -- lock grount
1232  *       4 -- lock deny
1233  *       5 -- lock release
1234  *
1235  * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
1236  * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
1237  * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
1238  *          3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
1239  *          lock type: 0 -- read; 1 -- write
1240  */
1241
1242 // transfer an object to targetcore
1243 // format: object
1244 void transferObject(struct transObjInfo * transObj) {
1245         void * obj = transObj->objptr;
1246         int type=((int *)obj)[0];
1247     int size=classsize[type];
1248         int targetcore = transObj->targetcore;
1249         //assert(type < NUMCLASSES); // can only transfer normal object
1250
1251 #ifdef RAW
1252         unsigned msgHdr;
1253         int self_y, self_x, target_y, target_x;
1254         //int isshared = 0;
1255         // for 32 bit machine, the size of fixed part is always 3 words
1256         //int msgsize = sizeof(int) * 2 + sizeof(void *);
1257         int msgsize = 3 + transObj->length * 2;
1258         int i = 0;
1259
1260         struct ___Object___ * newobj = (struct ___Object___ *)obj;
1261         /*if(0 == newobj->isolate) {
1262                 isshared = 1;
1263         }*/
1264
1265         calCoords(corenum, &self_y, &self_x);
1266         calCoords(targetcore, &target_y, &target_x);
1267         // Build the message header
1268     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
1269                                            self_y, self_x,
1270                                                            target_y, target_x);
1271         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
1272         raw_test_pass(0xbbbb);
1273         raw_test_pass(0xb000 + targetcore); // targetcore
1274     gdn_send(0);
1275     raw_test_pass(0);
1276         gdn_send(msgsize);
1277         raw_test_pass_reg(msgsize);
1278     gdn_send(obj);
1279         raw_test_pass_reg(obj);
1280         //gdn_send(isshared);
1281         //raw_test_pass_reg(isshared);
1282         for(i = 0; i < transObj->length; ++i) {
1283                 int taskindex = transObj->queues[2*i];
1284                 int paramindex = transObj->queues[2*i+1];
1285                 gdn_send(taskindex);
1286                 raw_test_pass_reg(taskindex);
1287                 gdn_send(paramindex);
1288                 raw_test_pass_reg(paramindex);
1289         }
1290         raw_test_pass(0xffff);
1291         ++(self_numsendobjs);
1292 #elif defined THREADSIMULATE
1293         int numofcore = pthread_getspecific(key);
1294
1295         // use POSIX message queue to transfer objects between cores
1296         mqd_t mqdnum;
1297         char corenumstr[3];
1298         int sourcelen = 0;
1299         if(targetcore < 10) {
1300                 corenumstr[0] = targetcore + '0';
1301                 corenumstr[1] = '\0';
1302                 sourcelen = 1;
1303         } else if(targetcore < 100) {
1304                 corenumstr[1] = targetcore % 10 + '0';
1305                 corenumstr[0] = (targetcore / 10) + '0';
1306                 corenumstr[2] = '\0';
1307                 sourcelen = 2;
1308         } else {
1309                 printf("Error: targetcore >= 100\n");
1310                 fflush(stdout);
1311                 exit(-1);
1312         }
1313         char * pathhead = "/msgqueue_";
1314         int targetlen = strlen(pathhead);
1315         char path[targetlen + sourcelen + 1];
1316         strcpy(path, pathhead);
1317         strncat(path, corenumstr, sourcelen);
1318         int oflags = O_WRONLY|O_NONBLOCK;
1319         int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1320         mqdnum = mq_open(path, oflags, omodes, NULL);
1321         if(mqdnum==-1) {
1322                 printf("[transferObject, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1323                 fflush(stdout);
1324                 exit(-1);
1325         }
1326         /*struct ___Object___ * newobj = (struct ___Object___ *)obj;
1327         if(0 == newobj->isolate) {
1328                 newobj = RUNMALLOC(size);
1329                 memcpy(newobj, obj, size);
1330                 newobj->original=obj;
1331         }*/
1332         struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
1333         memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
1334         int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
1335         memcpy(tmpqueue, tmptransObj->queues, sizeof(int)*2*tmptransObj->length);
1336         tmptransObj->queues = tmpqueue;
1337         struct ___Object___ * newobj = RUNMALLOC(sizeof(struct ___Object___));
1338         newobj->type = ((struct ___Object___ *)obj)->type;
1339         newobj->original = (struct ___Object___ *)tmptransObj;
1340         int ret;
1341         do {
1342                 ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1343                 if(ret != 0) {
1344                         printf("[transferObject, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1345                 }
1346         }while(ret!=0);
1347         RUNFREE(newobj);
1348         if(numofcore == STARTUPCORE) {
1349                 ++numsendobjs[numofcore];
1350         } else {
1351                 ++(thread_data_array[numofcore].numsendobjs);
1352         }
1353         printf("[transferObject, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1354 #endif
1355 }
1356
1357 // send terminate message to targetcore
1358 // format: -1
1359 bool transStallMsg(int targetcore) {
1360 #ifdef RAW
1361         unsigned msgHdr;
1362         int self_y, self_x, target_y, target_x;
1363         // for 32 bit machine, the size is always 4 words
1364         //int msgsize = sizeof(int) * 4;
1365         int msgsize = 4;
1366
1367         calCoords(corenum, &self_y, &self_x);
1368         calCoords(targetcore, &target_y, &target_x);
1369         // Build the message header
1370     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
1371                                            self_y, self_x,
1372                                                            target_y, target_x);
1373         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
1374         raw_test_pass(0xbbbb);
1375         raw_test_pass(0xb000 + targetcore); // targetcore
1376     gdn_send(1);
1377     raw_test_pass(1);
1378     gdn_send(corenum);
1379         raw_test_pass_reg(corenum);
1380         gdn_send(self_numsendobjs);
1381     raw_test_pass_reg(self_numsendobjs);
1382     gdn_send(self_numreceiveobjs);
1383         raw_test_pass_reg(self_numreceiveobjs);
1384         raw_test_pass(0xffff);
1385         return true;
1386 #elif defined THREADSIMULATE
1387         struct ___Object___ *newobj = RUNMALLOC(sizeof(struct ___Object___));
1388         // use the first four int field to hold msgtype/corenum/sendobj/receiveobj
1389         newobj->type = -1;
1390         int numofcore = pthread_getspecific(key);
1391         newobj->flag = numofcore;
1392         newobj->___cachedHash___ = thread_data_array[numofcore].numsendobjs;
1393         newobj->___cachedCode___ = thread_data_array[numofcore].numreceiveobjs;
1394
1395         // use POSIX message queue to send stall msg to startup core
1396         assert(targetcore == STARTUPCORE);
1397         mqd_t mqdnum;
1398         char corenumstr[3];
1399         int sourcelen = 0;
1400         if(targetcore < 10) {
1401                 corenumstr[0] = targetcore + '0';
1402                 corenumstr[1] = '\0';
1403                 sourcelen = 1;
1404         } else if(targetcore < 100) {
1405                 corenumstr[1] = targetcore % 10 + '0';
1406                 corenumstr[0] = (targetcore / 10) + '0';
1407                 corenumstr[2] = '\0';
1408                 sourcelen = 2;
1409         } else {
1410                 printf("Error: targetcore >= 100\n");
1411                 fflush(stdout);
1412                 exit(-1);
1413         }
1414         char * pathhead = "/msgqueue_";
1415         int targetlen = strlen(pathhead);
1416         char path[targetlen + sourcelen + 1];
1417         strcpy(path, pathhead);
1418         strncat(path, corenumstr, sourcelen);
1419         int oflags = O_WRONLY|O_NONBLOCK;
1420         int omodes = S_IRWXU|S_IRWXG|S_IRWXO;
1421         mqdnum = mq_open(path, oflags, omodes, NULL);
1422         if(mqdnum==-1) {
1423                 printf("[transStallMsg, %d] mq_open %s fail: %d, error: %s\n", numofcore, path, mqdnum, strerror(errno));
1424                 fflush(stdout);
1425                 exit(-1);
1426         }
1427         int ret;
1428         ret=mq_send(mqdnum, (void *)newobj, sizeof(struct ___Object___), 0); // send the object into the queue
1429         if(ret != 0) {
1430                 printf("[transStallMsg, %d] mq_send to %s returned: %d, error: %s\n", numofcore, path, ret, strerror(errno));
1431                 RUNFREE(newobj);
1432                 return false;
1433         } else {
1434                 printf("[transStallMsg, %d] mq_send to %s returned: $%x\n", numofcore, path, ret);
1435                 printf("<transStallMsg> to %s index: %d, sendobjs: %d, receiveobjs: %d\n", path, newobj->flag, newobj->___cachedHash___, newobj->___cachedCode___);
1436                 RUNFREE(newobj);
1437                 return true;
1438         }
1439 #endif
1440 }
1441
1442 // receive object transferred from other cores
1443 // or the terminate message from other cores
1444 // NOTICE: following format is for threadsimulate version only
1445 //         RAW version please see previous description
1446 // format: type + object
1447 // type: -1--stall msg
1448 //      !-1--object
1449 // return value: 0--received an object
1450 //               1--received nothing
1451 //               2--received a Stall Msg
1452 //               3--received a lock Msg
1453 //               RAW version: -1 -- received nothing
1454 //                            otherwise -- received msg type
1455 int receiveObject() {
1456 #ifdef RAW
1457         bool deny = false;
1458         unsigned msgHdr;
1459         int self_y, self_x, target_y, target_x;
1460         int targetcore = 0;
1461         if(gdn_input_avail() == 0) {
1462                 if(corenum < NUMCORES) {
1463                         raw_test_pass(0xd001);
1464                 }
1465                 return -1;
1466         }
1467         raw_test_pass(0xcccc);
1468         while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
1469                 msgdata[msgdataindex] = gdn_receive();
1470                 if(msgdataindex == 0) {
1471                         if(msgdata[0] > 2) {
1472                                 msglength = 3;
1473                         } else if(msgdata[0] > 0) {
1474                                 msglength = 4;
1475                         }
1476                 } else if((msgdataindex == 1) && (msgdata[0] == 0)) {
1477                         msglength = msgdata[msgdataindex];
1478                 }
1479                 raw_test_pass_reg(msgdata[msgdataindex]);
1480                 msgdataindex++;
1481
1482                 /*if(msgdataindex == 0) {
1483                         // type
1484                         msgtype = gdn_receive();
1485                         if(msgtype > 2) {
1486                                 msglength = 3;
1487                         } else {
1488                                 msglength = 4;
1489                         }
1490                         if(msgtype != 0) {
1491                                 msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
1492                                 msgdata[msgdataindex] = msgtype;
1493                         }
1494                         raw_test_pass_reg(msgtype);
1495                 } else if((msgdataindex == 1) && (msgtype == 0)) {
1496                         // object transfer msg
1497                         msglength = gdn_receive();
1498                         msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
1499                         msgdata[0] = msgtype;
1500                         msgdata[msgdataindex] = msglength;
1501                         raw_test_pass_reg(msgdata[msgdataindex]);
1502                 } else {
1503                         msgdata[msgdataindex] = gdn_receive();
1504                         raw_test_pass_reg(msgdata[msgdataindex]);
1505                 }
1506                 msgdataindex++;*/
1507         }
1508         raw_test_pass(0xffff);
1509         if(msgdataindex == msglength) {
1510                 // received a whole msg
1511                 int type, data1, data2; // will receive at least 3 words including type
1512                 type = msgdata[0];
1513                 data1 = msgdata[1];
1514                 data2 = msgdata[2];
1515                 switch(type) {
1516                         case 0: {
1517                                                 // receive a object transfer msg
1518                                                 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
1519                                                 int k = 0;
1520                                                 if(corenum > NUMCORES - 1) {
1521                                                         raw_test_done(0xa00a);
1522                                                 }
1523                                                 // store the object and its corresponding queue info, enqueue it later
1524                                                 transObj->objptr = (void *)data2; // data1 is now size of the msg
1525                                                 transObj->length = (msglength - 3) / 2;
1526                                                 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1527                                                 for(k = 0; k < transObj->length; ++k) {
1528                                                         transObj->queues[2*k] = msgdata[3+2*k];
1529                                                         raw_test_pass_reg(transObj->queues[2*k]);
1530                                                         transObj->queues[2*k+1] = msgdata[3+2*k+1];
1531                                                         raw_test_pass_reg(transObj->queues[2*k+1]);
1532                                                 }
1533                                                 //memcpy(transObj->queues, msgdata[3], sizeof(int)*(msglength - 3));
1534                                                 addNewItem_I(&objqueue, (void *)transObj);
1535                                                 ++(self_numreceiveobjs);
1536                                                 raw_test_pass(0xe881);
1537                                                 /*
1538                                                 addNewItem_I(&objqueue, (void *)data2);
1539                                                 ++(self_numreceiveobjs);
1540                                                 raw_test_pass(0xe881);*/
1541                                                 break;
1542                                         } 
1543                         case 1: {
1544                                                 // receive a stall msg
1545                                                 if(corenum != STARTUPCORE) {
1546                                                         // non startup core can not receive stall msg
1547                                                         // return -1
1548                                                         raw_test_done(0xa001);
1549                                                 }
1550                                                 if(data1 < NUMCORES) {
1551                                                         raw_test_pass(0xe882);
1552                                                         corestatus[data1] = 0;
1553                                                         numsendobjs[data1] = data2;
1554                                                         numreceiveobjs[data1] = msgdata[3];
1555                                                 }
1556                                                 break;
1557                                         } 
1558                         case 2: {
1559                                                 // receive lock request msg
1560                                                 // for 32 bit machine, the size is always 3 words                       
1561                                                 //int msgsize = sizeof(int) * 3;
1562                                                 int msgsize = 3;
1563                                                 // lock request msg, handle it right now
1564                                                 // check to see if there is a lock exist in locktbl for the required obj
1565                                                 int data3 = msgdata[3];
1566                                                 deny = false;
1567                                                 if(!RuntimeHashcontainskey(locktbl, data2)) {
1568                                                         // no locks for this object
1569                                                         // first time to operate on this shared object
1570                                                         // create a lock for it
1571                                                         // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
1572                                                         raw_test_pass(0xe883);
1573                                                         if(data1 == 0) {
1574                                                                 RuntimeHashadd_I(locktbl, data2, 1);
1575                                                         } else {
1576                                                                 RuntimeHashadd_I(locktbl, data2, -1);
1577                                                         }
1578                                                 } else {
1579                                                         int rwlock_obj = 0;
1580                                                         raw_test_pass(0xe884);
1581                                                         RuntimeHashget(locktbl, data2, &rwlock_obj);
1582                                                         raw_test_pass_reg(rwlock_obj);
1583                                                         if(0 == rwlock_obj) {
1584                                                                 if(data1 == 0) {
1585                                                                         rwlock_obj = 1;
1586                                                                 } else {
1587                                                                         rwlock_obj = -1;
1588                                                                 }
1589                                                                 RuntimeHashremovekey(locktbl, data2);
1590                                                                 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1591                                                         } else if((rwlock_obj > 0) && (data1 == 0)) {
1592                                                                 // read lock request and there are only read locks
1593                                                                 rwlock_obj++;
1594                                                                 RuntimeHashremovekey(locktbl, data2);
1595                                                                 RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1596                                                         } else {
1597                                                                 deny = true;
1598                                                         }       
1599                                                         raw_test_pass_reg(rwlock_obj);
1600                                                 }
1601                                                 targetcore = data3;
1602                                                 calCoords(corenum, &self_y, &self_x);
1603                                                 calCoords(targetcore, &target_y, &target_x);
1604                                                 // Build the message header
1605                                                 msgHdr = construct_dyn_hdr(0, msgsize, 0,               // msgsize word sent.
1606                                                                                    self_y, self_x,
1607                                                                                                    target_y, target_x);
1608                                                 gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
1609                                                 raw_test_pass(0xbbbb);
1610                                                 raw_test_pass(0xb000 + targetcore); // targetcore
1611                                                 if(deny == true) {
1612                                                         // deny the lock request
1613                                                         gdn_send(4); // lock request
1614                                                         raw_test_pass(4);
1615                                                 } else {
1616                                                         // grount the lock request              
1617                                                         gdn_send(3); // lock request
1618                                                         raw_test_pass(3);
1619                                                 }
1620                                                 gdn_send(data1); // lock type
1621                                                 raw_test_pass_reg(data1);
1622                                                 gdn_send(data2); // lock target
1623                                                 raw_test_pass_reg(data2);
1624                                                 raw_test_pass(0xffff);
1625                                                 break;
1626                                         }
1627                         case 3: {
1628                                                 // receive lock grount msg
1629                                                 if(corenum > NUMCORES - 1) {
1630                                                         raw_test_done(0xa00b);
1631                                                 }       
1632                                                 if(lockobj == data2) {
1633                                                         lockresult = 1;
1634                                                         lockflag = true;
1635 #ifndef INTERRUPT
1636                                                         reside = false;
1637 #endif
1638                                                 } else {
1639                                                         // conflicts on lockresults
1640                                                 raw_test_done(0xa002);
1641                                                 }
1642                                                 break;
1643                                         }
1644                         case 4: {
1645                                                 // receive lock grount/deny msg
1646                                                 if(corenum > NUMCORES - 1) {
1647                                                         raw_test_done(0xa00c);
1648                                                 }
1649                                                 if(lockobj == data2) {
1650                                                         lockresult = 0;
1651                                                         lockflag = true;
1652 #ifndef INTERRUPT
1653                                                         reside = false;
1654 #endif
1655                                                 } else {
1656                                                         // conflicts on lockresults
1657                                                         raw_test_done(0xa003);
1658                                                 }       
1659                                                 break;
1660                                         }
1661                         case 5: {
1662                                                 // receive lock release msg
1663                                                 if(!RuntimeHashcontainskey(locktbl, data2)) {
1664                                                         // no locks for this object, something is wrong
1665                                                         raw_test_done(0xa004);
1666                                                 } else {
1667                                                         int rwlock_obj = 0;
1668                                                         RuntimeHashget(locktbl, data2, &rwlock_obj);
1669                                                         raw_test_pass(0xe885);
1670                                                         raw_test_pass_reg(rwlock_obj);
1671                                                         if(data1 == 0) {
1672                                                                 rwlock_obj--;
1673                                                         } else {
1674                                                                 rwlock_obj++;
1675                                                         }
1676                                                         RuntimeHashremovekey(locktbl, data2);
1677                                                         RuntimeHashadd_I(locktbl, data2, rwlock_obj);
1678                                                         raw_test_pass_reg(rwlock_obj);
1679                                                 }
1680                                                 break;
1681                                         }
1682                         default:
1683                                         break;
1684                 }
1685                 //RUNFREE(msgdata);
1686                 //msgdata = NULL;
1687                 for(msgdataindex--;msgdataindex > 0; --msgdataindex) {
1688                         msgdata[msgdataindex] = -1;
1689                 }
1690                 msgtype = -1;
1691                 //msgdataindex = 0;
1692                 msglength = 30;
1693                 raw_test_pass(0xe886);
1694                 return type;
1695         } else {
1696                 // not a whole msg
1697                 raw_test_pass(0xe887);
1698                 return -2;
1699         }
1700 #elif defined THREADSIMULATE
1701         int numofcore = pthread_getspecific(key);
1702         // use POSIX message queue to transfer object
1703         int msglen = 0;
1704         struct mq_attr mqattr;
1705         mq_getattr(mqd[numofcore], &mqattr);
1706         void * msgptr =RUNMALLOC(mqattr.mq_msgsize);
1707         msglen=mq_receive(mqd[numofcore], msgptr, mqattr.mq_msgsize, NULL); // receive the object into the queue
1708         if(-1 == msglen) {
1709                 // no msg
1710                 free(msgptr);
1711                 return 1;
1712         }
1713         //printf("msg: %s\n",msgptr);
1714         if(((int*)msgptr)[0] == -1) {
1715                 // StallMsg
1716                 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
1717                 int index = tmpptr->flag;
1718                 corestatus[index] = 0;
1719                 numsendobjs[index] = tmpptr->___cachedHash___;
1720                 numreceiveobjs[index] = tmpptr->___cachedCode___;
1721                 printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
1722                 free(msgptr);
1723                 return 2;
1724         } /*else if(((int*)msgptr)[0] == -2) {
1725                 // terminate msg
1726                 return 3;
1727         } */else {
1728                 // an object
1729                 if(numofcore == STARTUPCORE) {
1730                         ++(numreceiveobjs[numofcore]);
1731                 } else {
1732                         ++(thread_data_array[numofcore].numreceiveobjs);
1733                 }
1734                 struct ___Object___ * tmpptr = (struct ___Object___ *)msgptr;
1735                 struct transObjInfo * transObj = (struct transObjInfo *)tmpptr->original;
1736                 tmpptr = (struct ___Object___ *)(transObj->objptr);
1737                 int type = tmpptr->type;
1738                 int size=classsize[type];
1739                 struct ___Object___ * newobj=RUNMALLOC(size);
1740                 memcpy(newobj, tmpptr, size);
1741                 if(0 == newobj->isolate) {
1742                         newobj->original=tmpptr;
1743                 }
1744                 RUNFREE(msgptr);
1745                 tmpptr = NULL;
1746                 int k = 0;
1747                 for(k = 0; k < transObj->length; ++k) {
1748                         int taskindex = transObj->queues[2 * k];
1749                         int paramindex = transObj->queues[2 * k + 1];
1750                         struct parameterwrapper ** queues = &(paramqueues[numofcore][taskindex][paramindex]);
1751                         enqueueObject(newobj, queues, 1);
1752                 }
1753                 RUNFREE(transObj->queues);
1754                 RUNFREE(transObj);
1755                 return 0;
1756         }
1757 #endif
1758 }
1759
1760 bool getreadlock(void * ptr) {
1761 #ifdef RAW
1762         unsigned msgHdr;
1763         int self_y, self_x, target_y, target_x;
1764         int targetcore = ((int)ptr) % TOTALCORE;
1765         // for 32 bit machine, the size is always 4 words
1766         //int msgsize = sizeof(int) * 4;
1767         int msgsize = 4;
1768
1769         lockobj = (int)ptr;
1770         lockflag = false;
1771 #ifndef INTERRUPT
1772         reside = false;
1773 #endif
1774         lockresult = 0;
1775
1776         if(targetcore == corenum) {
1777                 // reside on this core
1778                 bool deny = false;
1779 #ifdef INTERRUPT
1780                 raw_user_interrupts_off();
1781 #endif
1782                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1783                         // no locks for this object
1784                         // first time to operate on this shared object
1785                         // create a lock for it
1786                         // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
1787                         RuntimeHashadd_I(locktbl, (int)ptr, 1);
1788                 } else {
1789                         int rwlock_obj = 0;
1790                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
1791                         if(-1 != rwlock_obj) {
1792                                 rwlock_obj++;
1793                                 RuntimeHashremovekey(locktbl, (int)ptr);
1794                                 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
1795                         } else {
1796                                 deny = true;
1797                         }
1798                 }
1799 #ifdef INTERRUPT
1800                 raw_user_interrupts_on();
1801 #endif
1802                 if(lockobj == (int)ptr) {
1803                         if(deny) {
1804                                 lockresult = 0;
1805                         } else {
1806                                 lockresult = 1;
1807                         }
1808                         lockflag = true;
1809 #ifndef INTERRUPT
1810                         reside = true;
1811 #endif
1812                 } else {
1813                         // conflicts on lockresults
1814                         raw_test_done(0xa005);
1815                 }
1816                 return true;
1817         }
1818
1819         calCoords(corenum, &self_y, &self_x);
1820         calCoords(targetcore, &target_y, &target_x);
1821         // Build the message header
1822     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
1823                                            self_y, self_x,
1824                                                            target_y, target_x);
1825         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
1826         raw_test_pass(0xbbbb);
1827         raw_test_pass(0xb000 + targetcore); // targetcore
1828     gdn_send(2); // lock request
1829     raw_test_pass(2);
1830         gdn_send(0); // read lock
1831     raw_test_pass(0);
1832     gdn_send(ptr);
1833         raw_test_pass_reg(ptr);
1834         gdn_send(corenum);
1835         raw_test_pass_reg(corenum);
1836         raw_test_pass(0xffff);
1837         return true;
1838 #elif defined THREADSIMULATE
1839         int numofcore = pthread_getspecific(key);
1840
1841         int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
1842         printf("[getreadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1843         if(0 != rc) {
1844                 return false;
1845         }
1846         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1847                 // no locks for this object
1848                 // first time to operate on this shared object
1849                 // create a lock for it
1850                 rc = pthread_rwlock_unlock(&rwlock_tbl);
1851                 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1852                 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
1853                 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
1854                 rc = pthread_rwlock_init(rwlock, NULL);
1855                 printf("[getreadlock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
1856                 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
1857                 printf("[getreadlock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1858                 if(0 != rc) {
1859                         RUNFREE(rwlock);
1860                         return false;
1861                 } else {
1862                         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1863                                 // check again
1864                                 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
1865                         } else {
1866                                 RUNFREE(rwlock);
1867                                 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
1868                         }
1869                         rc = pthread_rwlock_unlock(&rwlock_tbl);
1870                                 printf("[getreadlock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1871                 }
1872                 rc = pthread_rwlock_tryrdlock(rwlock);
1873                 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));       
1874                 if(0 != rc) {
1875                         return false;
1876                 } else {
1877                         return true;
1878                 }
1879         } else {
1880                 pthread_rwlock_t* rwlock_obj = NULL;
1881                 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
1882                 rc = pthread_rwlock_unlock(&rwlock_tbl);
1883                 printf("[getreadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1884                 int rc_obj = pthread_rwlock_tryrdlock(rwlock_obj);
1885                 printf("[getreadlock, %d] getting read lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
1886                 if(0 != rc_obj) {
1887                         return false;
1888                 } else {
1889                         return true;
1890                 }
1891         }
1892 #endif
1893 }
1894
1895 void releasereadlock(void * ptr) {
1896 #ifdef RAW
1897         unsigned msgHdr;
1898         int self_y, self_x, target_y, target_x;
1899         int targetcore = ((int)ptr) % TOTALCORE;
1900         // for 32 bit machine, the size is always 3 words
1901         //int msgsize = sizeof(int) * 3;
1902         int msgsize = 3;
1903
1904         if(targetcore == corenum) {
1905 #ifdef INTERRUPT
1906                 raw_user_interrupts_off();
1907 #endif
1908                 // reside on this core
1909                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1910                         // no locks for this object, something is wrong
1911                         raw_test_done(0xa006);
1912                 } else {
1913                         int rwlock_obj = 0;
1914                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
1915                         rwlock_obj--;
1916                         RuntimeHashremovekey(locktbl, (int)ptr);
1917                         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
1918                 }
1919 #ifdef INTERRUPT
1920                 raw_user_interrupts_on();
1921 #endif
1922                 return;
1923         }
1924
1925         calCoords(corenum, &self_y, &self_x);
1926         calCoords(targetcore, &target_y, &target_x);
1927         // Build the message header
1928     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
1929                                            self_y, self_x,
1930                                                            target_y, target_x);
1931         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
1932         raw_test_pass(0xbbbb);
1933         raw_test_pass(0xb000 + targetcore); // targetcore
1934     gdn_send(5); // lock release
1935     raw_test_pass(5);
1936         gdn_send(0); // read lock
1937     raw_test_pass(0);
1938     gdn_send(ptr);
1939         raw_test_pass_reg(ptr);
1940         raw_test_pass(0xffff);
1941 #elif defined THREADSIMULATE
1942         int numofcore = pthread_getspecific(key);
1943         int rc = pthread_rwlock_rdlock(&rwlock_tbl);
1944         printf("[releasereadlock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1945         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1946                 printf("[releasereadlock, %d] Error: try to release a lock without previously grab it\n", numofcore);
1947                 exit(-1);
1948         }
1949         pthread_rwlock_t* rwlock_obj = NULL;
1950         RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
1951         int rc_obj = pthread_rwlock_unlock(rwlock_obj);
1952         printf("[releasereadlock, %d] unlocked object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
1953         rc = pthread_rwlock_unlock(&rwlock_tbl);
1954         printf("[releasereadlock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
1955 #endif
1956 }
1957
1958 #ifdef RAW
1959 bool getreadlock_I(void * ptr) {
1960         unsigned msgHdr;
1961         int self_y, self_x, target_y, target_x;
1962         int targetcore = ((int)ptr) % TOTALCORE;
1963         // for 32 bit machine, the size is always 4 words
1964         //int msgsize = sizeof(int) * 4;
1965         int msgsize = 4;
1966
1967         lockobj = (int)ptr;
1968         lockflag = false;
1969 #ifndef INTERRUPT
1970         reside = false;
1971 #endif
1972         lockresult = 0;
1973
1974         if(targetcore == corenum) {
1975                 // reside on this core
1976                 bool deny = false;
1977                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
1978                         // no locks for this object
1979                         // first time to operate on this shared object
1980                         // create a lock for it
1981                         // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
1982                         RuntimeHashadd_I(locktbl, (int)ptr, 1);
1983                 } else {
1984                         int rwlock_obj = 0;
1985                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
1986                         if(-1 != rwlock_obj) {
1987                                 rwlock_obj++;
1988                                 RuntimeHashremovekey(locktbl, (int)ptr);
1989                                 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
1990                         } else {
1991                                 deny = true;
1992                         }
1993                 }
1994                 if(lockobj == (int)ptr) {
1995                         if(deny) {
1996                                 lockresult = 0;
1997                         } else {
1998                                 lockresult = 1;
1999                         }
2000                         lockflag = true;
2001 #ifndef INTERRUPT
2002                         reside = true;
2003 #endif
2004                 } else {
2005                         // conflicts on lockresults
2006                         raw_test_done(0xa005);
2007                 }
2008                 return true;
2009         }
2010
2011         calCoords(corenum, &self_y, &self_x);
2012         calCoords(targetcore, &target_y, &target_x);
2013         // Build the message header
2014     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
2015                                            self_y, self_x,
2016                                                            target_y, target_x);
2017         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
2018         raw_test_pass(0xbbbb);
2019         raw_test_pass(0xb000 + targetcore); // targetcore
2020     gdn_send(2); // lock request
2021     raw_test_pass(2);
2022         gdn_send(0); // read lock
2023     raw_test_pass(0);
2024     gdn_send(ptr);
2025         raw_test_pass_reg(ptr);
2026         gdn_send(corenum);
2027         raw_test_pass_reg(corenum);
2028         raw_test_pass(0xffff);
2029         return true;
2030 }
2031
2032 void releasereadlock_I(void * ptr) {
2033         unsigned msgHdr;
2034         int self_y, self_x, target_y, target_x;
2035         int targetcore = ((int)ptr) % TOTALCORE;
2036         // for 32 bit machine, the size is always 3 words
2037         //int msgsize = sizeof(int) * 3;
2038         int msgsize = 3;
2039
2040         if(targetcore == corenum) {
2041                 // reside on this core
2042                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2043                         // no locks for this object, something is wrong
2044                         raw_test_done(0xa006);
2045                 } else {
2046                         int rwlock_obj = 0;
2047                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2048                         rwlock_obj--;
2049                         RuntimeHashremovekey(locktbl, (int)ptr);
2050                         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2051                 }
2052                 return;
2053         }
2054
2055         calCoords(corenum, &self_y, &self_x);
2056         calCoords(targetcore, &target_y, &target_x);
2057         // Build the message header
2058     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
2059                                            self_y, self_x,
2060                                                            target_y, target_x);
2061         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
2062         raw_test_pass(0xbbbb);
2063         raw_test_pass(0xb000 + targetcore); // targetcore
2064     gdn_send(5); // lock release
2065     raw_test_pass(5);
2066         gdn_send(0); // read lock
2067     raw_test_pass(0);
2068     gdn_send(ptr);
2069         raw_test_pass_reg(ptr);
2070         raw_test_pass(0xffff);
2071 }
2072 #endif
2073
2074 bool getwritelock(void * ptr) {
2075 #ifdef RAW
2076         unsigned msgHdr;
2077         int self_y, self_x, target_y, target_x;
2078         int targetcore = ((int)ptr) % TOTALCORE;
2079         // for 32 bit machine, the size is always 4 words
2080         //int msgsize = sizeof(int) * 4;
2081         int msgsize= 4;
2082
2083         lockobj = (int)ptr;
2084         lockflag = false;
2085 #ifndef INTERRUPT
2086         reside = false;
2087 #endif
2088         lockresult = 0;
2089
2090         if(targetcore == corenum) {
2091                 // reside on this core
2092                 bool deny = false;
2093 #ifdef INTERRUPT
2094                 raw_user_interrupts_off();
2095 #endif
2096                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2097                         // no locks for this object
2098                         // first time to operate on this shared object
2099                         // create a lock for it
2100                         // the lock is an integer: 0 -- stall, >0 -- read lock, -1 -- write lock
2101                         raw_test_pass(0xe552);
2102                         RuntimeHashadd_I(locktbl, (int)ptr, -1);
2103                 } else {
2104                         int rwlock_obj = 0;
2105                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2106                         raw_test_pass(0xe553);
2107                         raw_test_pass_reg(rwlock_obj);
2108                         if(0 == rwlock_obj) {
2109                                 rwlock_obj = -1;
2110                                 RuntimeHashremovekey(locktbl, (int)ptr);
2111                                 RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2112                         } else {
2113                                 deny = true;
2114                         }
2115                 }
2116 #ifdef INTERRUPT
2117                 raw_user_interrupts_on();
2118 #endif
2119                 raw_test_pass(0xe554);
2120                 raw_test_pass_reg(lockresult);
2121                 if(lockobj == (int)ptr) {
2122                         if(deny) {
2123                                 lockresult = 0;
2124                                 raw_test_pass(0);
2125                         } else {
2126                                 lockresult = 1;
2127                                 raw_test_pass(1);
2128                         }
2129                         lockflag = true;
2130 #ifndef INTERRUPT
2131                         reside = true;
2132 #endif
2133                 } else {
2134                         // conflicts on lockresults
2135                         raw_test_done(0xa007);
2136                 }
2137                 return true;
2138         }
2139
2140         raw_test_pass(0xe555);
2141         calCoords(corenum, &self_y, &self_x);
2142         calCoords(targetcore, &target_y, &target_x);
2143         // Build the message header
2144     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
2145                                            self_y, self_x,
2146                                                            target_y, target_x);
2147         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
2148         raw_test_pass(0xbbbb);
2149         raw_test_pass(0xb000 + targetcore); // targetcore
2150     gdn_send(2); // lock request
2151     raw_test_pass(2);
2152         gdn_send(1); // write lock
2153     raw_test_pass(1);
2154     gdn_send(ptr);
2155         raw_test_pass_reg(ptr);
2156         gdn_send(corenum);
2157         raw_test_pass_reg(corenum);
2158         raw_test_pass(0xffff);
2159         return true;
2160 #elif defined THREADSIMULATE
2161         int numofcore = pthread_getspecific(key);
2162
2163         int rc = pthread_rwlock_tryrdlock(&rwlock_tbl);
2164         printf("[getwritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2165         if(0 != rc) {
2166                 return false;
2167         }
2168         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2169                 // no locks for this object
2170                 // first time to operate on this shared object
2171                 // create a lock for it
2172                 rc = pthread_rwlock_unlock(&rwlock_tbl);
2173                 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2174                 pthread_rwlock_t* rwlock = (pthread_rwlock_t *)RUNMALLOC(sizeof(pthread_rwlock_t));
2175                 memcpy(rwlock, &rwlock_init, sizeof(pthread_rwlock_t));
2176                 rc = pthread_rwlock_init(rwlock, NULL);
2177                 printf("[getwritelock, %d] initialize the rwlock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));
2178                 rc = pthread_rwlock_trywrlock(&rwlock_tbl);
2179                 printf("[getwritelock, %d] getting the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2180                 if(0 != rc) {
2181                         pthread_rwlock_destroy(rwlock);
2182                         RUNFREE(rwlock);
2183                         return false;
2184                 } else {
2185                         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2186                                 // check again
2187                                 RuntimeHashadd(locktbl, (int)ptr, (int)rwlock);
2188                         } else {
2189                                 pthread_rwlock_destroy(rwlock);
2190                                 RUNFREE(rwlock);
2191                                 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock);
2192                         }
2193                         rc = pthread_rwlock_unlock(&rwlock_tbl);
2194                         printf("[getwritelock, %d] release the write lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2195                 }
2196                 rc = pthread_rwlock_trywrlock(rwlock);
2197                 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc, strerror(rc));     
2198                 if(0 != rc) {
2199                         return false;
2200                 } else {
2201                         return true;
2202                 }
2203         } else {
2204                 pthread_rwlock_t* rwlock_obj = NULL;
2205                 RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2206                 rc = pthread_rwlock_unlock(&rwlock_tbl);
2207                 printf("[getwritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2208                 int rc_obj = pthread_rwlock_trywrlock(rwlock_obj);
2209                 printf("[getwritelock, %d] getting write lock for object %d: %d error: \n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2210                 if(0 != rc_obj) {
2211                         return false;
2212                 } else {
2213                         return true;
2214                 }
2215         }
2216
2217 #endif
2218 }
2219
2220 void releasewritelock(void * ptr) {
2221 #ifdef RAW
2222         unsigned msgHdr;
2223         int self_y, self_x, target_y, target_x;
2224         int targetcore = ((int)ptr) % TOTALCORE;
2225         // for 32 bit machine, the size is always 3 words
2226         //int msgsize = sizeof(int) * 3;
2227         int msgsize = 3;
2228
2229         if(targetcore == corenum) {
2230 #ifdef INTERRUPT
2231                 raw_user_interrupts_off();
2232 #endif
2233                 // reside on this core
2234                 if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2235                         // no locks for this object, something is wrong
2236                         raw_test_done(0xa008);
2237                 } else {
2238                         int rwlock_obj = 0;
2239                         raw_test_pass(0xe662);
2240                         RuntimeHashget(locktbl, (int)ptr, &rwlock_obj);
2241                         raw_test_pass_reg(rwlock_obj);
2242                         rwlock_obj++;
2243                         RuntimeHashremovekey(locktbl, (int)ptr);
2244                         RuntimeHashadd_I(locktbl, (int)ptr, rwlock_obj);
2245                         raw_test_pass_reg(rwlock_obj);
2246                 }
2247 #ifdef INTERRUPT
2248                 raw_user_interrupts_on();
2249 #endif
2250                 return;
2251         }
2252
2253         raw_test_pass(0xe663);
2254         calCoords(corenum, &self_y, &self_x);
2255         calCoords(targetcore, &target_y, &target_x);
2256         // Build the message header
2257     msgHdr = construct_dyn_hdr(0, msgsize, 0,           // msgsize word sent.
2258                                            self_y, self_x,
2259                                                            target_y, target_x);
2260         gdn_send(msgHdr);               // Send the message header to EAST to handle fab(n - 1).
2261         raw_test_pass(0xbbbb);
2262         raw_test_pass(0xb000 + targetcore);
2263     gdn_send(5); // lock release
2264     raw_test_pass(5);
2265         gdn_send(1); // write lock
2266     raw_test_pass(1);
2267     gdn_send(ptr);
2268         raw_test_pass_reg(ptr);
2269         raw_test_pass(0xffff);
2270 #elif defined THREADSIMULATE
2271         int numofcore = pthread_getspecific(key);
2272         int rc = pthread_rwlock_rdlock(&rwlock_tbl);
2273         printf("[releasewritelock, %d] getting the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2274         if(!RuntimeHashcontainskey(locktbl, (int)ptr)) {
2275                 printf("[releasewritelock, %d] Error: try to release a lock without previously grab it\n", numofcore);
2276                 exit(-1);
2277         }
2278         pthread_rwlock_t* rwlock_obj = NULL;
2279         RuntimeHashget(locktbl, (int)ptr, (int*)&rwlock_obj);
2280         int rc_obj = pthread_rwlock_unlock(rwlock_obj);
2281         printf("[releasewritelock, %d] unlocked object %d: %d error:\n", numofcore, (int)ptr, rc_obj, strerror(rc_obj));
2282         rc = pthread_rwlock_unlock(&rwlock_tbl);
2283         printf("[releasewritelock, %d] release the read lock for locktbl: %d error: \n", numofcore, rc, strerror(rc));
2284 #endif
2285 }
2286
2287 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
2288   void * taskpointerarray[MAXTASKPARAMS];
2289   int j;
2290   int numparams=parameter->task->numParameters;
2291   int numiterators=parameter->task->numTotal-1;
2292   int retval=1;
2293   int addnormal=1;
2294   int adderror=1;
2295
2296   struct taskdescriptor * task=parameter->task;
2297
2298         ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);//this add the object to parameterwrapper
2299  
2300   /* Add enqueued object to parameter vector */
2301   taskpointerarray[parameter->slot]=ptr;
2302
2303   /* Reset iterators */
2304   for(j=0;j<numiterators;j++) {
2305     toiReset(&parameter->iterators[j]);
2306   }
2307
2308   /* Find initial state */
2309   for(j=0;j<numiterators;j++) {
2310   backtrackinit:
2311     if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2312       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2313     else if (j>0) {
2314       /* Need to backtrack */
2315       toiReset(&parameter->iterators[j]);
2316       j--;
2317       goto backtrackinit;
2318     } else {
2319       /* Nothing to enqueue */
2320       return retval;
2321     }
2322   }
2323
2324   
2325   while(1) {
2326     /* Enqueue current state */
2327     int launch = 0;
2328     struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
2329     tpd->task=task;
2330     tpd->numParameters=numiterators+1;
2331     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2332     for(j=0;j<=numiterators;j++){
2333       tpd->parameterArray[j]=taskpointerarray[j];//store the actual parameters
2334     }
2335     /* Enqueue task */
2336     if ((/*!gencontains(failedtasks, tpd)&&*/!gencontains(activetasks,tpd))) {
2337       genputtable(activetasks, tpd, tpd);
2338     } else {
2339       RUNFREE(tpd->parameterArray);
2340       RUNFREE(tpd);
2341     }
2342     
2343     /* This loop iterates to the next parameter combination */
2344     if (numiterators==0)
2345       return retval;
2346
2347     for(j=numiterators-1; j<numiterators;j++) {
2348     backtrackinc:
2349       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2350         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2351       else if (j>0) {
2352         /* Need to backtrack */
2353         toiReset(&parameter->iterators[j]);
2354         j--;
2355         goto backtrackinc;
2356       } else {
2357         /* Nothing more to enqueue */
2358         return retval;
2359       }
2360     }
2361   }
2362   return retval;
2363 }
2364
2365 #ifdef RAW
2366 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
2367   void * taskpointerarray[MAXTASKPARAMS];
2368   int j;
2369   int numparams=parameter->task->numParameters;
2370   int numiterators=parameter->task->numTotal-1;
2371   int retval=1;
2372   int addnormal=1;
2373   int adderror=1;
2374
2375   struct taskdescriptor * task=parameter->task;
2376
2377         ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);//this add the object to parameterwrapper
2378  
2379   /* Add enqueued object to parameter vector */
2380   taskpointerarray[parameter->slot]=ptr;
2381
2382   /* Reset iterators */
2383   for(j=0;j<numiterators;j++) {
2384     toiReset(&parameter->iterators[j]);
2385   }
2386
2387   /* Find initial state */
2388   for(j=0;j<numiterators;j++) {
2389   backtrackinit:
2390     if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2391       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2392     else if (j>0) {
2393       /* Need to backtrack */
2394       toiReset(&parameter->iterators[j]);
2395       j--;
2396       goto backtrackinit;
2397     } else {
2398       /* Nothing to enqueue */
2399       return retval;
2400     }
2401   }
2402   
2403   while(1) {
2404     /* Enqueue current state */
2405     int launch = 0;
2406     struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2407     tpd->task=task;
2408     tpd->numParameters=numiterators+1;
2409     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2410     for(j=0;j<=numiterators;j++){
2411       tpd->parameterArray[j]=taskpointerarray[j];//store the actual parameters
2412     }
2413     /* Enqueue task */
2414     if ((/*!gencontains(failedtasks, tpd)&&*/!gencontains(activetasks,tpd))) {
2415       genputtable_I(activetasks, tpd, tpd);
2416     } else {
2417       RUNFREE(tpd->parameterArray);
2418       RUNFREE(tpd);
2419     }
2420     
2421     /* This loop iterates to the next parameter combination */
2422     if (numiterators==0)
2423       return retval;
2424
2425     for(j=numiterators-1; j<numiterators;j++) {
2426     backtrackinc:
2427       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2428         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2429       else if (j>0) {
2430         /* Need to backtrack */
2431         toiReset(&parameter->iterators[j]);
2432         j--;
2433         goto backtrackinc;
2434       } else {
2435         /* Nothing more to enqueue */
2436         return retval;
2437       }
2438     }
2439   }
2440   return retval;
2441 }
2442 #endif
2443
2444 /* Handler for signals. The signals catch null pointer errors and
2445    arithmatic errors. */
2446 #ifndef RAW
2447 void myhandler(int sig, siginfo_t *info, void *uap) {
2448   sigset_t toclear;
2449 #ifdef DEBUG
2450   printf("sig=%d\n",sig);
2451   printf("signal\n");
2452 #endif
2453   sigemptyset(&toclear);
2454   sigaddset(&toclear, sig);
2455   sigprocmask(SIG_UNBLOCK, &toclear,NULL); 
2456   longjmp(error_handler,1);
2457 }
2458 #endif
2459
2460 fd_set readfds;
2461 int maxreadfd;
2462 struct RuntimeHash *fdtoobject;
2463
2464 void addreadfd(int fd) {
2465   if (fd>=maxreadfd)
2466     maxreadfd=fd+1;
2467   FD_SET(fd, &readfds);
2468 }
2469
2470 void removereadfd(int fd) {
2471   FD_CLR(fd, &readfds);
2472   if (maxreadfd==(fd+1)) {
2473     maxreadfd--;
2474     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
2475       maxreadfd--;
2476   }
2477 }
2478
2479 #ifdef PRECISE_GC
2480 #define OFFSET 2
2481 #else
2482 #define OFFSET 0
2483 #endif
2484
2485 void executetasks() {
2486   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2487   int numparams=0;
2488   int numtotal=0;
2489   struct ___Object___ * tmpparam = NULL;
2490   struct parameterdescriptor * pd=NULL;
2491   struct parameterwrapper *pw=NULL;
2492   int j = 0;
2493   int x = 0;
2494
2495 #ifdef RAW
2496   int grount = 0;
2497   int andmask=0;
2498   int checkmask=0;
2499
2500   raw_test_pass(0xe991);
2501 #endif
2502
2503 #ifndef RAW
2504   /* Set up signal handlers */
2505   struct sigaction sig;
2506   sig.sa_sigaction=&myhandler;
2507   sig.sa_flags=SA_SIGINFO;
2508   sigemptyset(&sig.sa_mask);
2509
2510   /* Catch bus errors, segmentation faults, and floating point exceptions*/
2511   sigaction(SIGBUS,&sig,0);
2512   sigaction(SIGSEGV,&sig,0);
2513   sigaction(SIGFPE,&sig,0);
2514   sigaction(SIGPIPE,&sig,0);
2515 #endif
2516
2517 #ifndef RAW
2518   /* Zero fd set */
2519   FD_ZERO(&readfds);
2520 #endif
2521   maxreadfd=0;
2522 #ifndef RAW
2523   fdtoobject=allocateRuntimeHash(100);
2524 #endif
2525
2526 #ifndef RAW
2527   /* Map first block of memory to protected, anonymous page */
2528   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
2529 #endif
2530
2531   newtask:
2532   while((hashsize(activetasks)>0)||(maxreadfd>0)) {
2533
2534 #ifdef RAW
2535           raw_test_pass(0xe992);
2536 #else
2537     /* Check if any filedescriptors have IO pending */
2538     if (maxreadfd>0) {
2539       int i;
2540       struct timeval timeout={0,0};
2541       fd_set tmpreadfds;
2542       int numselect;
2543       tmpreadfds=readfds;
2544       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
2545       if (numselect>0) {
2546         /* Process ready fd's */
2547         int fd;
2548         for(fd=0;fd<maxreadfd;fd++) {
2549           if (FD_ISSET(fd, &tmpreadfds)) {
2550             /* Set ready flag on object */
2551             void * objptr;
2552             //      printf("Setting fd %d\n",fd);
2553             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
2554               if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
2555                          enqueueObject(objptr, NULL, 0);
2556                   }
2557             }
2558           }
2559         }
2560       }
2561     }
2562 #endif
2563
2564     /* See if there are any active tasks */
2565     if (hashsize(activetasks)>0) {
2566       int i;
2567       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2568       genfreekey(activetasks, currtpd);
2569       
2570       /* Check if this task has failed, allow a task that contains optional objects to fire */
2571       /*if (gencontains(failedtasks, currtpd)) {
2572         // Free up task parameter descriptor
2573         RUNFREE(currtpd->parameterArray);
2574         RUNFREE(currtpd);
2575         goto newtask;
2576       }*/
2577       numparams=currtpd->task->numParameters;
2578       numtotal=currtpd->task->numTotal;
2579       
2580 #ifdef THREADSIMULATE
2581           int isolateflags[numparams];
2582 #endif
2583       /* Make sure that the parameters are still in the queues */
2584       for(i=0;i<numparams;i++) {
2585         void * parameter=currtpd->parameterArray[i];
2586 #ifdef RAW
2587         raw_test_pass(0xe993);
2588         // require locks for this parameter
2589         getwritelock(parameter);
2590         grount = 0;
2591         while(!lockflag) {
2592 #ifndef INTERRUPT
2593                 receiveObject();
2594 #endif
2595         }
2596 #ifndef INTERRUPT
2597         if(reside) {
2598                 while(receiveObject() != -1) {
2599                 }
2600         }
2601 #endif
2602         grount = lockresult;
2603         
2604         lockresult = 0;
2605         lockobj = 0;
2606         lockflag = false;
2607 #ifndef INTERRUPT
2608         reside = false;
2609 #endif
2610
2611         if(grount == 0) {
2612                 raw_test_pass(0xe994);
2613                 // can not get the lock, try later
2614                 for(j = 0; j < i; ++j) {
2615                         releasewritelock(taskpointerarray[j+OFFSET]);
2616                 }
2617                 genputtable(activetasks, currtpd, currtpd);
2618                 goto newtask;
2619         }
2620         // flush the object
2621         {
2622                 int tmp = 0;
2623                 for(tmp = 0; tmp < classsize[((struct ___Object___ *)parameter)->type]; ++tmp) {
2624                         invalidateAddr(parameter + tmp);
2625                 }
2626         }
2627 #endif
2628         tmpparam = (struct ___Object___ *)parameter;
2629 #ifdef THREADSIMULATE
2630         if(0 == tmpparam->isolate) {
2631                 isolateflags[i] = 0;
2632                 // shared object, need to flush with current value
2633                 //if(!getreadlock(tmpparam->original)) {
2634                 //      // fail to get read lock of the original object, try this task later
2635                 if(!getwritelock(tmpparam->original)) {
2636                         // fail to get write lock, release all obtained locks and try this task later
2637                         int j = 0;
2638                         for(j = 0; j < i; ++j) {
2639                                 if(0 == isolateflags[j]) {
2640                                         releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
2641                                 }
2642                         }
2643                         genputtable(activetasks, currtpd, currtpd);
2644                         goto newtask;
2645                 }
2646                 if(tmpparam->version != tmpparam->original->version) {
2647                         // some task on another core has changed this object
2648                         // flush this object
2649                         //memcpy(tmpparam, tmpparam->original, classsize[tmpparam->type]);
2650                         // release all obtained locks 
2651                         int j = 0;
2652                         for(j = 0; j < i; ++j) {
2653                                 if(0 == isolateflags[j]) {
2654                                         releasewritelock(((struct ___Object___ *)taskpointerarray[j+OFFSET])->original);
2655                                 }
2656                         }
2657                         releasewritelock(tmpparam->original);
2658
2659                         // dequeue this object
2660                         int numofcore = pthread_getspecific(key);
2661                         struct parameterwrapper ** queues = objectqueues[numofcore][tmpparam->type];
2662                         int length = numqueues[numofcore][tmpparam->type];
2663                         for(j = 0; j < length; ++j) {
2664                                 struct parameterwrapper * pw = queues[j];
2665                                 if(ObjectHashcontainskey(pw->objectset, (int)tmpparam)) {
2666                                         int next;
2667                                         int UNUSED, UNUSED2;
2668                                         int * enterflags;
2669                                         ObjectHashget(pw->objectset, (int) tmpparam, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
2670                                         ObjectHashremove(pw->objectset, (int)tmpparam);
2671                                         if (enterflags!=NULL)
2672                                                 free(enterflags);
2673                                 }
2674                         }
2675                         // try to enqueue it again to check if it feeds other tasks;
2676                         //enqueueObject(tmpparam, NULL, 0);
2677                         // Free up task parameter descriptor
2678                         RUNFREE(currtpd->parameterArray);
2679                         RUNFREE(currtpd);
2680                         goto newtask;
2681                 }
2682         } else {
2683                 isolateflags[i] = 1;
2684         }
2685 #endif
2686         pd=currtpd->task->descriptorarray[i];
2687         pw=(struct parameterwrapper *) pd->queue;
2688         /* Check that object is still in queue */
2689         {
2690           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2691 #ifdef RAW
2692                   raw_test_pass(0xe995);
2693 #endif
2694             RUNFREE(currtpd->parameterArray);
2695             RUNFREE(currtpd);
2696             goto newtask;
2697           }
2698         }
2699 #ifdef RAW
2700         /* Check if the object's flags still meets requirements */
2701         {
2702                 int tmpi = 0;
2703                 bool ismet = false;
2704                 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2705                         andmask=pw->intarray[tmpi*2];
2706                         checkmask=pw->intarray[tmpi*2+1];
2707                         raw_test_pass(0xdd000000 + andmask);
2708                         raw_test_pass_reg((int)parameter);
2709                         raw_test_pass(0xdd000000 + ((struct ___Object___ *)parameter)->flag);
2710                         raw_test_pass(0xdd000000 + checkmask);
2711                         if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2712                                 ismet = true;
2713                                 break;
2714                         }
2715                 }
2716                 if (!ismet) {
2717                         // flags are never suitable
2718                         // remove this obj from the queue
2719                         int next;
2720                         int UNUSED, UNUSED2;
2721                         int * enterflags;
2722                         raw_test_pass(0xe996);
2723                         ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
2724                         ObjectHashremove(pw->objectset, (int)parameter);
2725                         if (enterflags!=NULL)
2726                                 free(enterflags);
2727                         // release grabbed locks
2728                         for(j = 0; j < i; ++j) {
2729                                 releasewritelock(taskpointerarray[j+OFFSET]);
2730                         }
2731                         releasewritelock(parameter);
2732                         RUNFREE(currtpd->parameterArray);
2733                         RUNFREE(currtpd);
2734                         goto newtask;
2735                 }
2736         }
2737 #endif
2738       parameterpresent:
2739         ;
2740         /* Check that object still has necessary tags */
2741         for(j=0;j<pd->numbertags;j++) {
2742           int slotid=pd->tagarray[2*j]+numparams;
2743           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2744           if (!containstag(parameter, tagd)) {
2745 #ifdef RAW
2746                   raw_test_pass(0xe997);
2747 #endif
2748             RUNFREE(currtpd->parameterArray);
2749             RUNFREE(currtpd);
2750             goto newtask;
2751           }
2752         }
2753         
2754         taskpointerarray[i+OFFSET]=parameter;
2755       }
2756       /* Copy the tags */
2757       for(;i<numtotal;i++) {
2758         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2759       }
2760
2761 #ifdef THREADSIMULATE
2762          for(i = 0; i < numparams; ++i) {
2763                   if(0 == isolateflags[i]) {
2764                           struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
2765                           if(tmpparam != tmpparam->original) {
2766                                   taskpointerarray[i+OFFSET] = tmpparam->original;
2767                           }
2768                   }
2769           }
2770 #endif
2771
2772       {
2773 #if 0
2774 #ifndef RAW
2775         /* Checkpoint the state */
2776         forward=allocateRuntimeHash(100);
2777         reverse=allocateRuntimeHash(100);
2778         //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
2779 #endif
2780 #endif
2781         if (x=setjmp(error_handler)) {
2782           int counter;
2783           /* Recover */
2784 #ifndef RAW       
2785 #ifdef DEBUG
2786           printf("Fatal Error=%d, Recovering!\n",x);
2787 #endif
2788 #endif
2789          /*
2790           genputtable(failedtasks,currtpd,currtpd);
2791           //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
2792
2793           freeRuntimeHash(forward);
2794           freeRuntimeHash(reverse);
2795           freemalloc();
2796           forward=NULL;
2797           reverse=NULL;
2798           */
2799           //fflush(stdout);
2800 #ifdef RAW
2801           raw_test_pass_reg(x);
2802           raw_test_done(0xa009);
2803 #else
2804           exit(-1);
2805 #endif
2806         } else {
2807           /*if (injectfailures) {
2808             if ((((double)random())/RAND_MAX)<failurechance) {
2809               printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
2810               longjmp(error_handler,10);
2811             }
2812           }*/
2813           /* Actually call task */
2814 #ifdef PRECISE_GC
2815           ((int *)taskpointerarray)[0]=currtpd->numParameters;
2816           taskpointerarray[1]=NULL;
2817 #endif
2818           if(debugtask){
2819 #ifndef RAW
2820             printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
2821 #endif
2822             ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
2823 #ifndef RAW
2824             printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
2825 #endif
2826           } else
2827             ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
2828
2829 #ifdef RAW
2830           for(i = 0; i < numparams; ++i) {
2831                   int j = 0;
2832                   struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
2833                   raw_test_pass(0xe998);
2834                 raw_test_pass(0xdd100000 + tmpparam->flag);
2835                   releasewritelock(tmpparam);
2836           }
2837 #elif defined THREADSIMULATE
2838           for(i = 0; i < numparams; ++i) {
2839                   if(0 == isolateflags[i]) {
2840                           struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
2841                           releasewritelock(tmpparam);
2842                   }
2843           }
2844 #endif
2845
2846 #if 0
2847 #ifndef RAW
2848           freeRuntimeHash(forward);
2849           freeRuntimeHash(reverse);
2850 #endif
2851 #endif
2852           freemalloc();
2853           // Free up task parameter descriptor
2854           RUNFREE(currtpd->parameterArray);
2855           RUNFREE(currtpd);
2856 #if 0
2857 #ifndef RAW
2858           forward=NULL;
2859           reverse=NULL;
2860 #endif
2861 #endif
2862         }
2863       }
2864     }
2865   }
2866 }
2867  
2868 /* This function processes an objects tags */
2869 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
2870   int i;
2871   
2872   for(i=0;i<pd->numbertags;i++) {
2873     int slotid=pd->tagarray[2*i];
2874     int tagid=pd->tagarray[2*i+1];
2875     
2876     if (statusarray[slotid+numparams]==0) {
2877       parameter->iterators[*iteratorcount].istag=1;
2878       parameter->iterators[*iteratorcount].tagid=tagid;
2879       parameter->iterators[*iteratorcount].slot=slotid+numparams;
2880       parameter->iterators[*iteratorcount].tagobjectslot=index;
2881       statusarray[slotid+numparams]=1;
2882       (*iteratorcount)++;
2883     }
2884   }
2885 }
2886
2887
2888 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
2889   int i;
2890   int tagcount=0;
2891   struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
2892
2893   parameter->iterators[*iteratorcount].istag=0;
2894   parameter->iterators[*iteratorcount].slot=index;
2895   parameter->iterators[*iteratorcount].objectset=objectset;
2896   statusarray[index]=1;
2897
2898   for(i=0;i<pd->numbertags;i++) {
2899     int slotid=pd->tagarray[2*i];
2900     int tagid=pd->tagarray[2*i+1];
2901     if (statusarray[slotid+numparams]!=0) {
2902       /* This tag has already been enqueued, use it to narrow search */
2903       parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
2904       tagcount++;
2905     }
2906   }
2907   parameter->iterators[*iteratorcount].numtags=tagcount;
2908
2909   (*iteratorcount)++;
2910 }
2911
2912 /* This function builds the iterators for a task & parameter */
2913
2914 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
2915   int statusarray[MAXTASKPARAMS];
2916   int i;
2917   int numparams=task->numParameters;
2918   int iteratorcount=0;
2919   for(i=0;i<MAXTASKPARAMS;i++) statusarray[i]=0;
2920
2921   statusarray[index]=1; /* Initial parameter */
2922   /* Process tags for initial iterator */
2923   
2924   processtags(task->descriptorarray[index], index, parameter, & iteratorcount, statusarray, numparams);
2925   
2926   while(1) {
2927   loopstart:
2928     /* Check for objects with existing tags */
2929     for(i=0;i<numparams;i++) {
2930       if (statusarray[i]==0) {
2931         struct parameterdescriptor *pd=task->descriptorarray[i];
2932         int j;
2933         for(j=0;j<pd->numbertags;j++) {
2934           int slotid=pd->tagarray[2*j];
2935           if(statusarray[slotid+numparams]!=0) {
2936             processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2937             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2938             goto loopstart;
2939           }
2940         }
2941       }
2942     }
2943
2944     /* Next do objects w/ unbound tags*/
2945
2946     for(i=0;i<numparams;i++) {
2947       if (statusarray[i]==0) {
2948         struct parameterdescriptor *pd=task->descriptorarray[i];
2949         if (pd->numbertags>0) {
2950           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2951           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2952           goto loopstart;
2953         }
2954       }
2955     }
2956
2957     /* Nothing with a tag enqueued */
2958
2959     for(i=0;i<numparams;i++) {
2960       if (statusarray[i]==0) {
2961         struct parameterdescriptor *pd=task->descriptorarray[i];
2962         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2963         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2964         goto loopstart;
2965       }
2966     }
2967
2968     /* Nothing left */
2969     return;
2970   }
2971 }
2972
2973  void printdebug() {
2974    int i;
2975    int j;
2976 #ifdef THREADSIMULATE
2977    int numofcore = pthread_getspecific(key);
2978    for(i=0;i<numtasks[numofcore];i++) {
2979            struct taskdescriptor * task=taskarray[numofcore][i];
2980 #else
2981 #ifdef RAW
2982            if(corenum > NUMCORES - 1) {
2983                    return;
2984            }
2985 #endif
2986    for(i=0;i<numtasks[corenum];i++) {
2987      struct taskdescriptor * task=taskarray[corenum][i];
2988 #endif
2989 #ifndef RAW
2990      printf("%s\n", task->name);
2991 #endif
2992      for(j=0;j<task->numParameters;j++) {
2993        struct parameterdescriptor *param=task->descriptorarray[j];
2994        struct parameterwrapper *parameter=param->queue;
2995        struct ObjectHash * set=parameter->objectset;
2996        struct ObjectIterator objit;
2997 #ifndef RAW
2998        printf("  Parameter %d\n", j);
2999 #endif
3000        ObjectHashiterator(set, &objit);
3001        while(ObjhasNext(&objit)) {
3002          struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
3003          struct ___Object___ * tagptr=obj->___tags___;
3004          int nonfailed=Objdata4(&objit);
3005          int numflags=Objdata3(&objit);
3006          int flags=Objdata2(&objit);
3007          Objnext(&objit);
3008 #ifndef RAW
3009          printf("    Contains %lx\n", obj);
3010          printf("      flag=%d\n", obj->flag); 
3011 #endif
3012          if (tagptr==NULL) {
3013          } else if (tagptr->type==TAGTYPE) {
3014 #ifndef RAW
3015            printf("      tag=%lx\n",tagptr);
3016 #endif
3017            ;
3018          } else {
3019            int tagindex=0;
3020            struct ArrayObject *ao=(struct ArrayObject *)tagptr;
3021            for(;tagindex<ao->___cachedCode___;tagindex++) {
3022 #ifndef RAW
3023              printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
3024 #endif
3025            }
3026          }
3027        }
3028      }
3029    }
3030  }
3031  
3032
3033 /* This function processes the task information to create queues for
3034    each parameter type. */
3035
3036 void processtasks() {
3037   int i;
3038 #ifdef RAW
3039           if(corenum > NUMCORES - 1) {
3040                   return;
3041           }
3042 #endif
3043 #ifdef THREADSIMULATE
3044   int numofcore = pthread_getspecific(key);
3045   for(i=0;i<numtasks[numofcore];i++) {
3046           struct taskdescriptor *task=taskarray[numofcore][i];
3047 #else
3048   for(i=0;i<numtasks[corenum];i++) {
3049     struct taskdescriptor * task=taskarray[corenum][i];
3050 #endif
3051     int j;
3052
3053         /* Build objectsets */
3054         for(j=0;j<task->numParameters;j++) {
3055       struct parameterdescriptor *param=task->descriptorarray[j];
3056       struct parameterwrapper *parameter=param->queue;
3057           parameter->objectset=allocateObjectHash(10);
3058           parameter->task=task;
3059     }
3060
3061     /* Build iterators for parameters */
3062     for(j=0;j<task->numParameters;j++) {
3063       struct parameterdescriptor *param=task->descriptorarray[j];
3064       struct parameterwrapper *parameter=param->queue;
3065       builditerators(task, j, parameter);
3066     }
3067  }
3068 }
3069
3070 void toiReset(struct tagobjectiterator * it) {
3071   if (it->istag) {
3072     it->tagobjindex=0;
3073   } else if (it->numtags>0) {
3074     it->tagobjindex=0;
3075   } else {
3076     ObjectHashiterator(it->objectset, &it->it);
3077   }
3078 }
3079
3080 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
3081   if (it->istag) {
3082     /* Iterate tag */
3083     /* Get object with tags */
3084     struct ___Object___ *obj=objectarray[it->tagobjectslot];
3085     struct ___Object___ *tagptr=obj->___tags___;
3086     if (tagptr->type==TAGTYPE) {
3087       if ((it->tagobjindex==0)&& /* First object */
3088           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
3089         return 1;
3090       else
3091         return 0;
3092     } else {
3093       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3094       int tagindex=it->tagobjindex;
3095       for(;tagindex<ao->___cachedCode___;tagindex++) {
3096         struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
3097         if (td->flag==it->tagid) {
3098           it->tagobjindex=tagindex; /* Found right type of tag */
3099           return 1;
3100         }
3101       }
3102       return 0;
3103     }
3104   } else if (it->numtags>0) {
3105     /* Use tags to locate appropriate objects */
3106     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3107     struct ___Object___ *objptr=tag->flagptr;
3108     int i;
3109     if (objptr->type!=OBJECTARRAYTYPE) {
3110       if (it->tagobjindex>0)
3111         return 0;
3112       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3113         return 0;
3114       for(i=1;i<it->numtags;i++) {
3115         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3116         if (!containstag(objptr,tag2))
3117           return 0;
3118       }
3119       return 1;
3120     } else {
3121       struct ArrayObject *ao=(struct ArrayObject *) objptr;
3122       int tagindex;
3123       int i;
3124       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
3125         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
3126         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3127           continue;
3128         for(i=1;i<it->numtags;i++) {
3129           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3130           if (!containstag(objptr,tag2))
3131             goto nexttag;
3132         }
3133         it->tagobjindex=tagindex;
3134         return 1;
3135       nexttag:
3136         ;
3137       }
3138       it->tagobjindex=tagindex;
3139       return 0;
3140     }
3141   } else {
3142     return ObjhasNext(&it->it);
3143   }
3144 }
3145
3146 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
3147   int j;
3148   struct ___Object___ * objptr=tag->flagptr;
3149   if (objptr->type==OBJECTARRAYTYPE) {
3150     struct ArrayObject *ao=(struct ArrayObject *)objptr;
3151     for(j=0;j<ao->___cachedCode___;j++) {
3152       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
3153         return 1;
3154     }
3155     return 0;
3156   } else
3157     return objptr==ptr;
3158 }
3159
3160 void toiNext(struct tagobjectiterator *it , void ** objectarray OPTARG(int * failed)) {
3161   /* hasNext has all of the intelligence */
3162   if(it->istag) {
3163     /* Iterate tag */
3164     /* Get object with tags */
3165     struct ___Object___ *obj=objectarray[it->tagobjectslot];
3166     struct ___Object___ *tagptr=obj->___tags___;
3167     if (tagptr->type==TAGTYPE) {
3168       it->tagobjindex++;
3169       objectarray[it->slot]=tagptr;
3170     } else {
3171       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3172       objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
3173     }
3174   } else if (it->numtags>0) {
3175     /* Use tags to locate appropriate objects */
3176     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3177     struct ___Object___ *objptr=tag->flagptr;
3178     if (objptr->type!=OBJECTARRAYTYPE) {
3179       it->tagobjindex++;
3180       objectarray[it->slot]=objptr;
3181     } else {
3182       struct ArrayObject *ao=(struct ArrayObject *) objptr;
3183       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
3184     }
3185   } else {
3186     /* Iterate object */
3187     objectarray[it->slot]=(void *)Objkey(&it->it);
3188     Objnext(&it->it);
3189   }
3190 }
3191 #endif