Fix bugs in scheduling simulator. Also add -robustroot setting in Tests/dotest script
[IRC.git] / Robust / src / Runtime / multicoretask.c
index df46769637ca5676e3b04ed6cb1c18b514eb5a98..237a1eb810fcf23742e8c0c0d707b4fe6b5de8a9 100644 (file)
 #include <errno.h>
 #endif
 #ifdef RAW
+#ifdef RAWPROFILE
+#ifdef RAWUSEIO
+#include "stdio.h"
+#include "string.h"
+#endif
+#endif
 #include <raw.h>
 #include <raw_compiler_defs.h>
-//#include <libints.h>
 #elif defined THREADSIMULATE
 // use POSIX message queue
 // for each core, its message queue named as
@@ -51,7 +56,7 @@ struct RuntimeHash * reverse;
 
 int corestatus[NUMCORES]; // records status of each core
                           // 1: running tasks
-// 0: stall
+                          // 0: stall
 int numsendobjs[NUMCORES]; // records how many objects a core has sent out
 int numreceiveobjs[NUMCORES]; // records how many objects a core has received
 #ifdef RAW
@@ -109,8 +114,48 @@ void releasereadlock_I(void* ptr);
 bool getwritelock(void* ptr);
 void releasewritelock(void* ptr);
 
+// profiling mode of RAW version
+#ifdef RAWPROFILE
+
+#define TASKINFOLENGTH 10000
+//#define INTERRUPTINFOLENGTH 500
+
+bool stall;
+//bool isInterrupt;
+int totalexetime;
+
+typedef struct task_info {
+  char* taskName;
+  int startTime;
+  int endTime;
+  int exitIndex;
+  struct Queue * newObjs; 
+} TaskInfo;
+
+/*typedef struct interrupt_info {
+   int startTime;
+   int endTime;
+   } InterruptInfo;*/
+
+TaskInfo * taskInfoArray[TASKINFOLENGTH];
+int taskInfoIndex;
+bool taskInfoOverflow;
+/*InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
+   int interruptInfoIndex;
+   bool interruptInfoOverflow;*/
+int profilestatus[NUMCORES]; // records status of each core
+                             // 1: running tasks
+                             // 0: stall
+bool transProfileRequestMsg(int targetcore);
+void outputProfileData();
+#endif
+
 #ifdef RAW
