/******************************************************************************************

* Simulate 'shortest job first' process scheduling;
*
* Author: Farhan Ahmad
*
* Date: 2010-FEB-20
*
* Version: 1.0
*
* Comments:
*
* Version 0.0 was a total mess, with numerous bugs. Took several
weekends to eliminate
these bugs. *
*
*
*
*
* License: Creative Commons Attribution 2.5 India
*
******************************************************************************************/
/******************************************************************************************
* Reads input from a text file, that contains process ID<space>arrival time<space>total burst
time for each *
* process on a new
line;
*
******************************************************************************************/
/* Download Sample text file from http://docs.google.com/
View?id=dcfpqd2d_43tc9h8jc3
*/
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
/* Global declarations */
char debugvar[10];
int DEBUG_TRUE;
typedef struct node {
int PID;
int arrival;
int burst;
int remburst;
struct node *ptr;
} NODE;

NODE* readProcessData(char[],int*);
void printProcessData(NODE*);
void simulateSJF(NODE*,int);
void moveToWaiting(NODE*,NODE*,int);
NODE *getNext(NODE*,NODE*);
void moveToTerminated(NODE*,NODE*,NODE*);
void insertWaiting(NODE*);
void printSchedulingInfo(NODE*,int);
void printLL(NODE*);
int main(int argc , int **argv)
{
int nprocess;
NODE *processList;
char filename[] = "sjf.txt";
/*Process cmd line arguments */
if(argc > 2)
{
printf("\nError: Extra arguments to %s\n",argv[0]);
exit(EXIT_FAILURE);
}
else if(argc == 2)
{
if(strcmp("-d",(const char*)argv[1]))
{
printf("\nError: Invalid argument %s",argv[1]);
printf("\nOnly valid parameter can be '-d'\n");
exit(EXIT_FAILURE);
}
else
{
DEBUG_TRUE = 1;
}
}
else
{
DEBUG_TRUE == 0;

}
processList = readProcessData(filename,&nprocess);
printProcessData(processList);
simulateSJF(processList,nprocess);
return (0x0000);
}

NODE *readProcessData(char filename[],int *n)
{
FILE *fp;
NODE *start,*NEW,*temp, *debugPtr;
int p,a,b;
*n = 0;
start = (NODE*)malloc(sizeof(NODE));
start->ptr = NULL;
temp = start;
fp = fopen(filename,"r");
if(!fp)
{
printf("\nCan not open file: %s",filename);
exit(EXIT_FAILURE);
}
while(1)
{
fscanf(fp,"%d %d %d",&p,&a,&b);
if(feof(fp))
{
fclose(fp);
break;
}
NEW = (NODE*)malloc(sizeof(NODE));
NEW->ptr = NULL;

NEW->arrival = a;
NEW->burst = b;
NEW->PID = p;
temp->ptr = NEW;
temp = NEW;
*n = *n + 1;
}
return start;
}
void printProcessData(NODE *list)
{
NODE *temp = list->ptr;
printf("\n%12s %12s %12s","PID","Arrival","Burst");
while(temp != NULL)
{
printf("\n%12d %12d %12d",temp->PID,temp->arrival,temp->burst);
temp = temp->ptr;
}
printf("\n");
}
void simulateSJF(NODE *inputQueue,int n)
{
NODE *waiting = (NODE*)malloc(sizeof(NODE));
NODE *terminated = (NODE*)malloc(sizeof(NODE));
NODE *next;
int i=0;
int sysclock = 0;
NODE *current = NULL;
NODE *debugPtr = inputQueue->ptr;

waiting->ptr = NULL;
terminated->ptr = NULL;
/*
* While there are new or waiting processes
*/
while(inputQueue->ptr || waiting->ptr )
{
/*
* move all eligible processes to the waiting queue ;
*/
moveToWaiting(inputQueue,waiting,sysclock);
/*
* fetch the process to be executed during this slot
*/
next = getNext(waiting,current);

sysclock++;
/*
* no process to execute? Inset wait state in the 'terminated' queue
*/
if(next == NULL)
{
insertWaiting(terminated);
continue;
}
current = next;
current->remburst = current->remburst - 1;
/*
* Current process has zero reamaining burst time? move to terminated
*/

if(current->remburst == 0)
{
moveToTerminated(waiting,terminated,current);
}
}
printSchedulingInfo(terminated,n);
}

