Subversion Repositories shark

Rev

Rev 1497 | Rev 1500 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.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

#define DRAW_NUM 1000

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 int clk_per_msec = 0;

unsigned long long log_start_tsc = 0;
unsigned long long log_end_tsc = 0;
unsigned long long total_dtsc = 0;

int draw_data[DRAW_NUM];

int gnuplot_clear() {

   int i;

   for (i=0;i<DRAW_NUM;i++)
     draw_data[i] = 0;

   return 0;

}

int gnuplot_draw(unsigned long long max_limit) {

   FILE *gnuplot_data, *gnuplot_command;
   int i;

   gnuplot_data = fopen("/tmp/pwcet_tmp","w");
   gnuplot_command = popen("gnuplot","w");
   fprintf(gnuplot_command,"plot \"%s\" using 1:2 with lines\n","/tmp/pwcet_tmp"); 
   fflush(gnuplot_command);

   for (i=0;i<DRAW_NUM;i++)
     fprintf(gnuplot_data,"%f\t%f\n",(double)i * (double)max_limit / (double)DRAW_NUM,(float)draw_data[i]);

   fclose(gnuplot_data);
 
   getchar();
   fclose(gnuplot_command);

   return 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,h;
  char pidstr[10];
  unsigned long long temp_tsc,max_tsc,min_tsc;
  unsigned long long last_start, delta_start, first_exec;
  unsigned long long max_limit; 

  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;
    min_tsc = 0xFFFFFFFF;
    first_exec = 0;
    k = 0;
    for (i=0;i<exec_total;i++)
      if (exec_list[i].ctx == context_list[num].ctx) {
        if (first_exec == 0) first_exec = exec_list[i].start - log_start_tsc;
        if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
        if (exec_list[i].dtsc < min_tsc) min_tsc = exec_list[i].dtsc;
        temp_tsc += exec_list[i].dtsc;
        k++;
      }
    printf("  Total Execution dTSC [%12llu] us [%12llu]\n",temp_tsc,temp_tsc*1000/clk_per_msec);
    printf("  Mean  CPU Bandwidth  [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc)*100.0,'%');
    printf("    after first exec   [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc-first_exec)*100.0,'%');
    printf("  Execs Number         [%12d]\n",k);
    printf("  Min  Exec       dTSC [%12llu] us [%12llu]\n",min_tsc, min_tsc*1000/clk_per_msec);
    printf("  Mean Exec       dTSC [%12llu] us [%12llu]\n",temp_tsc / k, temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Exec       dTSC [%12llu] us [%12llu]\n\n",max_tsc, max_tsc*1000/clk_per_msec);

  }

  if (task_type == INTERRUPT) {

    printf("Interrupts\n");

    temp_tsc = 0;
    max_tsc = 0;
    min_tsc = 0xFFFFFFFF;
    first_exec = 0;
    k = 0;
    for (i=0;i<exec_total;i++)
      if (exec_list[i].ctx == context_list[num].ctx) {
        if (first_exec == 0) first_exec = exec_list[i].start - log_start_tsc;
        if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
        if (exec_list[i].dtsc < min_tsc) min_tsc = exec_list[i].dtsc;
        temp_tsc += exec_list[i].dtsc;
        k++;
      }

    gnuplot_clear();

    max_limit = max_tsc*1000/clk_per_msec;

    printf("  Total Execution dTSC [%12llu] us [%12llu]\n",temp_tsc,temp_tsc*1000/clk_per_msec);
    printf("  Mean  CPU Bandwidth  [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc)*100.0,'%');
    printf("    after first int    [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc-first_exec)*100.0,'%');
    printf("  Interrupts Number    [%12d]\n",k);
    printf("  Min  Interrupt  dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Interrupt  dTSC [%12llu] us [%12llu]\n",temp_tsc / k,temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Interrupt  dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);

    for (i=0;i<exec_total;i++)
      if (exec_list[i].ctx == context_list[num].ctx) {
        h = (exec_list[i].dtsc*1000/clk_per_msec) * DRAW_NUM / max_limit;
        if (h < DRAW_NUM) draw_data[h]++;
      }

    gnuplot_draw(max_limit);

    last_start = 0;
    temp_tsc = 0;
    max_tsc = 0;
    min_tsc = 0xFFFFFFFF;
    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;
                if (delta_start < min_tsc) min_tsc = delta_start;
                temp_tsc += delta_start;
                k++;
                last_start = exec_list[i].start;
        }
      }

    printf("  Min  Arr. Delta dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Arr. Delta dTSC [%12llu] us [%12llu]\n",temp_tsc / k,temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Arr. Delta dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);

    gnuplot_clear();

    max_limit = max_tsc*1000/clk_per_msec;

    last_start = 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;

                h = (delta_start*1000/clk_per_msec) * DRAW_NUM / max_limit;
                if (h < DRAW_NUM) draw_data[h]++;

                last_start = exec_list[i].start;
        }
      }

    gnuplot_draw(max_limit);

  }

  if (task_type == PERIODICAL) {

    printf("Periodical Task CTX [%5d] PID [%s]\n",context_list[num].ctx,pidstr);    

    temp_tsc = 0;
    max_tsc = 0;
    min_tsc = 0xFFFFFFFF;
    first_exec = 0;
    k = 0;
    for (i=0;i<exec_total;i++)
      if (exec_list[i].ctx == context_list[num].ctx) {
        if (first_exec == 0) first_exec = exec_list[i].start - log_start_tsc;
        if (exec_list[i].dtsc > max_tsc) max_tsc = exec_list[i].dtsc;
        if (exec_list[i].dtsc < min_tsc) min_tsc = exec_list[i].dtsc;
        temp_tsc += exec_list[i].dtsc;
        k++;
      }
    printf("  Total Execution dTSC [%12llu] us [%12llu]\n",temp_tsc,temp_tsc*1000/clk_per_msec);
    printf("  Mean  CPU Bandwidth  [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc)*100.0,'%');
    printf("    after first int    [%11f%c]\n",(double)(temp_tsc)/(double)(total_dtsc-first_exec)*100.0,'%');
    printf("  Execs Number         [%12d]\n",k);
    printf("  Min  Exec       dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Exec       dTSC [%12llu] us [%12llu]\n",temp_tsc / k,temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Exec       dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);    

    temp_tsc = 0;
    max_tsc = 0;
    min_tsc = 0xFFFFFFFF;
    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;
        if (job_list[i].dtsc < min_tsc) min_tsc = job_list[i].dtsc;
        temp_tsc += job_list[i].dtsc;
        k++;
      }
    printf("  Total Job Exec  dTSC [%12llu] us [%12llu]\n",temp_tsc,temp_tsc*1000/clk_per_msec);
    printf("  Jobs Number          [%12d]\n",k);
    printf("  Min  Job        dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Job        dTSC [%12llu] us [%12llu]\n",temp_tsc / k,temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Job        dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);

    gnuplot_clear();
  
    max_limit = max_tsc*1000/clk_per_msec;

    for (i=0;i<job_total;i++)
      if (job_list[i].ctx == context_list[num].ctx) {
        h = (job_list[i].dtsc*1000/clk_per_msec) * DRAW_NUM / max_limit;
        if (h < DRAW_NUM) draw_data[h]++;
      }

    gnuplot_draw(max_limit);

    last_start = 0;
    temp_tsc = 0;
    max_tsc = 0;
    min_tsc = 0xFFFFFFFF;
    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;
                if (delta_start < min_tsc) min_tsc = delta_start;
                temp_tsc += delta_start;
                k++;
                last_start = job_list[i].start;
        }
      }

    printf("  Min  Arr. Delta dTSC [%12llu] us [%12llu]\n\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Arr. Delta dTSC [%12llu] us [%12llu]\n",temp_tsc / k,temp_tsc / k*1000/clk_per_msec);
    printf("  Max  Arr. Delta dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);
  
    gnuplot_clear();

    max_limit = max_tsc*1000/clk_per_msec;

    last_start = 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;

                h = (delta_start*1000/clk_per_msec) * DRAW_NUM / max_limit;
                if (h < DRAW_NUM) draw_data[h]++;

                last_start = exec_list[i].start;
        }
      }

    gnuplot_draw(max_limit);

  }

  return 0;

}

int main(int argc, char *argv[]) {

  int events_total,k,i;
  int task_type;
  unsigned long long total_tsc;

  if (argc < 3) {
    printf("%s: Enter the input file name and clk_per_msec [%s filename clk_per_msec]\n",argv[0],argv[0]);
    exit(1);
  }

  printf("\n");

  clk_per_msec = atoi(argv[2]);
  
  printf("Clk/msec = %u\n\n",clk_per_msec);
                                                                                                                           
  events_total = create_lists(argv[1]);

  total_dtsc = log_end_tsc - log_start_tsc;

  printf("\nTotal dTSC [%12llu] us [%12llu]\n", total_dtsc, total_dtsc*1000/clk_per_msec);
  printf("Events     [%12d]\n",events_total);
  printf("Execs      [%12d]\n",exec_total);
  printf("EndCycles  [%12d]\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;

}