Subversion Repositories shark

Rev

Rev 1510 | Rev 1517 | 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>
#include <string.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, int line) {
        printf("Finite-State machine error %d at line %d\n",num,line);
        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;

/* Data for gnuplot external call */
int draw_data[DRAW_NUM+1];

int gnuplot_clear() {

   int i;

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

   return 0;

}

int gnuplot_draw(char *title,unsigned long long max_limit,int type) {

   FILE *gnuplot_data, *gnuplot_command;
   char temp_name[30];
   int i,pid,*current_mem;

   current_mem = malloc(sizeof(int)*(DRAW_NUM+1));
   memcpy(current_mem,draw_data,sizeof(int)*(DRAW_NUM+1));

   pid = fork();
   if (pid == 0) {

     srand(getpid());

     sprintf(temp_name,"/tmp/pwcet%d",rand()%10000);

     gnuplot_data = fopen(temp_name,"w");
     gnuplot_command = popen("gnuplot -persist","w");

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

     fflush(gnuplot_data);
     fclose(gnuplot_data);

     fprintf(gnuplot_command,"set xlabel \"Time [us]\"\n");
     if (type == 0) {
        fprintf(gnuplot_command,"set ylabel \"Frequency [#]\"\n");

        fprintf(gnuplot_command,"plot \"%s\" using 1:2 title \"%s\" with lines\n",temp_name,title);
        fflush(gnuplot_command);
     } else {
       fprintf(gnuplot_command,"set ylabel \"Time [us]\"\n");

       fprintf(gnuplot_command,"plot \"%s\" using 1:2 title \"%s\" with lines\n",temp_name,title);
       fflush(gnuplot_command);
     }

     pclose(gnuplot_command);

     exit(0);

   }

   return 0;
 
}

int stats_from_execs(int ctx_num, unsigned long long *tot_tsc,
                                unsigned long long *min_tsc,
                                unsigned long long *mean_tsc,
                                unsigned long long *max_tsc,
                                unsigned long long *first_tsc,
                                int *number) {

   unsigned long long temp_tsc;
   int k,i;

   temp_tsc = 0;
   *max_tsc = 0;
   *mean_tsc = 0;
   *min_tsc = 0xFFFFFFFF;
   *first_tsc = 0;
   k = 0;
   for (i=0;i<exec_total;i++)
     if (exec_list[i].ctx == context_list[ctx_num].ctx) {
       if (*first_tsc == 0) *first_tsc = 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++;
     }

   *number = k;
   *tot_tsc = temp_tsc;
   if (k != 0) *mean_tsc = temp_tsc / k;

   return 0;

}

int stats_from_jobs(int ctx_num, unsigned long long *tot_tsc,
                                unsigned long long *min_tsc,
                                unsigned long long *mean_tsc,
                                unsigned long long *max_tsc,
                                unsigned long long *first_tsc,
                                int *number) {

   unsigned long long temp_tsc;
   int k,i;

   temp_tsc = 0;
   *max_tsc = 0;
   *mean_tsc = 0;
   *min_tsc = 0xFFFFFFFF;
   *first_tsc = 0;
   k = 0;
   for (i=0;i<job_total;i++)
     if (job_list[i].ctx == context_list[ctx_num].ctx) {
       if (*first_tsc == 0) *first_tsc = job_list[i].start - log_start_tsc;
       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++;
     }

   *number = k;
   *tot_tsc = temp_tsc;
   if (k != 0) *mean_tsc = temp_tsc / k;

   return 0;

}

int arr_stats_from_execs(int ctx_num, unsigned long long *min_tsc,
                                unsigned long long *mean_tsc,
                                unsigned long long *max_tsc) {

   unsigned long long last_start,temp_tsc,delta_start;
   int i,k;

   last_start = 0;
   temp_tsc = 0;
   *max_tsc = 0;
   *min_tsc = 0xFFFFFFFF;
   *mean_tsc = 0;
   k = 0;
   for (i=0;i<exec_total;i++)
     if (exec_list[i].ctx == context_list[ctx_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;
        }
      }

   if (k != 0) *mean_tsc = temp_tsc / k;

   return 0;

}

int arr_stats_from_jobs(int ctx_num, unsigned long long *min_tsc,
                                unsigned long long *mean_tsc,
                                unsigned long long *max_tsc) {

   unsigned long long last_start,temp_tsc,delta_start;
   int i,k;

   last_start = 0;
   temp_tsc = 0;
   *max_tsc = 0;
   *min_tsc = 0xFFFFFFFF;
   *mean_tsc = 0;
   k = 0;
   for (i=0;i<job_total;i++)
     if (job_list[i].ctx == context_list[ctx_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;
        }
      }

   if (k != 0) *mean_tsc = temp_tsc / k;

   return 0;

}

