/*
 * CS560: Operating Systems
 * Jim Plank / Rich Wolski
 * dphil_skeleton.c -- Dining philosophers driver program for kthreads
 * Modified for Kthreads.
 */


#include <stdio.h>
#include "kt.h"
#include "dphil.h"


void philosopher(void *v)
{
  Phil_struct *ps;
  long st;
  long t;

  ps = (Phil_struct *) v;
  while(1) {

    /* First the philosopher thinks for a random number of seconds */

    st = (random()%ps->ms) + 1;
    printf("%3d Philosopher %d thinking for %d second%s\n",
                time(0)-ps->t0, ps->id, st, (st == 1) ? "" : "s");
    fflush(stdout);
    kt_sleep(st);

    /* Now, the philosopher wakes up and wants to eat.  He calls pickup
       to pick up the chopsticks */

    printf("%3d Philosopher %d no longer thinking -- calling pickup()\n", 
            time(0)-ps->t0, ps->id);
    fflush(stdout);
    t = time(0);
    pickup(ps);
    ps->blocktime[ps->id] += (time(0) - t);

    /* When pickup returns, the philosopher can eat for a random number of
       seconds */

    st = (random()%ps->ms) + 1;
    printf("%3d Philosopher %d eating for %d second%s\n",
                time(0)-ps->t0, ps->id, st, (st == 1) ? "" : "s");

    fflush(stdout);
    kt_sleep(st);

    /* Finally, the philosopher is done eating, and calls putdown to
       put down the chopsticks */

    printf("%3d Philosopher %d no longer eating -- calling putdown()\n", 
            time(0)-ps->t0, ps->id);
    fflush(stdout);
    putdown(ps);
  }
}

main(argc, argv)
int argc; 
char **argv;
{
  int i;
  void *threads[MAXTHREADS];
  Phil_struct ps[MAXTHREADS];
  void *v;
  long t0;
  int *blocktime;
  char s[500];
  int phil_count;
  char *curr;
  int total;

  if (argc != 3) {
    fprintf(stderr, "usage: dphil philosopher_count maxsleepsec\n");
    exit(1);
  }

  srandom(time(0));
  
  phil_count = atoi(argv[1]);
  
  if(phil_count > MAXTHREADS)
	  phil_count = MAXTHREADS;
   
  v = initialize_v(phil_count);
  t0 = time(0);
  blocktime = (int *) malloc(sizeof(int)*phil_count);
  for (i = 0; i < phil_count; i++) blocktime[i] = 0;

  for (i = 0; i < phil_count; i++) {
    ps[i].id = i;
    ps[i].t0 = t0;
    ps[i].v = v;
    ps[i].ms = atoi(argv[2]);
    ps[i].blocktime = blocktime;
    threads[i] = kt_fork(philosopher, (void *) (ps+i));
  }

  while(1) {
    curr = s;
    total=0;
    for(i=0; i < phil_count; i++)
	    total += blocktime[i];
    sprintf(curr,"%3d Total blocktime: %5d : ", 
		    time(0)-t0,
		    total);
    curr = s + strlen(s);
    for(i=0; i < phil_count; i++)
    {
    	sprintf(curr, "%5d ", blocktime[i]);
	curr = s + strlen(s);
    }
    printf("%s\n", s);
    fflush(stdout);
    kt_sleep(10);
  }
}

