#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_debug.h>
#include <cpu_tracer.h>
#include <rtl_fifo.h>

#define MICRO 1000
#define MILI 1000*1000
#define USAGE_WINDOW

unsigned int period=1000*1000*1000; // 1 second.
unsigned int ref=70000; // usage reference 40%

MODULE_PARM(ref,"i");
MODULE_PARM(period,"i");
pthread_t tasks[1];

#define MAXITERS 100
#define DEBUG
#define REF_FIFO 1

MODULE_AUTHOR("Josep Vidal");
MODULE_DESCRIPTION("CPU USAGE MONITORIZATION & TUNNING .");


int my_handler(unsigned int fifo)
{
  int err,aux=0,i=0,base=1;
  char buf[5];

  while ((err = rtf_get(REF_FIFO, &buf, sizeof(char)*5)) == sizeof(char)*5) {
    //ref=(int)buf;
    for (i=4;i>=0;i--) { aux+=((int)buf[i]-48)*base;  base*=10; }
    rtl_printf("FIFO handler: reciving buf[0] %d buf[1] %d reference \n",(int)buf[0], (int)buf[1]);
    ref=aux;
    rtl_printf(" AUX : %d \n",(int)aux);

  }
  if (err != 0) {
    rtl_printf(" Error while reciving reference value thorough the %d fifo \n",REF_FIFO);
    return -1;
  }
  return 0;
}



void *usage_reporter(void * arg){
  float usage=0;
  int i=0;
  struct sched_param p;
  p . sched_priority = 32 ;


  pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
  pthread_make_periodic_np (pthread_self(), gethrtime(),period);
  while(1) {
    pthread_wait_np();

    // get cpu usage.
#ifdef USAGE_WINDOW
    {
      hrtime_t aux=0;
      for (i=0;i<window_size;i++){
	aux+=UNIT-usage_window[i];
	//	rtl_printf("usage.o-> usage_window[%d]: %d\n",i,(int)usage_window[i]);
      }
      usage=aux/window_size;
      //      rtl_printf("sample: %d usage.o-> usage_window: %d\n",(int) sample,(int)aux/window_size);
      
    }
#else
    usage=1*UNIT-t_usage[0]; // get cpu usage.
#endif
    
    // send cpu usage thorough a fifo.
    rtf_put(REF_FIFO+1,&sample,sizeof(sample));
    rtf_put(REF_FIFO+1,&usage,sizeof(usage));
    
  }

}

int init_module(void) {
  int err=0;
  pthread_attr_t attr;
  

  //adjust scheduler usage sample period.
  PERIOD=period;


   /* thread creation */
   pthread_attr_init(&attr);
   pthread_attr_setfp_np(&attr, 1); 
   pthread_create (&tasks[0], &attr, usage_reporter, (int *)0);
   
   /* Create a fifo to send controller info to a user program.*/   
   /* Josep */
   err=rtf_destroy (REF_FIFO+1);
   err=rtf_create(REF_FIFO+1,2048);
 
   return 0;
}

void cleanup_module(void) {
     rtl_printf("Killing task %d\n",0);
    pthread_cancel (tasks[0]);
    pthread_join (tasks[0], NULL);

 }



