changes
[IRC.git] / Robust / src / Runtime / bamboo / multicoretaskprofile.c
1 #ifdef TASK
2 #ifdef PROFILE
3 #include "multicoretaskprofile.h"
4
5 int profilestatus[NUMCORESACTIVE]; // records status of each core
6                                    // 1: running tasks
7                                    // 0: stall
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.
15 //
16 // Maintaining protocols: 
17 //     INIT_TASKPROFILE_DATA() initializes this variable and should be invoked 
18 //     before executing any tasks.
19 //
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.
23 //
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.
27 // 
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.
33 //
34 //   This variable can only be updated with the functions/MACROs listed above! 
35 ///////////////////////////////////////////////////////////////////////////////
36 TaskProfile_t taskProfileInfo;
37
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.
43 //
44 // Maintaining protocols: 
45 //     INIT_TASKPROFILE_DATA() initializes this variable and should be invoked 
46 //     before executing any tasks.
47 //
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
50 //     interrupt handler.
51 //
52 //     PROFILE_INTERRUPT_END() records when an interrupt returns from its 
53 //     handler.  It should be invoked right before an interrupt handler returns.
54 // 
55 //   This variable can only be updated with the functions/MACROs listed above! 
56 ///////////////////////////////////////////////////////////////////////////////
57 InterruptProfile_t interruptProfileInfo;
58 #endif
59
60 void inittaskprofiledata() {
61   stall = false;
62   totalexetime = -1;
63   taskProfileInfo.taskInfoIndex = 0;
64   taskProfileInfo.taskInfoOverflow = false;
65 #ifdef PROFILE_INTERRUPT
66   interruptProfileInfo.interruptInfoIndex = 0;
67   interruptProfileInfo.interruptInfoOverflow = false;
68 #endif 
69 }
70
71 // output the profiling data
72 void outputProfileData() {
73 #ifdef USEIO
74   int i;
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;
81   int tasknum = 0;
82
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))) {
96           int num = 0;
97           RuntimeHashget(nobjtbl, (int)objtype, &num);
98           RuntimeHashremovekey(nobjtbl, (int)objtype);
99           num++;
100           RuntimeHashadd(nobjtbl, (int)objtype, num);
101         } else {
102           RuntimeHashadd(nobjtbl, (int)objtype, 1);
103         }
104       }
105
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);
112       }
113     }
114     printf("\n");
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;
121     } else {
122       totaltasktime += duration;
123       averagetasktime += duration;
124       tasknum++;
125     }
126   }
127
128   if(taskProfileInfo.taskInfoOverflow) {
129     printf("Caution: task info overflow!\n");
130   }
131
132   other = totalexetime-totaltasktime-preprocessingtime-postprocessingtime;
133   averagetasktime /= tasknum;
134
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));
141
142   printf("\nAverage task execution time: %lld\n", averagetasktime);
143
144 #else
145   int i = 0;
146   int j = 0;
147
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]);
157     }
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))) {
168           int num = 0;
169           RuntimeHashget(nobjtbl, (int)objtype, &num);
170           RuntimeHashremovekey(nobjtbl, (int)objtype);
171           num++;
172           RuntimeHashadd(nobjtbl, (int)objtype, num);
173         } else {
174           RuntimeHashadd(nobjtbl, (int)objtype, 1);
175         }
176       }
177
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]);
187         }
188         BAMBOO_PRINT(0xdddb);
189         BAMBOO_PRINT_REG(num);
190       }
191     }
192     BAMBOO_PRINT(0xdddc);
193   }
194
195   if(taskProfileInfo.taskInfoOverflow) {
196     BAMBOO_PRINT(0xefee);
197   }
198
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);
207   }
208
209   if(interruptProfileInfo.interruptInfoOverflow) {
210     BAMBOO_PRINT(0xefef);
211   }
212 #endif 
213
214   BAMBOO_PRINT(0xeeee);
215 #endif
216 }
217
218 #endif // PROFILE 
219 #endif // TASK