Rev 1495 | Rev 1497 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <stdio.h>
#include <stdlib.h>
#define MAXCONTEXT 100
#define MAXJOB 100000
#define INT_CTX 1
#define INT_PID 9999
#define PID_NO_DEF -1
#define BACKGROUND 0
#define PERIODICAL 1
#define INTERRUPT 2
struct ctx_exec {
int ctx;
unsigned long long dtsc;
unsigned long long start;
};
struct ctx_to_pid {
int ctx;
int pid;
};
struct endcycle {
int ctx;
unsigned long long tsc;
};
void Error(int num) {
printf("Finite-State machine error: %d\n",num);
exit(2);
}
int context_total = 0,endcycle_total = 0,job_total = 0,exec_total = 0;
struct ctx_exec *exec_list;
struct ctx_to_pid *context_list;
struct endcycle *endcycle_list;
struct ctx_exec *job_list;
unsigned long long log_start_tsc = 0;
unsigned long long log_end_tsc = 0;
int create_lists(char *filename) {
FILE *input_file;
int type,par1,par2,k,i,state;
int current_context = 0;
int current_exec = 0;
int current_endcycle = 0;
unsigned long long last_tsc, tsc;
input_file = fopen(filename,"r");
/* Memory alloc */
exec_list = malloc(sizeof(struct ctx_exec) * MAXJOB);
context_list = malloc(sizeof(struct ctx_to_pid) * MAXCONTEXT);
endcycle_list = malloc(sizeof(struct endcycle) * MAXJOB);
/* Finite-State machine
*
* FS-Machine states:
0 - Start
1 - Context running
2 - Interrupt running
10 - End
*/
for(i=0;i<MAXCONTEXT;i++) {
context_list[i].ctx = 0;
context_list[i].pid = PID_NO_DEF;
}
/* The start context + interrupt context */
context_total = 2;
current_context = 0;
last_tsc = 0;
context_list[0].ctx = 0;
context_list[0].pid = PID_NO_DEF;
context_list[1].ctx = INT_CTX;
context_list[1].pid = INT_PID;
state = 0;
k = 0;
while(!feof(input_file)) {
fscanf(input_file,"%d %llu",&type,&tsc);
k++;
switch (type) {
case 0:
case 1:
/* No par */
break;
case 2:
case 3:
case 4:
case 6:
case 7:
case 8:
/* 1 par */
fscanf(input_file,"%d",&par1);
break;
case 5:
/* 2 par */
fscanf(input_file,"%d %d",&par1,&par2);
break;
}
switch (type) {
case 0:
if (state != 0) Error(1);
printf("EVT:Log starts at [%12llu]\n",tsc);
last_tsc = tsc;
log_start_tsc = tsc;
exec_list[current_exec].start = tsc;
state = 1;
break;
case 1:
printf("EVT:Log ends at [%12llu]\n",tsc);
exec_list[current_exec].dtsc = tsc - last_tsc;
exec_list[current_exec].ctx = current_context;
current_exec++;
last_tsc = tsc;
log_end_tsc = tsc;
state = 10;
break;
/* Int start */
case 2:
if (state == 0) Error(2);
exec_list[current_exec].dtsc = tsc - last_tsc;
exec_list[current_exec].ctx = current_context;
current_exec++;
last_tsc = tsc;
current_context = INT_CTX;
exec_list[current_exec].start = tsc;
state = 2;
break;
/* Int end */
case 3:
if (state != 2) Error(3);
exec_list[current_exec].dtsc = tsc - last_tsc;
exec_list[current_exec].ctx = current_context;
current_exec++;
last_tsc = tsc;
current_context = par1;
for (i=0;i<context_total;i++)
if (par1 == context_list[i].ctx) break;
if (i == context_total) {
context_list[context_total].ctx = par1;
context_total++;
}
exec_list[current_exec].start = tsc;
state = 1;
break;
/* Change ctx */
case 4:
exec_list[current_exec].dtsc = tsc - last_tsc;
exec_list[current_exec].ctx = current_context;
current_exec++;
last_tsc = tsc;
current_context = par1;
for (i=0;i<context_total;i++)
if (par1 == context_list[i].ctx) break;
if (i == context_total) {
context_list[context_total].ctx = par1;
context_total++;
}
exec_list[current_exec].start = tsc;
state = 1;
break;
/* Task create */
case 5:
for (i=0;i<context_total;i++)
if (par1 == context_list[i].ctx) break;
if (i == context_total) {
context_list[context_total].ctx = par1;
context_list[context_total].pid = par2;
context_total++;
}
break;
/* Task endcycle */
case 8:
for (i=0;i<context_total;i++)
if (par1 == context_list[i].ctx) break;
if (i == context_total) Error(4);
endcycle_list[current_endcycle].ctx = par1;
endcycle_list[current_endcycle].tsc = tsc;
current_endcycle++;
break;
}
if (current_exec == MAXJOB-1) {
printf("Too many execs...\n");
exit(3);
}
if (current_endcycle == MAXJOB-1) {
printf("Too many endcycle...\n");
exit(4);
}
if (state == 10) break;
}
endcycle_total = current_endcycle;
exec_total = current_exec;
return k;
}
int create_job_list() {
int current_job = 0, h, i, k;
int temp_ctx;
unsigned long long temp_tsc, endcycle_start_tsc;
unsigned long long endcycle_end_tsc;
job_list = malloc(sizeof(struct ctx_exec) * MAXJOB);
for (k=0;k<context_total;k++) {
temp_ctx = context_list[k].ctx;
endcycle_start_tsc = 0;
for (h=0;h<endcycle_total;h++) {
if (endcycle_list[h].ctx == temp_ctx) {
if (endcycle_start_tsc == 0)
endcycle_start_tsc = log_start_tsc;
endcycle_end_tsc = endcycle_list[h].tsc;
temp_tsc = 0;
job_list[current_job].start = 0;
for(i=0;i<exec_total;i++)
if (exec_list[i].ctx == temp_ctx) {
if (exec_list[i].start < endcycle_end_tsc &&
exec_list[i].start >= endcycle_start_tsc) {
if (job_list[current_job].start == 0)
job_list[current_job].start = exec_list[i].start;
temp_tsc += exec_list[i].dtsc;
}
}
job_list[current_job].dtsc = temp_tsc;
job_list[current_job].ctx = temp_ctx;
current_job++;
endcycle_start_tsc = endcycle_end_tsc;
}
}
}
job_total = current_job;
return 0;
}
int elaborate_statistics(int num, int task_type) {
int i,k;
char pidstr[10];
unsigned long long temp_tsc,max_tsc;
unsigned long long last_start, delta_start;
switch (context_list[num].pid) {
case PID_NO_DEF:
sprintf(pidstr,"NODEF");
break;
case INT_PID:
sprintf(pidstr," INT");
break;
default:
sprintf(pidstr,"%5d",context_list[num].pid);
break;
}
if (task_type == BACKGROUND) {
printf("Background Task CTX [%5d] PID [%s]\n",context_list[num].ctx,pidstr);
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<exec_total;i++)
if (exec_list[i].ctx == context_list[num].ctx) {
if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
temp_tsc += exec_list[i].dtsc;
k++;
}
printf(" Total Execution dTSC [%12llu]\n",temp_tsc);
printf(" Execs Number [%12d]\n",k);
printf(" Mean Exec dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Exec dTSC [%12llu]\n\n",max_tsc);
}
if (task_type == INTERRUPT) {
printf("Interrupts\n");
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<exec_total;i++)
if (exec_list[i].ctx == context_list[num].ctx) {
if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
temp_tsc += exec_list[i].dtsc;
k++;
}
printf(" Total Execution dTSC [%12llu]\n",temp_tsc);
printf(" Interrupts Number [%12d]\n",k);
printf(" Mean Interrupt dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Interrupt dTSC [%12llu]\n\n",max_tsc);
last_start = 0;
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<exec_total;i++)
if (exec_list[i].ctx == context_list[num].ctx) {
if (last_start == 0) {
last_start = exec_list[i].start;
} else {
delta_start = exec_list[i].start - last_start;
if (delta_start > max_tsc) max_tsc = delta_start;
temp_tsc += delta_start;
k++;
last_start = exec_list[i].start;
}
}
printf(" Mean Arr. Delta dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Arr. Delta dTSC [%12llu]\n\n",max_tsc);
}
if (task_type == PERIODICAL) {
printf("Periodical Task CTX [%5d] PID [%s]\n",context_list[num].ctx,pidstr);
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<exec_total;i++)
if (exec_list[i].ctx == context_list[num].ctx) {
if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
temp_tsc += exec_list[i].dtsc;
k++;
}
printf(" Total Execution dTSC [%12llu]\n",temp_tsc);
printf(" Execs Number [%12d]\n",k);
printf(" Mean Exec dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Exec dTSC [%12llu]\n\n",max_tsc);
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<job_total;i++)
if (job_list[i].ctx == context_list[num].ctx) {
if (job_list[i].dtsc > max_tsc) max_tsc = job_list[i].dtsc;
temp_tsc += job_list[i].dtsc;
k++;
}
printf(" Total Job Exec dTSC [%12llu]\n",temp_tsc);
printf(" Jobs Number [%12d]\n",k);
printf(" Mean Job dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Job dTSC [%12llu]\n\n",max_tsc);
last_start = 0;
temp_tsc = 0;
max_tsc = 0;
k = 0;
for (i=0;i<job_total;i++)
if (job_list[i].ctx == context_list[num].ctx) {
if (last_start == 0) {
last_start = job_list[i].start;
} else {
delta_start = job_list[i].start - last_start;
if (delta_start > max_tsc) max_tsc = delta_start;
temp_tsc += delta_start;
k++;
last_start = job_list[i].start;
}
}
printf(" Mean Arr. Delta dTSC [%12llu]\n",temp_tsc / k);
printf(" Max Arr. Delta dTSC [%12llu]\n\n",max_tsc);
}
return 0;
}
int main(int argc, char *argv[]) {
int events_total,k,i;
int task_type;
unsigned long long total_tsc;
if (argc < 2) {
printf("%s: Enter the input file name [%s filename]\n",argv[0],argv[0]);
exit(1);
}
printf("\n");
events_total = create_lists(argv[1]);
printf("\nDelta TSC = %llu\n",log_end_tsc - log_start_tsc);
printf("Events [%8d]\n",events_total);
printf("Execs [%8d]\n",exec_total);
printf("EndCycles [%8d]\n",endcycle_total);
total_tsc = 0;
for (i=0;i<exec_total;i++)
total_tsc += exec_list[i].dtsc;
/* Exec total execution check */
printf("\nExec TSC sum = %llu (%2.2f)\n",total_tsc,(float)total_tsc/((float)(log_end_tsc - log_start_tsc))*100.0);
printf("\nPreemption Removing.... \n");
/* Remove preemption from the computation time */
create_job_list();
for (k=0;k<job_total;k++)
printf("Job CTX [%5d] Start [%12llu] dTSC [%12llu]\n",
job_list[k].ctx,job_list[k].start,job_list[k].dtsc);
printf("\nCompute Task Statistics.... \n\n");
for (i=0;i<context_total;i++) {
task_type = BACKGROUND;
if (context_list[i].ctx == INT_CTX) task_type = INTERRUPT;
for (k=0;k<job_total;k++)
if (job_list[k].ctx == context_list[i].ctx) {
task_type = PERIODICAL;
break;
}
elaborate_statistics(i,task_type);
}
return 0;
}