#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
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
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
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;
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);
}
}
- //pthread_exit(NULL);
while(true) {
}
}
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();
}
#endif
while(true) {
-/*#ifndef INTERRUPT
- while(receiveObject() != -1) {
- }
- #endif*/
-
// check if there are new active tasks can be executed
executetasks();
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];
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
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
}
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) {
#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.
}
}
if(!sendStall) {
#ifdef RAWDEBUG
raw_test_pass(0xee12);
+#endif
+#ifdef RAWPROFILE
+ if(!stall) {
#endif
if(isfirst) {
// wait for some time
sendStall = transStallMsg(STARTUPCORE);
isfirst = true;
}
+#ifdef RAWPROFILE
+ }
+#endif
} else {
isfirst = true;
#ifdef RAWDEBUG
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
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);
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
}
}
#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
* 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
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);
#ifdef RAWDEBUG
raw_test_pass_reg(msgsize);
#endif
- gdn_send(obj);
+ gdn_send((int)obj);
#ifdef RAWDEBUG
raw_test_pass_reg(obj);
#endif
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);
#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
#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);
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;
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);
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;
}
// 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;
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);
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;
}
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]);
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
#ifdef RAWDEBUG
raw_test_pass(0);
#endif
- gdn_send(ptr);
+ gdn_send((int)ptr);
#ifdef RAWDEBUG
raw_test_pass_reg(ptr);
#endif
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
#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);
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;
#ifdef RAWDEBUG
raw_test_pass(0);
#endif
- gdn_send(ptr);
+ gdn_send((int)ptr);
#ifdef RAWDEBUG
raw_test_pass_reg(ptr);
#endif
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) {
#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);
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
#ifdef RAWDEBUG
raw_test_pass(1);
#endif
- gdn_send(ptr);
+ gdn_send((int)ptr);
#ifdef RAWDEBUG
raw_test_pass_reg(ptr);
#endif
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
#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);
/* 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;
/* 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);
}
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) {
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;
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;
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) {
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);
#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;
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;
}
}
#ifdef RAWDEBUG
raw_test_pass_reg(x);
#endif
+ raw_test_pass_reg(x);
raw_test_done(0xa009);
#else
exit(-1);
}*/
/* 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));
} 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);