3 #include "multicoretaskprofile.h"
5 int profilestatus[NUMCORESACTIVE]; // records status of each core
8 ///////////////////////////////////////////////////////////////////////////////
9 // This global variable records the profiling information of tasks including
10 // when the task starts and ends, the exit path of each execution of the task,
11 // and how many new objs are created as well as the type of the new objs. There
12 // also have an index indicates how many tasks have been recorded and if the
13 // buffer has overflowed. These profile information is supposed to be dumped
14 // out before the execution of the program is terminated.
16 // Maintaining protocols:
17 // INIT_TASKPROFILE_DATA() initializes this variable and should be invoked
18 // before executing any tasks.
20 // PROFILE_TASK_START() creates a new item to record a task's execution. It
21 // should be invoked right before starting a new task as it also records
22 // the start time of a task's execution.
24 // PROFILE_TASK_END() records the stop time of a task's execution and close
25 // a task record item. It should be invoked immediately when a task
26 // finishes execution.
28 // The following functions record corresponding task information during the
29 // execution of a task and should be wrapped with a
30 // PROFILE_TASK_START()/PROFILE_TASK_END() pair.
31 // setTaskExitIndex() records the exit path of the execution.
32 // addNewObjInfo() records the information of new objs created by the task.
34 // This variable can only be updated with the functions/MACROs listed above!
35 ///////////////////////////////////////////////////////////////////////////////
36 TaskProfile_t taskProfileInfo;
38 #ifdef PROFILE_INTERRUPT
39 ///////////////////////////////////////////////////////////////////////////////
40 // This global variable records the profiling information of the interrupts
41 // happended during the execution of a program. It records when an interrupt
42 // happended and when it returns to normal program execution.
44 // Maintaining protocols:
45 // INIT_TASKPROFILE_DATA() initializes this variable and should be invoked
46 // before executing any tasks.
48 // PROFILE_INTERRUPT_START() creates a new item to record the information
49 // of an interrupt. It should be invoked at the very beginning of an
52 // PROFILE_INTERRUPT_END() records when an interrupt returns from its
53 // handler. It should be invoked right before an interrupt handler returns.
55 // This variable can only be updated with the functions/MACROs listed above!
56 ///////////////////////////////////////////////////////////////////////////////
57 InterruptProfile_t interruptProfileInfo;
60 void inittaskprofiledata() {
63 taskProfileInfo.taskInfoIndex = 0;
64 taskProfileInfo.taskInfoOverflow = false;
65 #ifdef PROFILE_INTERRUPT
66 interruptProfileInfo.interruptInfoIndex = 0;
67 interruptProfileInfo.interruptInfoOverflow = false;
71 // output the profiling data
72 void outputProfileData() {
75 unsigned long long totaltasktime = 0;
76 unsigned long long preprocessingtime = 0;
77 unsigned long long objqueuecheckingtime = 0;
78 unsigned long long postprocessingtime = 0;
79 unsigned long long other = 0;
80 unsigned long long averagetasktime = 0;
83 printf("Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
84 // output task related info
85 for(i = 0; i < taskProfileInfo.taskInfoIndex; i++) {
86 TaskInfo* tmpTInfo = taskProfileInfo.taskInfoArray[i];
87 unsigned long long duration = tmpTInfo->endTime - tmpTInfo->startTime;
88 printf("%s, %lld, %lld, %lld, %lld",tmpTInfo->taskName,tmpTInfo->startTime,tmpTInfo->endTime,duration,tmpTInfo->exitIndex);
89 // summarize new obj info
90 if(tmpTInfo->newObjs != NULL) {
91 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
92 struct RuntimeIterator * iter = NULL;
93 while(0 == isEmpty(tmpTInfo->newObjs)) {
94 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
95 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
97 RuntimeHashget(nobjtbl, (int)objtype, &num);
98 RuntimeHashremovekey(nobjtbl, (int)objtype);
100 RuntimeHashadd(nobjtbl, (int)objtype, num);
102 RuntimeHashadd(nobjtbl, (int)objtype, 1);
106 // output all new obj info
107 iter = RuntimeHashcreateiterator(nobjtbl);
108 while(RunhasNext(iter)) {
109 char * objtype = (char *)Runkey(iter);
110 int num = Runnext(iter);
111 printf(", %s, %d", objtype, num);
115 if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
116 preprocessingtime += duration;
117 } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
118 postprocessingtime += duration;
119 } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
120 objqueuecheckingtime += duration;
122 totaltasktime += duration;
123 averagetasktime += duration;
128 if(taskProfileInfo.taskInfoOverflow) {
129 printf("Caution: task info overflow!\n");
132 other = totalexetime-totaltasktime-preprocessingtime-postprocessingtime;
133 averagetasktime /= tasknum;
135 printf("\nTotal time: %lld\n", totalexetime);
136 printf("Total task execution time: %lld (%d%%)\n",totaltasktime,(int)(((double)totaltasktime/(double)totalexetime)*100));
137 printf("Total objqueue checking time: %lld (%d%%)\n",objqueuecheckingtime,(int)(((double)objqueuecheckingtime/(double)totalexetime)*100));
138 printf("Total pre-processing time: %lld (%d%%)\n", preprocessingtime,(int)(((double)preprocessingtime/(double)totalexetime)*100));
139 printf("Total post-processing time: %lld (%d%%)\n", postprocessingtime,(int)(((double)postprocessingtime/(double)totalexetime)*100));
140 printf("Other time: %lld (%d%%)\n", other,(int)(((double)other/(double)totalexetime)*100));
142 printf("\nAverage task execution time: %lld\n", averagetasktime);
148 BAMBOO_PRINT(0xdddd);
149 // output task related info
150 for(i= 0; i < taskProfileInfo.taskInfoIndex; i++) {
151 TaskInfo* tmpTInfo = taskInfoArray[i];
152 char* tmpName = tmpTInfo->taskName;
153 int nameLen = strlen(tmpName);
154 BAMBOO_PRINT(0xddda);
155 for(j = 0; j < nameLen; j++) {
156 BAMBOO_PRINT_REG(tmpName[j]);
158 BAMBOO_PRINT(0xdddb);
159 BAMBOO_PRINT_REG(tmpTInfo->startTime);
160 BAMBOO_PRINT_REG(tmpTInfo->endTime);
161 BAMBOO_PRINT_REG(tmpTInfo->exitIndex);
162 if(tmpTInfo->newObjs != NULL) {
163 struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
164 struct RuntimeIterator * iter = NULL;
165 while(0 == isEmpty(tmpTInfo->newObjs)) {
166 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
167 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
169 RuntimeHashget(nobjtbl, (int)objtype, &num);
170 RuntimeHashremovekey(nobjtbl, (int)objtype);
172 RuntimeHashadd(nobjtbl, (int)objtype, num);
174 RuntimeHashadd(nobjtbl, (int)objtype, 1);
178 // ouput all new obj info
179 iter = RuntimeHashcreateiterator(nobjtbl);
180 while(RunhasNext(iter)) {
181 char * objtype = (char *)Runkey(iter);
182 int num = Runnext(iter);
183 int nameLen = strlen(objtype);
184 BAMBOO_PRINT(0xddda);
185 for(j = 0; j < nameLen; j++) {
186 BAMBOO_PRINT_REG(objtype[j]);
188 BAMBOO_PRINT(0xdddb);
189 BAMBOO_PRINT_REG(num);
192 BAMBOO_PRINT(0xdddc);
195 if(taskProfileInfo.taskInfoOverflow) {
196 BAMBOO_PRINT(0xefee);
199 #ifdef PROFILE_INTERRUPT
200 // output interrupt related info
201 for(i = 0; i < interruptProfileInfo.interruptInfoIndex; i++) {
202 InterruptInfo* tmpIInfo = interruptProfileInfo.interruptInfoArray[i];
203 BAMBOO_PRINT(0xddde);
204 BAMBOO_PRINT_REG(tmpIInfo->startTime);
205 BAMBOO_PRINT_REG(tmpIInfo->endTime);
206 BAMBOO_PRINT(0xdddf);
209 if(interruptProfileInfo.interruptInfoOverflow) {
210 BAMBOO_PRINT(0xefef);
214 BAMBOO_PRINT(0xeeee);