int plot_exec_demand_function(int ctx_num, char *pidstr) {

   unsigned long long max_limit;
   char tmpstr[50];
   int i;

   gnuplot_clear();
                                                                                                                             
   max_limit = total_dtsc*1000/clk_per_msec;
                                                                                                                             
   for (i=0;i<exec_total;i++)
     if (exec_list[i].ctx == context_list[ctx_num].ctx) {
       int h1,h2,h3;
                                                                                                                             
       h1 = ((exec_list[i].start-log_start_tsc)*1000/clk_per_msec) * DRAW_NUM / max_limit;
       h2 = ((exec_list[i].start+exec_list[i].dtsc-log_start_tsc)*1000/clk_per_msec) * DRAW_NUM / max_limit;
       for (h3=h1;h3<h2;h3++)
         if (h3 <= DRAW_NUM) draw_data[h3] += (exec_list[i].dtsc*1000/clk_per_msec)*(h3-h1)/(h2-h1);
       for (h3=h2;h3<=DRAW_NUM;h3++)
         if (h3 <= DRAW_NUM) draw_data[h3] += (exec_list[i].dtsc*1000/clk_per_msec);
                                                                                                                             
     }
                                                                                                                             
   sprintf(tmpstr,"Ctx [%d:%s] Demand-Function",context_list[ctx_num].ctx,pidstr);
   gnuplot_draw(tmpstr,max_limit,1);

   return 0;

}

int plot_exec_c_distrib(int ctx_num, unsigned long long max_tsc, char *pidstr) {

   unsigned long long max_limit;
   char tmpstr[50];
   int i,h;

   if (max_tsc == 0) return 0;

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

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

   sprintf(tmpstr,"Ctx [%d:%s] Exec C-dist",context_list[ctx_num].ctx,pidstr);
   gnuplot_draw(tmpstr,max_limit,0);

   return 0;

}

int plot_job_c_distrib(int ctx_num, unsigned long long max_tsc, char *pidstr) {

   unsigned long long max_limit;
   char tmpstr[50];
   int i,h;

   if (max_tsc == 0) return 0;

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

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

   sprintf(tmpstr,"Ctx [%d:%s] Job C-dist",context_list[ctx_num].ctx,pidstr);
   gnuplot_draw(tmpstr,max_limit,0);

   return 0;

}

int plot_exec_arr_distrib(int ctx_num, unsigned long long max_tsc, char *pidstr) {

  unsigned long long max_limit,last_start,delta_start;
  char tmpstr[50];
  int i,h;

  if (max_tsc == 0) return 0;

  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[ctx_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;
      }
    }

  sprintf(tmpstr,"Ctx [%d:%s] Exec Arr.Delta",context_list[ctx_num].ctx,pidstr);
  gnuplot_draw(tmpstr,max_limit,0);

  return 0;

}

