/****************************************************************************
  Deze header file bevat de voor de opgave over high-level scheduling en
  geheugen-allocatie benodigde definities

Auteur:	Dick van Albada
Vakgroep Computersystemen
Kruislaan 403
Datum:	7 september 2003
Versie:	0.3

Student name .... Sander van Veen & Taddeus Kroes
Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
Collegekaart .... 6167969 & 6054129
Date ............ 10.10.2010
 ****************************************************************************/

/****************************************************************************
  De verschillende soorten events:
  NewProcess_event - er is een nieuw proces in de new_proc rij
  bijgeplaatst.
  Time_event - het lopende proces heeft zijn time-slice opgebruikt.
  Wordt niet gegenereerd, tenzij je zelf "set_slice" aanroept.
  Hoort b.v. in een Round-Robin schedule thuis.
  Ready_event - een proces is klaar met I/O en is weer achteraan de
  ready_proc rij geplaatst. Voor sommige CPU-scheduling algoritmen
  een punt om weer een beslissing te nemen.
  IO_event - het lopende proces gaat I/O doen en is achteraan de
  io_proc rij geplaatst. Als je de volgorde van de processen in
  de io_proc queue of in de ready queue wil aanpassen, kan dat nu.
  Finish_event - het lopende proces is beeindigd en in de defunct_proc rij
  geplaatst. Een goede gelegenheid om nieuwe processen toe te laten.
 ****************************************************************************/

typedef enum EVENT {NewProcess_event, Time_event, Ready_event, IO_event,
    Finish_event} event_type;

/****************************************************************************
  de structuur "pcb" bevat alle informatie die voor de scheduler
  beschikbaar is.
  SIM_pcb verwijst naar de voor de simulator benodigde informatie en mag
  niet worden gewijzigd.
  your_admin wordt door de simulator niet gebruikt (aanvankelijk NULL).
  Deze pointer is beschikbaar om desgewenst voor de scheduler een
  eigen administratie aan de pcb te kunnen koppelen.
  prev en next worden gebruikt voor het construeren van dubbel verbonden
  lijsten. Ze kunnen zowel door de simulator als door de scheduler
  worden gewijzigd.
  MEM_need bevat het aantal voor dit proces benodigde longs geheugen.
  MEM_need wordt door de simulator ingevuld en mag niet worden
  gewijzigd.
  MEM_base staat aanvankelijk op -1 en moet door de (hoog-niveau) scheduler
  een maal worden gevuld met de begin-locatie in het te gebruiken
  geheugen-array. Door jouw scheduler een maal te veranderen.
  proc_num is het volgnummer van het proces en wordt door de simulator
  gevuld. Niet veranderen.
 ****************************************************************************/

typedef struct PCB
{
    void *SIM_pcb;
    void *your_admin;
    struct PCB 	*prev,
                *next;
    long MEM_need,
         MEM_base,
         proc_num;
} pcb;

/****************************************************************************
  De wachtrijen.
  Nieuwe processen worden achteraan in de rij new_proc bijgeplaatst.
  (programma practicumleiding)
  Na toewijzing van geheugen dienen ze in de ready_proc rij te worden
  geplaatst.
  (procedure schedule)
  Een proces wordt voor de CPU gescheduled door het voorin de ready_proc
  rij te plaatsen. Zonder enige verdere voorzieningen werken de io_proc
  en ready_proc rijen op FCFS basis hun klanten af.
  (procedure schedule - een andere CPU scheduling dan FCFS vereist
  dus aanpassingen in de volgorde van processen in deze queues.
  Als een proces I/O wil doen (gesimuleerd), komt het in de io_proc rij.
  Laat deze rij met rust.
  Een beeindigd proces komt in de defunct_proc rij. Ruim deze op.
 *****************************************************************************/

pcb *new_proc,
    *ready_proc,
    *io_proc,
    *defunct_proc;

/****************************************************************************
  De door de practicum-leiding aangeleverde fucties
 *****************************************************************************/

double sim_time();

/****************************************************************************
  sim_time geeft de gesimuleerde "wall-clock time" terug. Gebruik
  naar het je goeddunkt
 *****************************************************************************/

extern void set_slice(double slice);

/****************************************************************************
  set_slice zorgt dat over slice tijdseenheden een Time_event optreedt.
  Er kan maar een Time_event tegelijk in de pijp zitten, dus iedere
  set_slice aanroep "overschrijft" de vorige.
  set_slice zorgt er intern voor dat slice steeds minstens 1.0 is, om
  voortgang te garanderen.
  Bij een Time_event wordt voordat de scheduler wordt aangeroepen steeds
  een set_slice(9.9e12) gedaan om te voorkomen dat de simulator daarop kan
  blijven hangen.
  Gebruik voor deze opgave is niet nodig.
 *****************************************************************************/

long    rm_process(pcb **proces);

/****************************************************************************
  rm_process heeft twee taken:
  1. het verzamelt de nodige statistische gegevens over de executie
  van het proces voor het "eindrapport"
  2. het ruimt de pcb en de "SIM_pcb" op en werkt de defunct_proc rij bij.
  rm_process ruimt de eventueel door "your_admin" gebruikte ruimte
  niet op en geeft ook het gereserveerde geheugen niet vrij. Dat
  moet je bij een "Finish_event" zelf doen.
 ****************************************************************************/

/***************************************************************************
  De functie variabele finale wordt door het hoofdprogramma geinitialiseerd
  met een vrijwel lege functie die alleen de tekst "Einde van het programma"
  afdrukt.
  Hij wordt aangeroepen vlak voor het eind van het programma, als de
  door het hoofdprogramma verzamelde statistische gegevens zijn afgedrukt.
  Door finale naar een eigen functie van het juiste type te laten verwijzen,
  kun je ervoor zorgen dat je eigen afsluitende routine wordt aangeroepen
  om zo eventuele eigen statistieken af te drukken.
  Een interessante mogelijkheid is b.v. de samenhang tussen de wachttijd op
  geheugen en de grootte van het aangevraagde geheugen te onderzoeken.
  Treedt er starvation op, en zo ja, voor welke processen?
 ****************************************************************************/

typedef void function();

function *finale;

/****************************************************************************
  Voor de eigenlijke meting worden 100 processen opgestart om de
  queues te vullen. Daarna worden de statistieken weer op nul gezet.
  Definieer zelf een functie waar je reset_stats naar laat wijzen
  om dat ook eventueel voor je eigen statistieken te doen.
 ****************************************************************************e */

function *reset_stats;

/****************************************************************************
  De door de practicanten te schrijven routine
 ****************************************************************************e */

void   schedule(event_type event);

void   enqueue_front(pcb **queue, pcb *elem);
void   enqueue_back(pcb **queue, pcb *elem);
pcb    *remove_from_queue(pcb **queue, pcb *elem);
pcb    *dequeue(pcb **queue);
