/* 
  CSC354 Problem Set 1, Question 1.

  Name:    Andria Hunter
  Login:   at354hun
  Stud.ID: 555555555

  Program Description:
    This program uses CSIM to simulate a terminal-driven computer system.
    This computer system has 24 terminals.  It has a uniformly distributed
    response time of 4 +/- 2 seconds.  Upon receiving a system response, a
    user sitting at a terminal generates the next command after a uniformly
    distributed think time of 8 +/- 4 seconds.  This program determines
     (a) the system throughput (rate at which the computer system
            processes requests).
     (b) a view of the distribution of time in the system.
*/

#include "csim.h"

#define TMEAN 8.0      /* mean think time */
#define TSPRD 4.0      /* half of think time spread */

#define RMEAN 4.0      /* mean response time */
#define RSPRD 2.0      /* half of response time spread */

#define NTERMS 24l     /* number of terminals */
#define NCOMMS 500l    /* number of submitted commands */

/* Global CSIM structure definitions */

EVENT   done;          /* event to signal last command */

HIST    rsp_histo;     /* time in computer system (response) histogram */
                       /* (Table gives a view of distribution of */
                       /*  time in the computer system.)         */

int cnt;               /* number of active commands */

/* sim process - Execution starts here.  Generate 24 terminals */
/*    and wait until the NCOMMS commands have completed. */

sim()
{
   long i;

   create("sim");                         /* create main process */
   set_model_name("Terminal-Driven Computer System");
   max_processes(2000l);

   done = event("done");                  /* initialize event */

   rsp_histo = histogram("Time in System", 6, 1.0, 7.0);

   /* Generate 24 terminal processes.  Each will run independently. */
   /* Each starts at simulated time 0.0.                            */

   cnt = NCOMMS;
   for(i = 1; i <= NTERMS; i++) {
      terminal(i);
   }

   /* Wait until the NCOMMS commands have been generated. */
   wait(done);

   /* Calculate simulation throughput */
   printf ("\nAverage throughput is %lf\n\n", NCOMMS/clock);

   report();                              /* print report */
}

/* process terminal - For each terminal, a user thinks, and then waits */
/*    for the system's response time.  Each time we call the "compute" */
/*    procedure to generate a response time, we decrement the count of */
/*    the number of commands in the system. */

terminal(n)
long n;        /* The terminal number, from 1 to NTERMS */

{
   float start;                     /* simulation start time. */
   EVENT eventdone;                 /* signal end of thinking */ 
                                    /*   or computing. */ 
 
   create("terminal");              /* create terminal process */

   eventdone = event("eventdone");  /* local event used to signal */
                                    /* end of think time, and then */
                                    /* end of compute/response time. */

   /* This loop continues until the count of commands in the */
   /* system has been decremented to zero.  The count is     */
   /* decremented each time we call the "compute" function   */
   /* to simulate computing time for a command.              */

   while (cnt>0) {

      start = clock;

      /* Schedule the think time, and wait for it to finish. */

      think (n, eventdone);
      wait (eventdone);

      /* Schedule the compute time, and wait for it to finish. */

      compute (n, eventdone);
      wait (eventdone);

      cnt--;
   }

   set (done);                      /* Last command has competed. */
   terminate();
}

/* process compute - generate a uniform system response time  */
/*    amount and advance the simulation clock for this amount */
/*    of time.  Record in rsp_histo histogram. */

compute(n, ev)
long n;
EVENT ev;

{
   float start_resp;
   float resp_time = 0.0;
 
   create("compute");

   start_resp = clock;                     /* start of response time */

   /* generate response time amount */
   resp_time = uniform (RMEAN-RSPRD,RMEAN+RSPRD);

   hold (resp_time);                       /* advance simulated time */
   record(clock-start_resp, rsp_histo);    /* record end of response time */

   set (ev);
   terminate();
}

/* process think - generate a uniform think time and hold the */
/*    simulation for this amount of time. */

think(n, ev)
long n;
EVENT ev;

{
   float think_time = 0.0;
 
   create("think");

   /* generate think time amount */
   think_time = uniform (TMEAN-TSPRD,TMEAN+TSPRD);

   hold (think_time);                      /* advance simulated time */

   set (ev);
   terminate();
}