void moveToWaiting(NODE *inputQueue,NODE *waiting,int ti)
{
NODE *temp1 = inputQueue;
NODE *temp2 = waiting;
//////////////////////////////////////////////////////////////////////////////////////
// DEBUG
///////////////////////////////////////////////////////////////////////////////////////
if(DEBUG_TRUE)
{
printf("\nEntering 'moveToWaiting'");
printf("\nTime >> %d",ti);
printf("\nThe input queue is:");
printLL(inputQueue);
printf("Waiting queue is:");
printLL(waiting);
gets(debugvar);
if(debugvar[0]== 'e') exit(EXIT_SUCCESS);
}
///////////////////////////////////////////////////////////////////////////////////////
// END DEBUG
///////////////////////////////////////////////////////////////////////////////////////
/*
Reach end of waiting queue
*/

while(temp2->ptr != NULL)
{
temp2 = temp2->ptr;
}
while(temp1->ptr != NULL)
{
if((temp1->ptr)->arrival == ti)
{
temp2->ptr = temp1->ptr;
temp1->ptr = (temp1->ptr)->ptr;
temp2 = temp2->ptr;
temp2->ptr = NULL;
temp2->remburst = temp2->burst;
}
else
{
temp1 = temp1->ptr;
}
} // end of while
/////////////////////////////////////////////////////////////////////////////////////////
// DEBUG
////////////////////////////////////////////////////////////////////////////////////////
if(DEBUG_TRUE)
{
printf("\nLeaving 'moveToWaiting'");
printf("\nThe input queue is:");
printLL(inputQueue);
printf("Waiting queue is:");
printLL(waiting);
gets(debugvar);
if(debugvar[0]== 'e') exit(EXIT_SUCCESS);
}
/////////////////////////////////////////////////////////////////////////////////////////
// END DEBUG
/////////////////////////////////////////////////////////////////////////////////////////

}

NODE *getNext(NODE *waiting,NODE *current)
{
NODE *temp = waiting->ptr;
NODE *rvalue;
int minburst;
/*
* waiting queue empty? return NULL
*/
if(temp == NULL)
{
return NULL;
}
/*
* else if current process is not null and it has remaining burst time return current;
*/
// The inner if() is reduntant: any process with zero burst time remaining is
// automatically sent to the 'terminated' queue;
//consider removing it.
if(current != NULL )
{
if(current->remburst != 0)
{
return current;
}
}
/* else
// assume first process has minimum burst;
*/
rvalue = temp;
minburst = temp->burst;
while(temp != NULL)

{
if(temp->burst < minburst)
{
minburst = temp->burst;
rvalue = temp;
}
temp = temp->ptr;
}
return rvalue;
}
void insertWaiting(NODE* terminated)
{
NODE *temp = terminated;
NODE *new;
while(temp->ptr != NULL)
{
temp= temp->ptr;
}
new = (NODE*)malloc(sizeof(NODE));
new->PID = -1;
new->ptr = NULL;
temp->ptr = new;
}
void moveToTerminated(NODE *waiting,NODE *terminated,NODE *tomove)
{
NODE *temp1;
NODE *temp2;
temp2 = waiting;
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// DEBUG

if(DEBUG_TRUE)
{
printf("\nInside function 'moveToTerminated '");
printf("\nwaiting queue is:");
printLL(waiting);
printf("terminated queue is:");
printLL(terminated);
}
//END DEBUG
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
while(temp2->ptr != NULL)
{
if(temp2->ptr == tomove) break;
temp2 = temp2->ptr;
}
temp2->ptr= tomove->ptr;
temp1 = terminated;
while(temp1->ptr != NULL)
{
temp1 = temp1->ptr;
}
temp1->ptr = tomove;
tomove->ptr = NULL;
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// DEBUG
if(DEBUG_TRUE)
{
printf("\nLeaving moveToTerminated\n");
printf("Waiting queue is:");
printLL(waiting);
printf("Terminated queue is: ");
printLL(terminated);
}
// END DEBUG

/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
}

void printSchedulingInfo(NODE *list,int n)
{
NODE *temp = list->ptr;
int arrival,burst,PID,waiting,taround,systime=0;
printf("\n%10s %10s %10s %10s %10s","PID","Arrival","Burst","Wait.","T-around");
while(temp != NULL)
{
arrival = temp->arrival;
burst = temp->burst;
PID = temp->PID;
if(PID == -1)
{
systime++;
temp = temp->ptr;
continue;
}
if(arrival < systime)
{
waiting = systime - arrival;
}
else
{
waiting = 0;
}
systime = systime + burst;
taround = waiting + burst;
temp = temp->ptr;
printf("\n%10d %10d %10d %10d %10d",PID,arrival,burst,waiting,taround);

}
printf("\n");
}
void printLL( NODE *list)
{
NODE *tmp;
tmp = list->ptr;
printf("\n");
while(tmp != NULL)
{
printf(" %d ",tmp->PID);
tmp = tmp->ptr;
}
printf("\n");
}