#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdint.h>
#include <limits.h>
#include <sys/time.h>
#include "../lve-ctl.h"

#define DIFF_T(a,b) ( (a.tv_sec - b.tv_sec) + (double)(a.tv_usec - b.tv_usec)/1000000 )

static int lve_available = 0; /* not available by default */
struct liblve *lve;

/**
 * Default will have 1 entry, 50,000 cycles
 * You can change it by providing parameters
 * First parameter controls number of lve entries
 * second parameter controls number of cycles
 * Author: Igor Seletskiy <iseletsk@gmail.com>
 */

main(int argc, char *argv[]) 
{
  int i,j,k,x;
  uint32_t p_cookie;  
  int rc;
  struct timeval start, end;
  
  int entries = 1,ve_id=902;
  int cycles = 50000;
  double tc;
  if (argc>1) {
    entries = atoi(argv[1]);
    argc--;
  }
  if (argc>1) {
    cycles = atoi(argv[2]);
  }
//  printf("Entries %d, cycles %d\n", entries, cycles);
  
  rc = lve_instance_init(NULL);
//  printf("LVE data size %d\n", rc);
  lve = malloc(rc);
  rc = lve_instance_init(lve);
  if (rc != 0) {
    printf("Can't init lve instance %d\n", rc);
    _exit(-1);
  }
//  printf("Successfull init lve instance %d - %d\n", rc, getpid());
  
    printf("With LVE\tWithout LVE\tWith diff LVE\n");
    tc = 0;
  // entering into same LVE each time
  for (i = 0; i <10; i++) {
    gettimeofday(&start, NULL);
    for (x=0; x<entries; x++) {
      if (lve_enter(lve, ve_id, -1, -1, &p_cookie)) {
	printf("couldn't enter ve %d for the %d time\n",ve_id, x);
	exit(-1);
      }
      for (j = 1; j<cycles; j++) {
	k = j*j;
      }
      if (lve_leave(lve, &p_cookie)) {
	printf("lve_leave failed");
	exit(-1);
      }
    }
    gettimeofday(&end, NULL);
//    printf("With lve%d - time took %.6f sec\n", i, DIFF_T(end, start));
    tc += DIFF_T(end, start)*100;
  }

    printf("%.6f\t",tc);
    tc = 0;
  // no lve
  for (i = 0; i < 10; i++) {
    gettimeofday(&start, NULL);
    for (x=0; x<entries; x++) {
      for (j = 0; j<cycles; j++) {
	k = j*j;
      }
    }
    gettimeofday(&end, NULL);
    tc += DIFF_T(end, start)*100;
//    printf("Without lve%d - time took %.6f sec\n", i, DIFF_T(end,start));
  }

    printf("%.6f\t",tc);
    tc = 0;
  //entering into different lve
  for (i = 0; i <10; i++) {
    gettimeofday(&start, NULL);
    for (x=0; x<entries; x++) {
      if (lve_enter(lve, 1000+x, -1, -1, &p_cookie)) {
	exit(-1);
      }
      for (j = 1; j<cycles; j++) {
	k = j*j;
      }
      if (lve_leave(lve, &p_cookie)) {
	printf("lve_leave failed");
	exit(-1);
      }
    }
    gettimeofday(&end, NULL);
    tc += DIFF_T(end, start)*100;
//    printf("With diff lve%d - time took %.6f sec\n", i, DIFF_T(end, start));
  }
    printf("%.6f\n",tc);

  lve_instance_destroy(lve);
  return 0;
}