int plot_job_arr_distrib(int ctx_num, unsigned long long max_tsc, char *pidstr) {

  unsigned long long max_limit,last_start,delta_start;
  char tmpstr[50];
  int i,h;

  if (max_tsc == 0) return 0;

  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[ctx_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 = job_list[i].start;
      }
    }

  sprintf(tmpstr,"Ctx [%d:%s] Job Arr.Delta",context_list[ctx_num].ctx,pidstr);
  gnuplot_draw(tmpstr,max_limit,0);

  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;

  int kill_delta = 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:
        case 9:
                /* 2 par */
                fscanf(input_file,"%d %d",&par1,&par2);
                break;

    }

    switch (type) {

        case 0:
                if (state != 0) Error(1,k);
                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,k);
                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,k);            
                exec_list[current_exec].dtsc = tsc - last_tsc;
                exec_list[current_exec].ctx = current_context;
                current_exec++;
                last_tsc = tsc;
                if (par1 > 16) {
                  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) {
                                context_list[i].pid = par2;
                                break;
                        }
                if (i == context_total) {
                        context_list[context_total].ctx = par1;
                        context_list[context_total].pid = par2;
                        context_total++;
                }

                break;
       
        /* Task kill */
        case 7:

                for (i=0;i<context_total;i++)
                        if (par1 == context_list[i].ctx) break;
                if (i == context_total) Error(5,k);
                  else {

                        kill_delta += 1000;

                        for (k=0;k<current_endcycle;k++)
                                if (endcycle_list[k].ctx == par1)
                                        endcycle_list[k].ctx += kill_delta;
                        for (k=0;k<current_exec;k++)
                                if (exec_list[k].ctx == par1)
                                        exec_list[k].ctx += kill_delta;
                        context_list[context_total].ctx = context_list[i].ctx + kill_delta;
                        context_list[context_total].pid = context_list[i].pid;
                        context_total++;

                        if (current_context == par1) current_context += kill_delta;

                  }

                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,k);
               
                endcycle_list[current_endcycle].ctx = par1;
                endcycle_list[current_endcycle].tsc = tsc;
                current_endcycle++;

                break;

        /* Task id */
        case 9:
                                                                                                                             
                for (i=0;i<context_total;i++)
                        if (par1 == context_list[i].ctx) {
                                context_list[i].pid = par2;
                                break;
                        }      
                if (i == context_total) {
                        context_list[context_total].ctx = par1;
                        context_list[context_total].pid = par2;
                        context_total++;
                }
                                                                                                                             
                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) {

  char pidstr[10];
  unsigned long long tot_tsc,mean_tsc,max_tsc,min_tsc,first_tsc;
  int number;

  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);

    stats_from_execs(num,&tot_tsc,&min_tsc,&mean_tsc,&max_tsc,&first_tsc,&number);    

    printf("  Total Execution dTSC [%12llu] us [%12llu]\n",tot_tsc,tot_tsc*1000/clk_per_msec);
    printf("  Mean  CPU Bandwidth  [%11f%c]\n",(double)(tot_tsc)/(double)(total_dtsc)*100.0,'%');
    printf("    after first exec   [%11f%c]\n",(double)(tot_tsc)/(double)(total_dtsc-first_tsc)*100.0,'%');
    printf("  Execs Number         [%12d]\n",number);
    printf("  Min  Exec       dTSC [%12llu] us [%12llu]\n",min_tsc, min_tsc*1000/clk_per_msec);
    printf("  Mean Exec       dTSC [%12llu] us [%12llu]\n",mean_tsc, mean_tsc*1000/clk_per_msec);
    printf("  Max  Exec       dTSC [%12llu] us [%12llu]\n\n",max_tsc, max_tsc*1000/clk_per_msec);

    plot_exec_demand_function(num,pidstr);

  }

  if (task_type == INTERRUPT) {

    printf("Interrupts\n");

    stats_from_execs(num,&tot_tsc,&min_tsc,&mean_tsc,&max_tsc,&first_tsc,&number);

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

    plot_exec_c_distrib(num,max_tsc,pidstr);

    arr_stats_from_execs(num,&min_tsc,&mean_tsc,&max_tsc);

    if (max_tsc > 0) {

      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",mean_tsc,mean_tsc*1000/clk_per_msec);
      printf("  Max  Arr. Delta dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);

      plot_exec_arr_distrib(num,max_tsc,pidstr);

    }

  }

  if (task_type == PERIODICAL) {

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

    stats_from_execs(num,&tot_tsc,&min_tsc,&mean_tsc,&max_tsc,&first_tsc,&number);

    printf("  Total Execution dTSC [%12llu] us [%12llu]\n",tot_tsc,tot_tsc*1000/clk_per_msec);
    printf("  Mean  CPU Bandwidth  [%11f%c]\n",(double)(tot_tsc)/(double)(total_dtsc)*100.0,'%');
    printf("    after first exec   [%11f%c]\n",(double)(tot_tsc)/(double)(total_dtsc-first_tsc)*100.0,'%');
    printf("  Execs Number         [%12d]\n",number);
    printf("  Min  Exec       dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Exec       dTSC [%12llu] us [%12llu]\n",mean_tsc,mean_tsc*1000/clk_per_msec);
    printf("  Max  Exec       dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);    

    plot_exec_demand_function(num,pidstr);

    stats_from_jobs(num,&tot_tsc,&min_tsc,&mean_tsc,&max_tsc,&first_tsc,&number);  

    printf("  Total Job Exec  dTSC [%12llu] us [%12llu]\n",tot_tsc,tot_tsc*1000/clk_per_msec);
    printf("  Jobs Number          [%12d]\n",number);
    printf("  Min  Job        dTSC [%12llu] us [%12llu]\n",min_tsc,min_tsc*1000/clk_per_msec);
    printf("  Mean Job        dTSC [%12llu] us [%12llu]\n",mean_tsc,mean_tsc*1000/clk_per_msec);
    printf("  Max  Job        dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);

    plot_job_c_distrib(num,max_tsc,pidstr);

    arr_stats_from_jobs(num,&min_tsc,&mean_tsc,&max_tsc);

    if (max_tsc > 0) {

      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",mean_tsc,mean_tsc*1000/clk_per_msec);
      printf("  Max  Arr. Delta dTSC [%12llu] us [%12llu]\n\n",max_tsc,max_tsc*1000/clk_per_msec);
 
      plot_job_arr_distrib(num,max_tsc,pidstr);

    }

  }

  return 0;

}

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

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

  srand(getpid());

  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;

}