/*
 * CS560: Operating Systems
 * Jim Plank / Rich Wolski
 * printqsim.c -- Printer simulation solution #5
   Modified for Kthreads
 */

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

typedef struct {
  Job **b;
  int head;
  int tail;
  int njobs;
  kt_sem job_sem;
  kt_sem slot_sem;
} Buffer;
  
void initialize_v(Spq *s)
{
  Buffer *b;

  b = (Buffer *) malloc(sizeof(Buffer));
  b->b = (Job **) malloc(sizeof(Job *)*s->bufsize);
  b->head = 0;
  b->tail = 0;
  b->njobs = 0;
  b->job_sem = make_kt_sem(0);
  b->slot_sem = make_kt_sem(s->bufsize);
  s->v = (void *) b;
}

void submit_job(Spq *s, Job *j)
{
  Buffer *b;

  b = (Buffer *) s->v;

  P_kt_sem(b->slot_sem);

  if (b->njobs >= s->bufsize) {
    printf("%4d: user %2d Error -- Woke up from a P with no slots.\n", 
           time(0)-s->starttime, s->id);
    fflush(stdout);
    exit(1);
  }

  b->b[b->head] = j;
  b->head = (b->head + 1) % s->bufsize;
  b->njobs++;

  V_kt_sem(b->job_sem);
}


Job *get_print_job(Spq *s)
{
  Buffer *b;
  Job *j;

  b = (Buffer *) s->v;

  P_kt_sem(b->job_sem);

  if (b->njobs <= 0) {
    printf("%4d: prnt %2d Error -- Woke up from a P with no jobs.\n", 
           time(0)-s->starttime, s->id);
    fflush(stdout);
    exit(1);
  }

  j = b->b[b->tail];
  b->tail = (b->tail + 1) % s->bufsize;
  b->njobs--;
  V_kt_sem(b->slot_sem);
  return j;
}

