/*
 * Copyright (C) 2002 Luca Abeni
 * This is Free Software; see GPL.txt for details
 */

#include <linux/config.h>
#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
#define MODVERSIONS
#endif
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/kernel.h>
#include <linux/sched.h>

#include <time.h>
#include <cbs.h>

#include <logger.h>

#define TASK_ARRIVAL 0
#define TASK_SCHEDULE 1
#define TASK_DESCHEDULE 2
#define TASK_END 3
#define TASK_DLINEPOST 4
#define TASK_DLINESET 5
#define TASK_WAIT 6
#define TASK_SIGNAL 7
#define TASK_IDLE 8
#define TASK_NAME 9

static struct cbs_struct *exec;
static unsigned long long int start_time;

#define __BINARY_TRACE__

static int swap(int val)
{
  int *p;
  char swapped[4], *orig;

  orig = (char *)&val;
  swapped[0] = orig[3];
  swapped[1] = orig[2];
  swapped[2] = orig[1];
  swapped[3] = orig[0];
  p = (int *)swapped;

  return *p;
}

#ifdef __BINARY_TRACE__
static void trace_log_int(int v)
{
  int sw;

  sw = swap(v);
  log_write((char *)&sw, sizeof(int));
}
#else
static void trace_log_int(int v)
{
  int sw;

  log_printf("%d ", v);
}
#endif

static void trace_common(int type, int time, int task)
{
  trace_log_int(type);
  trace_log_int(time);
  trace_log_int(task % 10);
}

void trace_dispatch(struct cbs_struct *t, unsigned long long int time)
{
  int utime;

  utime = clock2ms(time - start_time);
  if (exec != NULL) {
    trace_common(TASK_DESCHEDULE, utime, exec->task->pid);
  }
  exec = t;
  if (t != NULL) {
    trace_common(TASK_SCHEDULE, utime, t->task->pid);
  }
}

void trace_activation(struct cbs_struct *t, unsigned long long int time)
{
  int utime;

  utime = clock2ms(time - start_time);
  trace_common(TASK_ARRIVAL, utime, t->task->pid);
}

void trace_deactivation(struct cbs_struct *t, unsigned long long int time)
{
  int utime;

  utime = clock2ms(time - start_time);
  trace_common(TASK_END, utime, t->task->pid);
}

void trace_creation(struct cbs_struct *t, unsigned long long int time)
{
  int utime;
  int len;
  char name[16];

  utime = clock2ms(time - start_time);
  trace_common(TASK_NAME, utime, t->task->pid);
  sprintf(name, "task%d", t->task->pid);
  len = strlen(name);
  trace_log_int(len);
  log_write(name, len);
}

void trace_destruction(struct cbs_struct *t, unsigned long long int time)
{
  /* Nothing to do, here... */
}

void trace_dl_postpone(struct cbs_struct *t, unsigned long long int time,
		unsigned long long int old_dl, unsigned long long int new_dl)
{
  int utime;

  utime = clock2ms(time - start_time);
  trace_common(TASK_DLINEPOST, utime, t->task->pid);
  trace_log_int(clock2ms(old_dl - start_time));
  trace_log_int(clock2ms(new_dl - start_time));
}

void trace_dl_assign(struct cbs_struct *t, unsigned long long int time,
		unsigned long long int new_dl)
{
  int utime;

  utime = clock2ms(time - start_time);
  trace_common(TASK_DLINESET, utime, t->task->pid);
  trace_log_int(clock2ms(new_dl - start_time));
}

void trace_start(unsigned long long int time)
{
  start_time = time;
}