+#ifdef RAWUSEIO
+int main(void) {
+#else
 void begin() {
+#endif
 #else
 int main(int argc, char **argv) {
 #endif
@@ -140,13 +185,17 @@ int main(int argc, char **argv) {
       numsendobjs[i] = 0;                   // assume all variables in RAW are local variables! MAY BE WRONG!!!
       numreceiveobjs[i] = 0;
     }
+#ifdef RAWPROFILE
+    for(i = 0; i < NUMCORES; ++i) {
+      profilestatus[i] = 1;
+    }
+#endif
   }
   self_numsendobjs = 0;
   self_numreceiveobjs = 0;
   for(i = 0; i < 30; ++i) {
     msgdata[i] = -1;
   }
-  //msgdata = NULL;
   msgtype = -1;
   msgdataindex = 0;
   msglength = 30;
@@ -183,12 +232,20 @@ int main(int argc, char **argv) {
   raw_test_pass(0xee03);
 #endif
 
+#ifdef RAWPROFILE
+  stall = false;
+  //isInterrupt = true;
+  totalexetime = -1;
+  taskInfoIndex = 0;
+  /*interruptInfoIndex = 0;
+     taskInfoOverflow = false;
+     interruptInfoOverflow = false;*/
+#endif
+
 #ifdef INTERRUPT
   if (corenum < NUMCORES) {
     // set up interrupts
     setup_ints();
-    //setup_interrupts();
-    //start_gdn_avail_ints(recvMsg);
     raw_user_interrupts_on();
 #ifdef RAWDEBUG
     raw_test_pass(0xee04);
@@ -265,7 +322,6 @@ int main(int argc, char **argv) {
     }
   }
 
-  //pthread_exit(NULL);
   while(true) {
   }
 }
@@ -298,6 +354,21 @@ void run(void* arg) {
   if(corenum > NUMCORES - 1) {
     failedtasks = NULL;
     activetasks = NULL;
+/*#ifdef RAWPROFILE
+        raw_test_pass(0xee01);
+        raw_test_pass_reg(taskInfoIndex);
+        raw_test_pass_reg(taskInfoOverflow);
+        if(!taskInfoOverflow) {
+        TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
+        taskInfoArray[taskInfoIndex] = taskInfo;
+        taskInfo->taskName = "msg handling";
+        taskInfo->startTime = raw_get_cycle();
+        taskInfo->endTime = -1;
+        }
+ #endif*/
+#ifdef RAWPROFILE
+    //isInterrupt = false;
+#endif
     while(true) {
       receiveObject();
     }
@@ -339,11 +410,6 @@ void run(void* arg) {
 #endif
 
   while(true) {
-/*#ifndef INTERRUPT
-          while(receiveObject() != -1) {
-          }
- #endif*/
-
     // check if there are new active tasks can be executed
     executetasks();
 
@@ -360,48 +426,81 @@ void run(void* arg) {
     tocontinue = false;
 #ifdef RAWDEBUG
     raw_test_pass(0xee0d);
+#endif
+#ifdef RAWPROFILE
+    {
+      bool isChecking = false;
+      if(!isEmpty(&objqueue)) {
+       if(!taskInfoOverflow) {
+         TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
+         taskInfoArray[taskInfoIndex] = taskInfo;
+         taskInfo->taskName = "objqueue checking";
+         taskInfo->startTime = raw_get_cycle();
+         taskInfo->endTime = -1;
+         taskInfo->exitIndex = -1;
+         taskInfo->newObjs = NULL;
+       }
+       isChecking = true;
+      }
 #endif
     while(!isEmpty(&objqueue)) {
       void * obj = NULL;
+      int * locks = NULL;
+      int numlocks = 0;
 #ifdef INTERRUPT
       raw_user_interrupts_off();
 #endif
+#ifdef RAWPROFILE
+      //isInterrupt = false;
+#endif
 #ifdef RAWDEBUG
       raw_test_pass(0xeee1);
 #endif
       sendStall = false;
       tocontinue = true;
       objitem = getTail(&objqueue);
-      //obj = objitem->objectptr;
       objInfo = (struct transObjInfo *)objitem->objectptr;
       obj = objInfo->objptr;
 #ifdef RAWDEBUG
       raw_test_pass_reg((int)obj);
 #endif
       // grab lock and flush the obj
-      getreadlock_I(obj);
-      while(!lockflag) {
-       receiveObject();
+      grount = 0;
+      if(((struct ___Object___ *)obj)->numlocks == 0) {
+       locks = obj;
+       numlocks = 1;
+      } else {
+       locks = ((struct ___Object___ *)obj)->locks;
+       numlocks = ((struct ___Object___ *)obj)->numlocks;
       }
-      grount = lockresult;
+      for(; numlocks > 0; numlocks--) {
+       getreadlock_I(locks);
+       while(!lockflag) {
+         receiveObject();
+       }
+       grount = grount || lockresult;
 #ifdef RAWDEBUG
-      raw_test_pass_reg(grount);
+       raw_test_pass_reg(grount);
 #endif
 
-      lockresult = 0;
-      lockobj = 0;
-      lockflag = false;
+       lockresult = 0;
+       lockobj = 0;
+       lockflag = false;
 #ifndef INTERRUPT
-      reside = false;
+       reside = false;
 #endif
 
+       if(grount == 0) {
+         goto grablockfail;
+       }
+
+       locks = (int*)(*locks);
+      }
+
       if(grount == 1) {
        int k = 0;
+       // flush the object
        raw_invalidate_cache_range((int)obj, classsize[((struct ___Object___ *)obj)->type]);
-       // flush the obj
-       /*for(k = 0; k < classsize[((struct ___Object___ *)obj)->type]; ++k) {
-               invalidateAddr(obj + k);
-          }*/
        // enqueue the object
        for(k = 0; k < objInfo->length; ++k) {
          int taskindex = objInfo->queues[2 * k];
@@ -414,18 +513,38 @@ void run(void* arg) {
          enqueueObject_I(obj, queues, 1);
        }
        removeItem(&objqueue, objitem);
-       releasereadlock_I(obj);
+       if(((struct ___Object___ *)obj)->numlocks == 0) {
+         locks = obj;
+         numlocks = 1;
+       } else {
+         locks = ((struct ___Object___ *)obj)->locks;
+         numlocks = ((struct ___Object___ *)obj)->numlocks;
+       }
+       for(; numlocks > 0; numlocks--) {
+         releasereadlock_I(locks);
+         locks = (int *)(*locks);
+       }
        RUNFREE(objInfo->queues);
        RUNFREE(objInfo);
-       /*enqueueObject_I(obj, NULL, 0);
-          removeItem(&objqueue, objitem);
-          releasereadlock_I(obj);*/
       } else {
+grablockfail:
        // can not get lock
        // put it at the end of the queue
        // and try to execute active tasks already enqueued first
        removeItem(&objqueue, objitem);
        addNewItem_I(&objqueue, objInfo);
+       if(((struct ___Object___ *)obj)->numlocks > 0) {
+         //release grabbed locks
+         numlocks = ((struct ___Object___ *)obj)->numlocks - numlocks;
+         locks = ((struct ___Object___ *)obj)->locks;
+         for(; numlocks > 0; numlocks--) {
+           releasereadlock_I(locks);
+           locks = (int *)(*locks);
+         }
+       }
+#ifdef RAWPROFILE
+       //isInterrupt = true;
+#endif
 #ifdef INTERRUPT
        raw_user_interrupts_on();
 #endif
@@ -438,6 +557,16 @@ void run(void* arg) {
       raw_test_pass(0xee0e);
 #endif
     }
+#ifdef RAWPROFILE
+    if(isChecking && (!taskInfoOverflow)) {
+      taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+      taskInfoIndex++;
+      if(taskInfoIndex == TASKINFOLENGTH) {
+       taskInfoOverflow = true;
+      }
+    }
+  }
+#endif
 #ifdef RAWDEBUG
     raw_test_pass(0xee0f);
 #endif
@@ -473,7 +602,8 @@ void run(void* arg) {
        }
        if(allStall) {
          // check if the sum of send objs and receive obj are the same
-         // yes->terminate
+         // yes->terminate; for profiling mode, yes->send request to all
+         // other cores to pour out profiling data
          // no->go on executing
          sumsendobj = 0;
          for(i = 0; i < NUMCORES; ++i) {
@@ -493,7 +623,57 @@ void run(void* arg) {
 #ifdef RAWDEBUG
            raw_test_pass(0xee11);
 #endif
+#ifdef RAWUSEIO
+           totalexetime = raw_get_cycle();
+#else
+           raw_test_pass(0xbbbbbbbb);
            raw_test_pass(raw_get_cycle());
+#endif
+
+           // profile mode, send msgs to other cores to request pouring
+           // out progiling data
+#ifdef RAWPROFILE
+#ifdef INTERRUPT
+           // reopen gdn_avail interrupts
+           raw_user_interrupts_on();
+#endif
+           for(i = 1; i < NUMCORES; ++i) {
+             transProfileRequestMsg(i);
+           }
+           // pour profiling data on startup core
+           outputProfileData();
+           while(true) {
+#ifdef INTERRUPT
+             raw_user_interrupts_off();
+#endif
+             profilestatus[corenum] = 0;
+             // check the status of all cores
+             allStall = true;
+#ifdef RAWDEBUG
+             raw_test_pass_reg(NUMCORES);
+#endif
+             for(i = 0; i < NUMCORES; ++i) {
+#ifdef RAWDEBUG
+               raw_test_pass(0xe000 + profilestatus[i]);
+#endif
+               if(profilestatus[i] != 0) {
+                 allStall = false;
+                 break;
+               }
+             }
+             if(!allStall) {
+               int halt = 10000;
+#ifdef INTERRUPT
+               raw_user_interrupts_on();
+#endif
+               while(halt--) {
+               }
+             } else {
+               break;
+             }
+           }
+#endif
+
            raw_test_done(1);                                   // All done.
          }
        }
@@ -504,6 +684,9 @@ void run(void* arg) {
        if(!sendStall) {
 #ifdef RAWDEBUG
          raw_test_pass(0xee12);
+#endif
+#ifdef RAWPROFILE
+         if(!stall) {
 #endif
          if(isfirst) {
            // wait for some time
@@ -525,6 +708,9 @@ void run(void* arg) {
            sendStall = transStallMsg(STARTUPCORE);
            isfirst = true;
          }
+#ifdef RAWPROFILE
+       }
+#endif
        } else {
          isfirst = true;
 #ifdef RAWDEBUG
@@ -547,7 +733,7 @@ void run(void* arg) {
   while(true) {
     switch(receiveObject()) {
     case 0: {
-      printf("[run, %d] receive an object\n", numofcore);
+      //printf("[run, %d] receive an object\n", numofcore);
       sendStall = false;
       // received an object
       // check if there are new active tasks can be executed
@@ -645,15 +831,6 @@ void run(void* arg) {
       break;
     }
 
-      /* case 3: {
-                               printf("[run, %d] receive a terminate msg\n", numofcore);
-                               // receive a terminate Msg
-                               assert(STARTUPCORE != corenum); // only non-startup core can receive such msg
-                               mq_close(mqd[corenum]);
-                               fflush(stdout);
-                               exit(0);
-                               break;
-                       }*/
     default: {
       printf("[run, %d] Error: invalid message type.\n", numofcore);
       fflush(stdout);
@@ -690,12 +867,13 @@ void createstartupobject(int argc, char ** argv) {
 
   startupobject->isolate = 1;
   startupobject->version = 0;
+  startupobject->numlocks = 0;
+  startupobject->locks = NULL;
 
   /* Set initialized flag for startup object */
   flagorandinit(startupobject,1,0xFFFFFFFF);
   enqueueObject(startupobject, NULL, 0);
 #ifdef RAW
-  //flushAll();
   raw_flush_entire_cache();
 #endif
 }
@@ -1267,6 +1445,37 @@ void calCoords(int core_num, int* coordY, int* coordX) {
 }
 #endif
 
+void addAliasLock(void * ptr, int lock) {
+  struct ___Object___ * obj = (struct ___Object___ *)ptr;
+  if(obj->numlocks == 0) {
+    // originally no alias locks associated
+    obj->locks = (int *)lock;
+    *(obj->locks) = 0;
+    obj->numlocks++;
+  } else {
+    // already have some alias locks
+    // insert the new lock into the sorted lock linklist
+    int prev, next;
+    prev = next = (int)obj->locks;
+    while(next != 0) {
+      if(next < lock) {
+       // next is less than lock, move to next node
+       prev = next;
+       next = *((int *)next);
+      } else if(next == lock) {
+       // already have this lock, do nothing
+       return;
+      } else {
+       // insert the lock between prev and next
+       break;
+      }
+    }
+    *(int *)prev = lock;
+    *(int *)lock = next;
+    obj->numlocks++;
+  }
+}
+
 /* Message format for RAW version:
  *      type + Msgbody
  * type: 0 -- transfer object
@@ -1275,12 +1484,16 @@ void calCoords(int core_num, int* coordY, int* coordX) {
  *       3 -- lock grount
  *       4 -- lock deny
  *       5 -- lock release
+ *       6 -- transfer profile output msg
+ *       7 -- transfer profile output finish msg
  *
  * ObjMsg: 0 + size of msg + obj's address + (task index + param index)+
  * StallMsg: 1 + corenum + sendobjs + receiveobjs (size is always 4 * sizeof(int))
  * LockMsg: 2 + lock type + obj pointer + request core (size is always 4 * sizeof(int))
  *          3/4/5 + lock type + obj pointer (size is always 3 * sizeof(int))
  *          lock type: 0 -- read; 1 -- write
+ * ProfileMsg: 6 + totalexetime (size is always 2 * sizeof(int))
+ *             7 + corenum (size is always 2 * sizeof(int))
  */
 
 // transfer an object to targetcore
@@ -1290,21 +1503,15 @@ void transferObject(struct transObjInfo * transObj) {
   int type=((int *)obj)[0];
   int size=classsize[type];
   int targetcore = transObj->targetcore;
-  //assert(type < NUMCLASSES); // can only transfer normal object
 
 #ifdef RAW
   unsigned msgHdr;
   int self_y, self_x, target_y, target_x;
-  //int isshared = 0;
   // for 32 bit machine, the size of fixed part is always 3 words
-  //int msgsize = sizeof(int) * 2 + sizeof(void *);
   int msgsize = 3 + transObj->length * 2;
   int i = 0;
 
   struct ___Object___ * newobj = (struct ___Object___ *)obj;
-  /*if(0 == newobj->isolate) {
-          isshared = 1;
-     }*/
 
   calCoords(corenum, &self_y, &self_x);
   calCoords(targetcore, &target_y, &target_x);
@@ -1327,7 +1534,7 @@ void transferObject(struct transObjInfo * transObj) {
 #ifdef RAWDEBUG
   raw_test_pass_reg(msgsize);
 #endif
-  gdn_send(obj);
+  gdn_send((int)obj);
 #ifdef RAWDEBUG
   raw_test_pass_reg(obj);
 #endif
@@ -1423,12 +1630,6 @@ void transferObject(struct transObjInfo * transObj) {
     fflush(stdout);
     exit(-1);
   }
-  /*struct ___Object___ * newobj = (struct ___Object___ *)obj;
-     if(0 == newobj->isolate) {
-          newobj = RUNMALLOC(size);
-          memcpy(newobj, obj, size);
-          newobj->original=obj;
-     }*/
   struct transObjInfo * tmptransObj = RUNMALLOC(sizeof(struct transObjInfo));
   memcpy(tmptransObj, transObj, sizeof(struct transObjInfo));
   int * tmpqueue = RUNMALLOC(sizeof(int)*2*tmptransObj->length);
@@ -1593,6 +1794,264 @@ bool transStallMsg(int targetcore) {
 #endif
 }
 
+#ifdef RAWPROFILE
+// send profile request message to targetcore
+// format: 6
+bool transProfileRequestMsg(int targetcore) {
+  unsigned msgHdr;
+  int self_y, self_x, target_y, target_x;
+  // for 32 bit machine, the size is always 4 words
+  int msgsize = 2;
+
+  calCoords(corenum, &self_y, &self_x);
+  calCoords(targetcore, &target_y, &target_x);
+  // Build the message header
+  msgHdr = construct_dyn_hdr(0, msgsize, 0,             // msgsize word sent.
+                             self_y, self_x,
+                             target_y, target_x);
+  // start sending msgs, set msg sending flag
+  isMsgSending = true;
+  gdn_send(msgHdr);                     // Send the message header to EAST to handle fab(n - 1).
+#ifdef RAWDEBUG
+  raw_test_pass(0xbbbb);
+  raw_test_pass(0xb000 + targetcore);       // targetcore
+#endif
+  gdn_send(6);
+#ifdef RAWDEBUG
+  raw_test_pass(6);
+#endif
+  gdn_send(totalexetime);
+#ifdef RAWDEBUG
+  raw_test_pass_reg(totalexetime);
+  raw_test_pass(0xffff);
+#endif
+  // end of sending this msg, set sand msg flag false
+  isMsgSending = false;
+  // check if there are pending msgs
+  while(isMsgHanging) {
+    // get the msg from outmsgdata[]
+    // length + target + msg
+    outmsgleft = outmsgdata[outmsgindex++];
+    targetcore = outmsgdata[outmsgindex++];
+    calCoords(targetcore, &target_y, &target_x);
+    // Build the message header
+    msgHdr = construct_dyn_hdr(0, outmsgleft, 0,                        // msgsize word sent.
+                               self_y, self_x,
+                               target_y, target_x);
+    isMsgSending = true;
+    gdn_send(msgHdr);
+#ifdef RAWDEBUG
+    raw_test_pass(0xbbbb);
+    raw_test_pass(0xb000 + targetcore);             // targetcore
+#endif
+    while(outmsgleft-- > 0) {
+      gdn_send(outmsgdata[outmsgindex++]);
+#ifdef RAWDEBUG
+      raw_test_pass_reg(outmsgdata[outmsgindex - 1]);
+#endif
+    }
+#ifdef RAWDEBUG
+    raw_test_pass(0xffff);
+#endif
+    isMsgSending = false;
+#ifdef INTERRUPT
+    raw_user_interrupts_off();
+#endif
+    // check if there are still msg hanging
+    if(outmsgindex == outmsglast) {
+      // no more msgs
+      outmsgindex = outmsglast = 0;
+      isMsgHanging = false;
+    }
+#ifdef INTERRUPT
+    raw_user_interrupts_on();
+#endif
+  }
+  return true;
+}
+
+// output the profiling data
+void outputProfileData() {
+#ifdef RAWUSEIO
+  FILE * fp;
+  char fn[50];
+  int self_y, self_x;
+  char c_y, c_x;
+  int i;
+  int totaltasktime = 0;
+  int preprocessingtime = 0;
+  int objqueuecheckingtime = 0;
+  int postprocessingtime = 0;
+  //int interruptiontime = 0;
+  int other = 0;
+  int averagetasktime = 0;
+  int tasknum = 0;
+
+  for(i = 0; i < 50; i++) {
+    fn[i] = 0;
+  }
+
+  calCoords(corenum, &self_y, &self_x);
+  c_y = (char)self_y + '0';
+  c_x = (char)self_x + '0';
+  strcat(fn, "profile_");
+  strcat(fn, &c_x);
+  strcat(fn, "_");
+  strcat(fn, &c_y);
+  strcat(fn, ".rst");
+
+  if((fp = fopen(fn, "w+")) == NULL) {
+    fprintf(stderr, "fopen error\n");
+    return;
+  }
+
+  fprintf(fp, "Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
+  // output task related info
+  for(i = 0; i < taskInfoIndex; i++) {
+    TaskInfo* tmpTInfo = taskInfoArray[i];
+    int duration = tmpTInfo->endTime - tmpTInfo->startTime;
+    fprintf(fp, "%s, %d, %d, %d, %d", tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime, duration, tmpTInfo->exitIndex);
+       // summarize new obj info
+       if(tmpTInfo->newObjs != NULL) {
+               struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
+               struct RuntimeIterator * iter = NULL;
+               while(0 == isEmpty(tmpTInfo->newObjs)) {
+                       char * objtype = (char *)(getItem(tmpTInfo->newObjs));
+                       if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
+                               int num = 0;
+                               RuntimeHashget(nobjtbl, (int)objtype, &num);
+                               RuntimeHashremovekey(nobjtbl, (int)objtype);
+                               num++;
+                               RuntimeHashadd(nobjtbl, (int)objtype, num);
+                       } else {
+                               RuntimeHashadd(nobjtbl, (int)objtype, 1);
+                       }
+                       //fprintf(stderr, "new obj!\n");
+               }
+
+               // output all new obj info
+               iter = RuntimeHashcreateiterator(nobjtbl);
+               while(RunhasNext(iter)) {
+                       char * objtype = (char *)Runkey(iter);
+                       int num = Runnext(iter);
+                       fprintf(fp, ", %s, %d", objtype, num);
+               }
+       }
+       fprintf(fp, "\n");
+    if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
+      preprocessingtime += duration;
+    } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
+      postprocessingtime += duration;
+    } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
+      objqueuecheckingtime += duration;
+    } else {
+      totaltasktime += duration;
+      averagetasktime += duration;
+      tasknum++;
+    }
+  }
+
+  if(taskInfoOverflow) {
+    fprintf(stderr, "Caution: task info overflow!\n");
+  }
+
+  other = totalexetime - totaltasktime - preprocessingtime - postprocessingtime;
+  averagetasktime /= tasknum;
+
+  fprintf(fp, "\nTotal time: %d\n", totalexetime);
+  fprintf(fp, "Total task execution time: %d (%f%%)\n", totaltasktime, ((double)totaltasktime/(double)totalexetime)*100);
+  fprintf(fp, "Total objqueue checking time: %d (%f%%)\n", objqueuecheckingtime, ((double)objqueuecheckingtime/(double)totalexetime)*100);
+  fprintf(fp, "Total pre-processing time: %d (%f%%)\n", preprocessingtime, ((double)preprocessingtime/(double)totalexetime)*100);
+  fprintf(fp, "Total post-processing time: %d (%f%%)\n", postprocessingtime, ((double)postprocessingtime/(double)totalexetime)*100);
+  fprintf(fp, "Other time: %d (%f%%)\n", other, ((double)other/(double)totalexetime)*100);
+
+  fprintf(fp, "\nAverage task execution time: %d\n", averagetasktime);
+
+  fclose(fp);
+#else
+  int i = 0;
+  int j = 0;
+
+  raw_test_pass(0xdddd);
+  // output task related info
+  for(i= 0; i < taskInfoIndex; i++) {
+    TaskInfo* tmpTInfo = taskInfoArray[i];
+    char* tmpName = tmpTInfo->taskName;
+    int nameLen = strlen(tmpName);
+    raw_test_pass(0xddda);
+    for(j = 0; j < nameLen; j++) {
+      raw_test_pass_reg(tmpName[j]);
+    }
+    raw_test_pass(0xdddb);
+    raw_test_pass_reg(tmpTInfo->startTime);
+    raw_test_pass_reg(tmpTInfo->endTime);
+       raw_test_pass_reg(tmpTInfo->exitIndex);
+       if(tmpTInfo->newObjs != NULL) {
+               struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
+               struct RuntimeIterator * iter = NULL;
+               while(0 == isEmpty(tmpTInfo->newObjs)) {
+                       char * objtype = (char *)(getItem(tmpTInfo->newObjs));
+                       if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
+                               int num = 0;
+                               RuntimeHashget(nobjtbl, (int)objtype, &num);
+                               RuntimeHashremovekey(nobjtbl, (int)objtype);
+                               num++;
+                               RuntimeHashadd(nobjtbl, (int)objtype, num);
+                       } else {
+                               RuntimeHashadd(nobjtbl, (int)objtype, 1);
+                       }
+               }
+
+               // ouput all new obj info
+               iter = RuntimeHashcreateiterator(nobjtbl);
+               while(RunhasNext(iter)) {
+                       char * objtype = (char *)Runkey(iter);
+                       int num = Runnext(iter);
+                       int nameLen = strlen(objtype);
+                       raw_test_pass(0xddda);
+                       for(j = 0; j < nameLen; j++) {
+                               raw_test_pass_reg(objtype[j]);
+                       }
+                       raw_test_pass(0xdddb);
+                       raw_test_pass_reg(num);
+               }
+       }
+    raw_test_pass(0xdddc);
+  }
+
+  if(taskInfoOverflow) {
+    raw_test_pass(0xefee);
+  }
+
+  // output interrupt related info
+  /*for(i = 0; i < interruptInfoIndex; i++) {
+       InterruptInfo* tmpIInfo = interruptInfoArray[i];
+       raw_test_pass(0xddde);
+       raw_test_pass_reg(tmpIInfo->startTime);
+       raw_test_pass_reg(tmpIInfo->endTime);
+       raw_test_pass(0xdddf);
+     }
+
+     if(interruptInfoOverflow) {
+       raw_test_pass(0xefef);
+     }*/
+
+  raw_test_pass(0xeeee);
+#endif
+}
+
+inline void setTaskExitIndex(int index) {
+       taskInfoArray[taskInfoIndex]->exitIndex = index;
+}
+
+inline void addNewObjInfo(void * nobj) {
+       if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
+               taskInfoArray[taskInfoIndex]->newObjs = createQueue();
+       }
+       addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
+}
+#endif
+
 // receive object transferred from other cores
 // or the terminate message from other cores
 // NOTICE: following format is for threadsimulate version only
@@ -1620,6 +2079,14 @@ int receiveObject() {
 #endif
     return -1;
   }
+#ifdef RAWPROFILE
+  /*if(isInterrupt && (!interruptInfoOverflow)) {
+     // raw_test_pass(0xffff);
+     interruptInfoArray[interruptInfoIndex] = RUNMALLOC_I(sizeof(struct interrupt_info));
+     interruptInfoArray[interruptInfoIndex]->startTime = raw_get_cycle();
+     interruptInfoArray[interruptInfoIndex]->endTime = -1;
+     }*/
+#endif
 msg:
 #ifdef RAWDEBUG
   raw_test_pass(0xcccc);
@@ -1627,7 +2094,11 @@ msg:
   while((gdn_input_avail() != 0) && (msgdataindex < msglength)) {
     msgdata[msgdataindex] = gdn_receive();
     if(msgdataindex == 0) {
-      if(msgdata[0] > 2) {
+      if(msgdata[0] == 7) {
+       msglength = 2;
+      } else if(msgdata[0] == 6) {
+       msglength = 2;
+      } else if(msgdata[0] > 2) {
        msglength = 3;
       } else if(msgdata[0] > 0) {
        msglength = 4;
@@ -1639,38 +2110,6 @@ msg:
     raw_test_pass_reg(msgdata[msgdataindex]);
 #endif
     msgdataindex++;
-
-    /*if(msgdataindex == 0) {
-            // type
-            msgtype = gdn_receive();
-            if(msgtype > 2) {
-                    msglength = 3;
-            } else {
-                    msglength = 4;
-            }
-            if(msgtype != 0) {
-                    msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
-                    msgdata[msgdataindex] = msgtype;
-            }
-     #ifdef RAWDEBUG
-            raw_test_pass_reg(msgtype);
-     #endif
-       } else if((msgdataindex == 1) && (msgtype == 0)) {
-            // object transfer msg
-            msglength = gdn_receive();
-            msgdata = (int *)RUNMALLOC_I(msglength * sizeof(int));
-            msgdata[0] = msgtype;
-            msgdata[msgdataindex] = msglength;
-     #ifdef RAWDEBUG
-            raw_test_pass_reg(msgdata[msgdataindex]);
-     #endif
-       } else {
-            msgdata[msgdataindex] = gdn_receive();
-     #ifdef RAWDEBUG
-            raw_test_pass_reg(msgdata[msgdataindex]);
-     #endif
-       }
-       msgdataindex++;*/
   }
 #ifdef RAWDEBUG
   raw_test_pass(0xffff);
@@ -1718,23 +2157,15 @@ msg:
          if(prev == NULL) {
            qitem = getTail(&objqueue);
          } else {
-           qitem = getNext(prev);
+           qitem = getNextQueueItem(prev);
          }
        }
-       //memcpy(transObj->queues, msgdata[3], sizeof(int)*(msglength - 3));
        addNewItem_I(&objqueue, (void *)transObj);
       }
       ++(self_numreceiveobjs);
 #ifdef RAWDEBUG
       raw_test_pass(0xe881);
 #endif
-      /*
-         addNewItem_I(&objqueue, (void *)data2);
-       ++(self_numreceiveobjs);
-       #ifdef RAWDEBUG
-         raw_test_pass(0xe881);
-       #endif
-       */
       break;
     }
 
@@ -1907,6 +2338,7 @@ msg:
       // receive lock release msg
       if(!RuntimeHashcontainskey(locktbl, data2)) {
        // no locks for this object, something is wrong
+       //raw_test_pass_reg(data2);
        raw_test_done(0xa004);
       } else {
        int rwlock_obj = 0;
@@ -1929,16 +2361,74 @@ msg:
       break;
     }
 
+#ifdef RAWPROFILE
+    case 6: {
+      // receive an output request msg
+      if(corenum == STARTUPCORE) {
+       // startup core can not receive profile output finish msg
+       raw_test_done(0xa00a);
+      }
+      {
+       int msgsize = 2;
+       stall = true;
+       totalexetime = data1;
+       outputProfileData();
+       /*if(data1 >= NUMCORES) {
+               raw_test_pass(0xee04);
+          raw_test_pass_reg(taskInfoIndex);
+          raw_test_pass_reg(taskInfoOverflow);
+               if(!taskInfoOverflow) {
+                       taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+                       taskInfoIndex++;
+                       if(taskInfoIndex == TASKINFOLENGTH) {
+                               taskInfoOverflow = true;
+                       }
+               }
+          }*/
+       // no msg on sending, send it out
+       targetcore = STARTUPCORE;
+       calCoords(corenum, &self_y, &self_x);
+       calCoords(targetcore, &target_y, &target_x);
+       // Build the message header
+       msgHdr = construct_dyn_hdr(0, msgsize, 0,                                                               // msgsize word sent.
+                                  self_y, self_x,
+                                  target_y, target_x);
+       gdn_send(msgHdr);
+#ifdef RAWDEBUG
+       raw_test_pass(0xbbbb);
+       raw_test_pass(0xb000 + targetcore);                                                 // targetcore
+#endif
+       gdn_send(7);
+#ifdef RAWDEBUG
+       raw_test_pass(7);
+#endif
+       gdn_send(corenum);
+#ifdef RAWDEBUG
+       raw_test_pass_reg(corenum);
+       raw_test_pass(0xffff);
+#endif
+      }
+      break;
+    }
+
+    case 7: {
+      // receive a profile output finish msg
+      if(corenum != STARTUPCORE) {
+       // non startup core can not receive profile output finish msg
+       raw_test_done(0xa00b);
+      }
+      profilestatus[data1] = 0;
+      break;
+    }
+#endif
+
     default:
       break;
     }
-    //RUNFREE(msgdata);
-    //msgdata = NULL;
     for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
       msgdata[msgdataindex] = -1;
     }
     msgtype = -1;
-    //msgdataindex = 0;
     msglength = 30;
 #ifdef RAWDEBUG
     raw_test_pass(0xe888);
@@ -1946,11 +2436,29 @@ msg:
     if(gdn_input_avail() != 0) {
       goto msg;
     }
+#ifdef RAWPROFILE
+/*    if(isInterrupt && (!interruptInfoOverflow)) {
+      interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
+      interruptInfoIndex++;
+      if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
+        interruptInfoOverflow = true;
+      }
+    }*/
+#endif
     return type;
   } else {
     // not a whole msg
 #ifdef RAWDEBUG
     raw_test_pass(0xe889);
+#endif
+#ifdef RAWPROFILE
+/*    if(isInterrupt && (!interruptInfoOverflow)) {
+      interruptInfoArray[interruptInfoIndex]->endTime = raw_get_cycle();
+      interruptInfoIndex++;
+      if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
+        interruptInfoOverflow = true;
+      }
+    }*/
 #endif
     return -2;
   }
@@ -1978,11 +2486,7 @@ msg:
     printf("<receiveObject> index: %d, sendobjs: %d, reveiveobjs: %d\n", index, numsendobjs[index], numreceiveobjs[index]);
     free(msgptr);
     return 2;
-  }       /*else if(((int*)msgptr)[0] == -2) {
-               // terminate msg
-               return 3;
-            } */
-  else {
+  } else {
     // an object
     if(numofcore == STARTUPCORE) {
       ++(numreceiveobjs[numofcore]);
@@ -2021,7 +2525,6 @@ bool getreadlock(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 4 words
-  //int msgsize = sizeof(int) * 4;
   int msgsize = 4;
   int tc = TOTALCORE;
 #ifdef INTERRUPT
@@ -2103,7 +2606,7 @@ bool getreadlock(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(0);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
 #endif
@@ -2218,7 +2721,6 @@ void releasereadlock(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 3 words
-  //int msgsize = sizeof(int) * 3;
   int msgsize = 3;
   int tc = TOTALCORE;
 #ifdef INTERRUPT
@@ -2271,7 +2773,7 @@ void releasereadlock(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(0);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
   raw_test_pass(0xffff);
@@ -2341,7 +2843,6 @@ bool getreadlock_I(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = ((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 4 words
-  //int msgsize = sizeof(int) * 4;
   int msgsize = 4;
 
   lockobj = (int)ptr;
@@ -2407,7 +2908,7 @@ bool getreadlock_I(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(0);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
 #endif
@@ -2424,7 +2925,6 @@ void releasereadlock_I(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = ((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 3 words
-  //int msgsize = sizeof(int) * 3;
   int msgsize = 3;
 
   if(targetcore == corenum) {
@@ -2461,7 +2961,7 @@ void releasereadlock_I(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(0);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
   raw_test_pass(0xffff);
@@ -2476,7 +2976,6 @@ bool getwritelock(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 4 words
-  //int msgsize = sizeof(int) * 4;
   int msgsize= 4;
   int tc = TOTALCORE;
 #ifdef INTERRUPT
@@ -2585,7 +3084,7 @@ bool getwritelock(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(1);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
 #endif
@@ -2703,7 +3202,6 @@ void releasewritelock(void * ptr) {
   int self_y, self_x, target_y, target_x;
   int targetcore = 0;       //((int)ptr >> 5) % TOTALCORE;
   // for 32 bit machine, the size is always 3 words
-  //int msgsize = sizeof(int) * 3;
   int msgsize = 3;
   int tc = TOTALCORE;
 #ifdef INTERRUPT
@@ -2768,7 +3266,7 @@ void releasewritelock(void * ptr) {
 #ifdef RAWDEBUG
   raw_test_pass(1);
 #endif
-  gdn_send(ptr);
+  gdn_send((int)ptr);
 #ifdef RAWDEBUG
   raw_test_pass_reg(ptr);
   raw_test_pass(0xffff);
@@ -3116,16 +3614,20 @@ newtask:
     /* See if there are any active tasks */
     if (hashsize(activetasks)>0) {
       int i;
+#ifdef RAWPROFILE
+      if(!taskInfoOverflow) {
+       TaskInfo* checkTaskInfo = RUNMALLOC(sizeof(struct task_info));
+       taskInfoArray[taskInfoIndex] = checkTaskInfo;
+       checkTaskInfo->taskName = "tpd checking";
+       checkTaskInfo->startTime = raw_get_cycle();
+       checkTaskInfo->endTime = -1;
+       checkTaskInfo->exitIndex = -1;
+       checkTaskInfo->newObjs = NULL;
+      }
+#endif
       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
       genfreekey(activetasks, currtpd);
 
-      /* Check if this task has failed, allow a task that contains optional objects to fire */
-      /*if (gencontains(failedtasks, currtpd)) {
-         // Free up task parameter descriptor
-         RUNFREE(currtpd->parameterArray);
-         RUNFREE(currtpd);
-         goto newtask;
-         }*/
       numparams=currtpd->task->numParameters;
       numtotal=currtpd->task->numTotal;
 
@@ -3135,6 +3637,8 @@ newtask:
       /* Make sure that the parameters are still in the queues */
       for(i=0; i<numparams; i++) {
        void * parameter=currtpd->parameterArray[i];
+       int * locks;
+       int numlocks;
 #ifdef RAW
 #ifdef RAWDEBUG
        raw_test_pass(0xe993);
@@ -3147,40 +3651,80 @@ newtask:
        }
        lock = true;
        // require locks for this parameter if it is not a startup object
-       getwritelock(parameter);
+       if(((struct ___Object___ *)parameter)->numlocks == 0) {
+         numlocks = 1;
+         locks = parameter;
+       } else {
+         numlocks = ((struct ___Object___ *)parameter)->numlocks;
+         locks = ((struct ___Object___ *)parameter)->locks;
+       }
+
        grount = 0;
+       for(; numlocks > 0; numlocks--) {
+         getwritelock(locks);
 
 #ifdef INTERRUPT
-       raw_user_interrupts_off();
+         raw_user_interrupts_off();
 #endif
-       while(!lockflag) {
-         receiveObject();
-       }
+#ifdef RAWPROFILE
+         //isInterrupt = false;
+#endif
+         while(!lockflag) {
+           receiveObject();
+         }
 #ifndef INTERRUPT
-       if(reside) {
-         while(receiveObject() != -1) {
+         if(reside) {
+           while(receiveObject() != -1) {
+           }
          }
-       }
 #endif
-       grount = lockresult;
+         grount = grount || lockresult;
 
-       lockresult = 0;
-       lockobj = 0;
-       lockflag = false;
+         lockresult = 0;
+         lockobj = 0;
+         lockflag = false;
 #ifndef INTERRUPT
-       reside = false;
+         reside = false;
+#endif
+#ifdef RAWPROFILE
+         //isInterrupt = true;
 #endif
 #ifdef INTERRUPT
-       raw_user_interrupts_on();
+         raw_user_interrupts_on();
 #endif
 
+         if(grount == 0) {
+           goto grablock_fail;
+         }
+         locks = (int *)(*locks);
+       }
+
        if(grount == 0) {
+grablock_fail:
 #ifdef RAWDEBUG
          raw_test_pass(0xe994);
 #endif
          // can not get the lock, try later
+         // first release all grabbed locks for this parameter
+         numlocks = ((struct ___Object___ *)parameter)->numlocks - numlocks;
+         locks = ((struct ___Object___ *)parameter)->locks;
+         for(; numlocks > 0; numlocks--) {
+           releasewritelock(locks);
+           locks = (int *)(*locks);
+         }
+         // then releas all grabbed locks for previous parameters
          for(j = 0; j < i; ++j) {
-           releasewritelock(taskpointerarray[j+OFFSET]);
+           if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
+             locks = taskpointerarray[j+OFFSET];
+             numlocks = 1;
+           } else {
+             locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
+             numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
+           }
+           for(; numlocks > 0; numlocks--) {
+             releasewritelock(locks);
+             locks = (int *)(*locks);
+           }
          }
          genputtable(activetasks, currtpd, currtpd);
          if(hashsize(activetasks) == 1) {
@@ -3189,15 +3733,21 @@ newtask:
            while(halt--) {
            }
          }
+#ifdef RAWPROFILE
+         // fail, set the end of the checkTaskInfo
+         if(!taskInfoOverflow) {
+           taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+           taskInfoIndex++;
+           if(taskInfoIndex == TASKINFOLENGTH) {
+             taskInfoOverflow = true;
+           }
+         }
+#endif
          goto newtask;
        }
        // flush the object
        {
          raw_invalidate_cache_range((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
-         /*int tmp = 0;
-            for(tmp = 0; tmp < classsize[((struct ___Object___ *)parameter)->type]; ++tmp) {
-                 invalidateAddr(parameter + tmp);
-            }*/
        }
 #endif
        tmpparam = (struct ___Object___ *)parameter;
@@ -3211,8 +3761,7 @@ newtask:
        if(0 == tmpparam->isolate) {
          isolateflags[i] = 0;
          // shared object, need to flush with current value
-         //if(!getreadlock(tmpparam->original)) {
-         //    // fail to get read lock of the original object, try this task later
+         // TODO: need modification according to added alias locks
          if(!getwritelock(tmpparam->original)) {
            // fail to get write lock, release all obtained locks and try this task later
            int j = 0;
@@ -3225,9 +3774,6 @@ newtask:
            goto newtask;
          }
          if(tmpparam->version != tmpparam->original->version) {
-           // some task on another core has changed this object
-           // flush this object
-           //memcpy(tmpparam, tmpparam->original, classsize[tmpparam->type]);
            // release all obtained locks
            int j = 0;
            for(j = 0; j < i; ++j) {
@@ -3253,8 +3799,6 @@ newtask:
                  free(enterflags);
              }
            }
-           // try to enqueue it again to check if it feeds other tasks;
-           //enqueueObject(tmpparam, NULL, 0);
            // Free up task parameter descriptor
            RUNFREE(currtpd->parameterArray);
            RUNFREE(currtpd);
@@ -3274,9 +3818,29 @@ newtask:
 #endif
            // release grabbed locks
            for(j = 0; j < i; ++j) {
-             releasewritelock(taskpointerarray[j+OFFSET]);
+             if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
+               numlocks = 1;
+               locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
+             } else {
+               numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
+               locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
+             }
+             for(; numlocks > 0; numlocks--) {
+               releasewritelock(locks);
+               locks = (int *)(*locks);
+             }
+           }
+           if(((struct ___Object___ *)parameter)->numlocks == 0) {
+             numlocks = 1;
+             locks = parameter;
+           } else {
+             numlocks = ((struct ___Object___ *)parameter)->numlocks;
+             locks = ((struct ___Object___ *)parameter)->locks;
+           }
+           for(; numlocks > 0; numlocks--) {
+             releasewritelock(locks);
+             locks = (int *)(*locks);
            }
-           releasewritelock(parameter);
            RUNFREE(currtpd->parameterArray);
            RUNFREE(currtpd);
            goto newtask;
@@ -3316,11 +3880,41 @@ newtask:
              free(enterflags);
            // release grabbed locks
            for(j = 0; j < i; ++j) {
-             releasewritelock(taskpointerarray[j+OFFSET]);
+             if(((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks == 0) {
+               numlocks = 1;
+               locks = taskpointerarray[j+OFFSET];
+             } else {
+               numlocks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->numlocks;
+               locks = ((struct ___Object___ *)taskpointerarray[j+OFFSET])->locks;
+             }
+             for(; numlocks > 0; numlocks--) {
+               releasewritelock(locks);
+               locks = (int *)(*locks);
+             }
+           }
+           if(((struct ___Object___ *)parameter)->numlocks == 0) {
+             numlocks = 1;
+             locks = parameter;
+           } else {
+             numlocks = ((struct ___Object___ *)parameter)->numlocks;
+             locks = ((struct ___Object___ *)parameter)->locks;
+           }
+           for(; numlocks > 0; numlocks--) {
+             releasewritelock(locks);
+             locks = (int *)(*locks);
            }
-           releasewritelock(parameter);
            RUNFREE(currtpd->parameterArray);
            RUNFREE(currtpd);
+#ifdef RAWPROFILE
+           // fail, set the end of the checkTaskInfo
+           if(!taskInfoOverflow) {
+             taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+             taskInfoIndex++;
+             if(taskInfoIndex == TASKINFOLENGTH) {
+               taskInfoOverflow = true;
+             }
+           }
+#endif
            goto newtask;
          }
        }
@@ -3391,6 +3985,7 @@ parameterpresent:
 #ifdef RAWDEBUG
          raw_test_pass_reg(x);
 #endif
+         raw_test_pass_reg(x);
          raw_test_done(0xa009);
 #else
          exit(-1);
@@ -3404,10 +3999,33 @@ parameterpresent:
             }*/
          /* Actually call task */
 #ifdef PRECISE_GC
-                                                         ((int *)taskpointerarray)[0]=currtpd->numParameters;
+                                                                                 ((int *)taskpointerarray)[0]=currtpd->numParameters;
          taskpointerarray[1]=NULL;
 #endif
 execute:
+#ifdef RAWPROFILE
+         {
+           // check finish, set the end of the checkTaskInfo
+           if(!taskInfoOverflow) {
+             taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+             taskInfoIndex++;
+             if(taskInfoIndex == TASKINFOLENGTH) {
+               taskInfoOverflow = true;
+             }
+           }
+         }
+         if(!taskInfoOverflow) {
+           // new a taskInfo for the task execution
+           TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
+           taskInfoArray[taskInfoIndex] = taskInfo;
+           taskInfo->taskName = currtpd->task->name;
+           taskInfo->startTime = raw_get_cycle();
+           taskInfo->endTime = -1;
+               taskInfo->exitIndex = -1;
+               taskInfo->newObjs = NULL;
+         }
+#endif
+
          if(debugtask) {
 #ifndef RAW
            printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
@@ -3419,39 +4037,92 @@ execute:
          } else {
            ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
          }
+#ifdef RAWPROFILE
+         // task finish, set the end of the checkTaskInfo
+         if(!taskInfoOverflow) {
+           taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+           taskInfoIndex++;
+           if(taskInfoIndex == TASKINFOLENGTH) {
+             taskInfoOverflow = true;
+           }
+         }
+         // new a PostTaskInfo for the post-task execution
+         if(!taskInfoOverflow) {
+           TaskInfo* postTaskInfo = RUNMALLOC(sizeof(struct task_info));
+           taskInfoArray[taskInfoIndex] = postTaskInfo;
+           postTaskInfo->taskName = "post task execution";
+           postTaskInfo->startTime = raw_get_cycle();
+           postTaskInfo->endTime = -1;
+               postTaskInfo->exitIndex = -1;
+               postTaskInfo->newObjs = NULL;
+         }
+#endif
 #ifdef RAWDEBUG
          raw_test_pass(0xe998);
          raw_test_pass_reg(lock);
-                 #endif
+#endif
 
          if(lock) {
 #ifdef RAW
            for(i = 0; i < numparams; ++i) {
              int j = 0;
              struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
+             int numlocks;
+             int * locks;
 #ifdef RAWDEBUG
              raw_test_pass(0xe999);
              raw_test_pass(0xdd100000 + tmpparam->flag);
 #endif
-             releasewritelock(tmpparam);
+             if(tmpparam->numlocks == 0) {
+               numlocks = 1;
+               locks = (int*)tmpparam;
+             } else {
+               numlocks = tmpparam->numlocks;
+               locks = tmpparam->locks;
+             }
+             for(; numlocks > 0; numlocks--) {
+               releasewritelock(locks);
+               locks = (int *)(*locks);
+             }
            }
 #elif defined THREADSIMULATE
            for(i = 0; i < numparams; ++i) {
              if(0 == isolateflags[i]) {
                struct ___Object___ * tmpparam = (struct ___Object___ *)taskpointerarray[i+OFFSET];
-               releasewritelock(tmpparam);
+               if(tmpparam->numlocks == 0) {
+                 numlocks = 1;
+                 locks = (int*)tmpparam;
+               } else {
+                 numlocks = tmpparam->numlocks;
+                 locks = tmpparam->locks;
+               }
+               for(; numlocks > 0; numlocks--) {
+                 releasewritelock(locks);
+                 locks = (int *)(*locks);
+               }
              }
            }
 #endif
          }
 
+#ifdef RAWPROFILE
+         // post task execution finish, set the end of the postTaskInfo
+         if(!taskInfoOverflow) {
+           taskInfoArray[taskInfoIndex]->endTime = raw_get_cycle();
+           taskInfoIndex++;
+           if(taskInfoIndex == TASKINFOLENGTH) {
+             taskInfoOverflow = true;
+           }
+         }
+#endif
+
 #if 0
 #ifndef RAW
          freeRuntimeHash(forward);
          freeRuntimeHash(reverse);
+         freemalloc();
 #endif
 #endif
-         freemalloc();
          // Free up task parameter descriptor
          RUNFREE(currtpd->parameterArray);
          RUNFREE(currtpd);