first commit
This commit is contained in:
27
README.txt
Normal file
27
README.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
CIS3110 Assignment 2
|
||||
author: Bronson Graansma, 0872249
|
||||
date: Sunday, March 13th, 2016
|
||||
contact: bgraansm@mail.uoguelph.ca
|
||||
course: CIS*3110 Operating Systems I
|
||||
__________________________________________________________________
|
||||
|
||||
For documentation on any of the function's functionality,
|
||||
view function headers in *.h or *.c.
|
||||
__________________________________________________________________
|
||||
|
||||
**Assumptions, Limitations, and Testing**
|
||||
__________________________________________________________________
|
||||
Assumes input file is redirected to stdin.
|
||||
Assumes input file contains only integers, spaces or tabs
|
||||
Assumes input file is in proper format
|
||||
If any of the above assumptions are violated, program
|
||||
receives a short message to stderr before terminating
|
||||
|
||||
Assumes command line arguments (if any exist) are among:
|
||||
-v, -d, (-r x) in any order. -r must be followed directly
|
||||
by some integer value (x). Any unrecognized flags will cause
|
||||
the program to terminate with a message on stderr.
|
||||
|
||||
Assumes system has sufficient memory in order to run the program.
|
||||
Memory allocations are checked with assert. Program will
|
||||
terminate if an assertion fails and NDEBUG isn't defined.
|
||||
15
input.txt
Normal file
15
input.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
2 3 7
|
||||
1 2
|
||||
1 0 3
|
||||
1 10 20
|
||||
2 10 20
|
||||
3 10
|
||||
2 5 2
|
||||
1 50 10
|
||||
2 50
|
||||
2 2
|
||||
1 0 1
|
||||
1 100
|
||||
2 50 2
|
||||
1 100 20
|
||||
2 100
|
||||
13
main.c
Normal file
13
main.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "mode.h"
|
||||
#include "schedule.h"
|
||||
#include "simulation.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Mode mode = newMode(argv, argc);
|
||||
Schedule schedule = readSchedule(stdin);
|
||||
|
||||
simulate(schedule, mode);
|
||||
freeSchedule(schedule);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
8
makefile
Normal file
8
makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -pedantic -std=c99 -g
|
||||
|
||||
simcpu: main.c schedule.c mode.c simulation.c
|
||||
$(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o simcpu
|
||||
89
mode.c
Normal file
89
mode.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "mode.h"
|
||||
|
||||
/* Creates a new mode to run the simulation in. Handles any errors
|
||||
* with a useful message to stderr, and terminated the program.
|
||||
* args: command line arguments to parse into the mode
|
||||
* returns: a mode that signifies such things as:
|
||||
* RR, quantum, verbose, detailed */
|
||||
Mode newMode(char** argv, int argc) {
|
||||
Mode new;
|
||||
|
||||
new.detailed = false;
|
||||
new.verbose = false;
|
||||
new.roundRobin = false;
|
||||
new.quantum = 0;
|
||||
|
||||
for(int i=1; i<argc; i++) {
|
||||
if(strcmp(argv[i], "-r") == 0) {
|
||||
new.roundRobin = true;
|
||||
if(i < argc-1) {
|
||||
if(isInt(argv[i+1])) {
|
||||
new.quantum = atol(argv[i+1]);
|
||||
|
||||
if(new.quantum < 1) {
|
||||
fprintf(stderr, "This won't accomplish anything.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
fprintf(stderr, "Quantum value must be an integer.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Round robin flag must be followed by a quantum value.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if(strcmp(argv[i], "-d") == 0) {
|
||||
new.detailed = true;
|
||||
} else if(strcmp(argv[i], "-v") == 0) {
|
||||
new.verbose = true;
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s [-d] [-v] [-r quantum]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Checks to see if a string can be converted to an integer.
|
||||
* args: the string to check
|
||||
* returns: true if string is an int, false otherwise */
|
||||
bool isInt(char* str) {
|
||||
int len = 0;
|
||||
|
||||
if(!str) {
|
||||
return false;
|
||||
} else if((len = strlen(str)) < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0; i<len; i++) {
|
||||
if(!isdigit(str[i])) {
|
||||
if(i == 0 && str[i] == '-') {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Checks if a string is empty or not
|
||||
* args: the string to check
|
||||
* returns: true if all characters are whitespace, false otherwise */
|
||||
bool isEmpty(char* str) {
|
||||
int len = 0;
|
||||
|
||||
if(!str) {
|
||||
return false;
|
||||
} else if((len = strlen(str)) < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0; i<len; i++) {
|
||||
if(!isspace(str[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
34
mode.h
Normal file
34
mode.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef __MODE_H_
|
||||
#define __MODE_H_
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct Mode {
|
||||
bool detailed;
|
||||
bool verbose;
|
||||
bool roundRobin;
|
||||
int quantum;
|
||||
} Mode;
|
||||
|
||||
/* Creates a new mode to run the simulation in. Handles any errors
|
||||
* with a useful message to stderr, and terminated the program.
|
||||
* args: command line arguments to parse into the mode
|
||||
* returns: a mode that signifies such things as:
|
||||
* RR, quantum, verbose, detailed */
|
||||
Mode newMode(char** argv, int argc);
|
||||
|
||||
/* Checks to see if a string can be converted to an integer.
|
||||
* args: the string to check
|
||||
* returns: true if string is an int, false otherwise */
|
||||
bool isInt(char* str);
|
||||
|
||||
/* Checks if a string is empty or not
|
||||
* args: the string to check
|
||||
* returns: true if all characters are whitespace, false otherwise */
|
||||
bool isEmpty(char* str);
|
||||
|
||||
#endif
|
||||
281
schedule.c
Normal file
281
schedule.c
Normal file
@@ -0,0 +1,281 @@
|
||||
#include "schedule.h"
|
||||
|
||||
static bool readBurst(FILE* fp, Burst* burst) {
|
||||
char buffer[BUFF_LEN];
|
||||
|
||||
if(!burst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fgets(buffer, BUFF_LEN-1, fp)) { buffer[strlen(buffer)-1] = '\0';
|
||||
char* token = strtok(buffer, " \t");
|
||||
int ntokens = 0;
|
||||
|
||||
while(token) {
|
||||
if(isEmpty(token)) {
|
||||
token = strtok(NULL, " \t");
|
||||
continue;
|
||||
} else if(isInt(token)) {
|
||||
switch(ntokens) {
|
||||
case 0: burst->burstNum = atol(token); break;
|
||||
case 1: burst->cpuTime = atol(token); break;
|
||||
case 2: burst->ioTime = atol(token); break;
|
||||
default: return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ntokens++;
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
if(ntokens == 2) {
|
||||
burst->ioTime = 0;
|
||||
} else if(ntokens != 3) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readThread(FILE* fp, Thread* thread) {
|
||||
char buffer[BUFF_LEN];
|
||||
Burst* brst = NULL;
|
||||
Burst* prev = NULL;
|
||||
|
||||
if(!thread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
thread->burst = malloc(sizeof(Burst));
|
||||
assert(thread->burst);
|
||||
brst = thread->burst;
|
||||
|
||||
if(fgets(buffer, BUFF_LEN-1, fp)) { buffer[strlen(buffer)-1] = '\0';
|
||||
char* token = strtok(buffer, " \t");
|
||||
int ntokens = 0;
|
||||
|
||||
while(token) {
|
||||
if(isEmpty(token)) {
|
||||
token = strtok(NULL, " \t");
|
||||
continue;
|
||||
} else if(isInt(token)) {
|
||||
switch(ntokens) {
|
||||
case 0: thread->threadNum = atol(token); break;
|
||||
case 1: thread->arriveTime = atol(token); break;
|
||||
case 2: thread->nbursts = atol(token); break;
|
||||
default: return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ntokens++;
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
if(ntokens != 3) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0; i<thread->nbursts; i++) {
|
||||
if(readBurst(fp, brst)) {
|
||||
brst->next = malloc(sizeof(Burst));
|
||||
assert(brst->next);
|
||||
prev = brst;
|
||||
brst = brst->next;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(thread->nbursts == 0) {
|
||||
free(thread->burst);
|
||||
thread->burst = NULL;
|
||||
} else {
|
||||
free(brst);
|
||||
prev->next = NULL;
|
||||
}
|
||||
|
||||
thread->data.serviceTime = 0;
|
||||
thread->data.ioTime = 0;
|
||||
thread->data.turnAroundTime = 0;
|
||||
thread->data.finishTime = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readProcess(FILE* fp, Process* process) {
|
||||
char buffer[BUFF_LEN];
|
||||
Thread* thrd = NULL;
|
||||
Thread* prev = NULL;
|
||||
|
||||
if(!process) {
|
||||
return false;
|
||||
}
|
||||
|
||||
process->thread = malloc(sizeof(Thread));
|
||||
assert(process->thread);
|
||||
thrd = process->thread;
|
||||
|
||||
if(fgets(buffer, BUFF_LEN-1, fp)) { buffer[strlen(buffer)-1] = '\0';
|
||||
char* token = strtok(buffer, " \t");
|
||||
int ntokens = 0;
|
||||
|
||||
while(token) {
|
||||
if(isEmpty(token)) {
|
||||
token = strtok(NULL, " \t");
|
||||
continue;
|
||||
} else if(isInt(token)) {
|
||||
switch(ntokens) {
|
||||
case 0: process->processNum = atol(token); break;
|
||||
case 1: process->nthreads = atol(token); break;
|
||||
default: return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ntokens++;
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
if(ntokens != 2) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0; i<process->nthreads; i++) {
|
||||
if(readThread(fp, thrd)) {
|
||||
thrd->next = malloc(sizeof(Thread));
|
||||
assert(thrd->next);
|
||||
prev = thrd;
|
||||
thrd = thrd->next;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(process->nthreads == 0) {
|
||||
free(process->thread);
|
||||
process->thread = NULL;
|
||||
} else {
|
||||
free(thrd);
|
||||
prev->next = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* reads input from a stream to create a schedule
|
||||
* args: the stream to read from
|
||||
* returns: a schedule with specs from file */
|
||||
Schedule readSchedule(FILE* fp) {
|
||||
Schedule schedule;
|
||||
char buffer[BUFF_LEN];
|
||||
Process* proc = NULL;
|
||||
Process* prev = NULL;
|
||||
|
||||
schedule.nprocesses = 0;
|
||||
schedule.switchSame = 0;
|
||||
schedule.switchNew = 0;
|
||||
schedule.process = NULL;
|
||||
|
||||
if(fp == NULL) {
|
||||
fprintf(stderr, "Unable to read from file.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
schedule.process = malloc(sizeof(Process));
|
||||
assert(schedule.process);
|
||||
proc = schedule.process;
|
||||
|
||||
while(fgets(buffer, BUFF_LEN-1, fp)) { buffer[strlen(buffer)-1] = '\0';
|
||||
char* token = strtok(buffer, " \t");
|
||||
int ntokens = 0;
|
||||
|
||||
while(token) {
|
||||
if(isEmpty(token)) {
|
||||
token = strtok(NULL, " \t");
|
||||
continue;
|
||||
} else if(isInt(token)) {
|
||||
switch(ntokens) {
|
||||
case 0: schedule.nprocesses = atol(token); break;
|
||||
case 1: schedule.switchSame = atol(token); break;
|
||||
case 2: schedule.switchNew = atol(token); break;
|
||||
default:
|
||||
fprintf(stderr, "Unexpected file contents.\n");
|
||||
freeSchedule(schedule);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unexpected file contents.\n");
|
||||
freeSchedule(schedule);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ntokens++;
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
|
||||
if(ntokens != 3) {
|
||||
fprintf(stderr, "Unexpected file contents.\n");
|
||||
freeSchedule(schedule);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for(int i=0; i<schedule.nprocesses; i++) {
|
||||
if(readProcess(fp, proc)) {
|
||||
proc->next = malloc(sizeof(Process));
|
||||
assert(proc->next);
|
||||
prev = proc;
|
||||
proc = proc->next;
|
||||
} else {
|
||||
fprintf(stderr, "Unexpected file contents.\n");
|
||||
freeSchedule(schedule);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(schedule.nprocesses == 0) {
|
||||
fprintf(stderr, "Unexpected file contents.\n");
|
||||
freeSchedule(schedule);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
free(proc);
|
||||
prev->next = NULL;
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
static void freeBurst(Burst* burst) {
|
||||
if(!burst) return;
|
||||
|
||||
freeBurst(burst->next);
|
||||
free(burst);
|
||||
}
|
||||
|
||||
static void freeThread(Thread* thread) {
|
||||
if(!thread) return;
|
||||
|
||||
freeThread(thread->next);
|
||||
freeBurst(thread->burst);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
static void freeProcess(Process* process) {
|
||||
if(!process) return;
|
||||
|
||||
freeProcess(process->next);
|
||||
freeThread(process->thread);
|
||||
free(process);
|
||||
}
|
||||
|
||||
|
||||
/* frees all memory allocated for the schedule
|
||||
* args: the schedule to deallocate */
|
||||
void freeSchedule(Schedule schedule) {
|
||||
freeProcess(schedule.process);
|
||||
}
|
||||
132
schedule.h
Normal file
132
schedule.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef __SCHEDULE_H_
|
||||
#define __SCHEDULE_H_
|
||||
|
||||
#include "mode.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define BUFF_LEN 1024
|
||||
|
||||
/*
|
||||
|
||||
Schedule schedule:
|
||||
|
||||
int nprocesses
|
||||
int switchSame
|
||||
int switchNew
|
||||
Process* process:
|
||||
|
||||
int processNum
|
||||
int nthreads
|
||||
Process* next
|
||||
Thread* thread:
|
||||
|
||||
int threadNum
|
||||
int arriveTime
|
||||
int nbursts
|
||||
Thread* next
|
||||
Burst* burst:
|
||||
|
||||
int burstNum
|
||||
int cpuTime
|
||||
int ioTime
|
||||
Burst* next
|
||||
|
||||
Data data:
|
||||
|
||||
int serviceTime
|
||||
int ioTime
|
||||
int turnAroundTime
|
||||
int finishTime
|
||||
|
||||
Queue queue:
|
||||
|
||||
int size
|
||||
Event* event:
|
||||
|
||||
int ofProcess
|
||||
int ready
|
||||
Thread* thread:
|
||||
|
||||
int threadNum
|
||||
int arriveTime
|
||||
int nbursts
|
||||
Thread* next
|
||||
Burst* burst:
|
||||
|
||||
int burstNum
|
||||
int cpuTime
|
||||
int ioTime
|
||||
Burst* next
|
||||
|
||||
Data data:
|
||||
|
||||
int serviceTime
|
||||
int ioTime
|
||||
int turnAroundTime
|
||||
int finishTime
|
||||
|
||||
|
||||
*/
|
||||
|
||||
typedef struct Data {
|
||||
int serviceTime;
|
||||
int ioTime;
|
||||
int turnAroundTime;
|
||||
int finishTime;
|
||||
} Data;
|
||||
|
||||
typedef struct Burst {
|
||||
int burstNum;
|
||||
int cpuTime;
|
||||
int ioTime;
|
||||
struct Burst* next;
|
||||
} Burst;
|
||||
|
||||
typedef struct Thread {
|
||||
int threadNum;
|
||||
int arriveTime;
|
||||
int nbursts;
|
||||
Burst* burst;
|
||||
Data data;
|
||||
struct Thread* next;
|
||||
} Thread;
|
||||
|
||||
typedef struct Process {
|
||||
int processNum;
|
||||
int nthreads;
|
||||
Thread* thread;
|
||||
struct Process* next;
|
||||
} Process;
|
||||
|
||||
typedef struct Schedule {
|
||||
int nprocesses;
|
||||
int switchSame;
|
||||
int switchNew;
|
||||
Process* process;
|
||||
} Schedule;
|
||||
|
||||
typedef struct Event {
|
||||
Thread* thread;
|
||||
int ofProcess;
|
||||
int ready;
|
||||
} Event;
|
||||
|
||||
typedef struct Queue {
|
||||
int size;
|
||||
Event* event;
|
||||
} Queue;
|
||||
|
||||
/* reads input from a stream to create a schedule
|
||||
* args: the stream to read from
|
||||
* returns: a schedule with specs from file */
|
||||
Schedule readSchedule(FILE* fp);
|
||||
|
||||
/* frees all memory allocated for the schedule
|
||||
* args: the schedule to deallocate */
|
||||
void freeSchedule(Schedule schedule);
|
||||
|
||||
#endif
|
||||
15
sim2.txt
Normal file
15
sim2.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
3 3 7
|
||||
1 2
|
||||
1 0 2
|
||||
1 10 20
|
||||
2 10
|
||||
2 5 2
|
||||
1 50 10
|
||||
2 50
|
||||
2 1
|
||||
1 0 1
|
||||
1 100
|
||||
3 1
|
||||
1 25 2
|
||||
1 100 20
|
||||
2 100
|
||||
219
simulation.c
Normal file
219
simulation.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "simulation.h"
|
||||
|
||||
/* compare function for qsort. sort queue on arrival times */
|
||||
static int compareEvent(const void* event1, const void* event2) {
|
||||
Event e1 = *(Event*)event1;
|
||||
Event e2 = *(Event*)event2;
|
||||
|
||||
return (e1.ready > e2.ready) - (e1.ready < e2.ready);
|
||||
}
|
||||
|
||||
/* create an initial queue from a fresh schedule */
|
||||
static Queue newQueue(Schedule schedule) {
|
||||
Queue queue = {.size = 0, .event = NULL};
|
||||
Process* proc = schedule.process;
|
||||
|
||||
for(int i=0; i<schedule.nprocesses; i++) {
|
||||
Thread* thread = proc->thread;
|
||||
|
||||
for(int j=0; j<proc->nthreads; j++) {
|
||||
queue.event = realloc(queue.event, (queue.size+1)*sizeof(Event));
|
||||
assert(queue.event);
|
||||
queue.event[queue.size].thread = thread;
|
||||
queue.event[queue.size].ofProcess = proc->processNum;
|
||||
queue.event[queue.size].ready = thread->arriveTime;
|
||||
queue.size++;
|
||||
|
||||
thread = thread->next;
|
||||
}
|
||||
proc = proc->next;
|
||||
}
|
||||
qsort(queue.event, queue.size, sizeof(Event), compareEvent);
|
||||
return queue;
|
||||
}
|
||||
|
||||
/* Simulates a cpu thread scheduler for rr or fcfs.
|
||||
* args: the schedule to simulate, and the mode in which to simulate it */
|
||||
void simulate(Schedule schedule, Mode mode) {
|
||||
Queue queue = newQueue(schedule);
|
||||
Process* proc = schedule.process;
|
||||
char* verbose = malloc(1); verbose[0] = '\0';
|
||||
int idle = 0;
|
||||
int cpuTime = 0;
|
||||
int timeSlice = 0;
|
||||
int turnAround = 0;
|
||||
int totalTime = 0;
|
||||
int nthreads = 0;
|
||||
|
||||
if(mode.roundRobin) {
|
||||
printf("Round Robin Scheduling (quantum = %d time units)\n", mode.quantum);
|
||||
} else {
|
||||
printf("First Come First Serve Scheduling\n");
|
||||
}
|
||||
|
||||
for(int i=0; i<queue.size; i++) {
|
||||
if(mode.verbose) {
|
||||
char buff[BUFF_LEN];
|
||||
int sysTime = timeSlice;
|
||||
|
||||
if(timeSlice <= queue.event[i].ready) {
|
||||
sysTime = queue.event[i].ready;
|
||||
}
|
||||
|
||||
sprintf(buff, "At time %d: Thread %d of Process %d moves from new to ready\n",
|
||||
sysTime, queue.event[i].thread->threadNum, queue.event[i].ofProcess);
|
||||
verbose = realloc(verbose, strlen(verbose)+strlen(buff)+1);
|
||||
assert(verbose);
|
||||
strcat(verbose, buff);
|
||||
}
|
||||
|
||||
if(i > 0) { // context switch
|
||||
if(queue.event[i].ofProcess == queue.event[i-1].ofProcess) {
|
||||
if(queue.event[i].thread->threadNum == queue.event[i-1].thread->threadNum) {
|
||||
//no overhead
|
||||
} else {
|
||||
timeSlice += schedule.switchSame;
|
||||
idle += schedule.switchSame;
|
||||
}
|
||||
} else {
|
||||
timeSlice += schedule.switchNew;
|
||||
idle += schedule.switchNew;
|
||||
}
|
||||
}
|
||||
|
||||
if(timeSlice <= queue.event[i].ready) { // nothing waiting for the cpu
|
||||
idle += queue.event[i].ready - timeSlice;
|
||||
timeSlice = queue.event[i].ready; // advance the timer
|
||||
}
|
||||
|
||||
if(mode.verbose) {
|
||||
char buff[BUFF_LEN];
|
||||
|
||||
sprintf(buff, "At time %d: Thread %d of Process %d moves from ready to running\n",
|
||||
timeSlice, queue.event[i].thread->threadNum, queue.event[i].ofProcess);
|
||||
verbose = realloc(verbose, strlen(verbose)+strlen(buff)+1);
|
||||
assert(verbose);
|
||||
strcat(verbose, buff);
|
||||
}
|
||||
|
||||
// run threads in queue's burst. then kick it out for io or quantum
|
||||
if(mode.roundRobin) {
|
||||
if(queue.event[i].thread->burst->cpuTime > mode.quantum) {
|
||||
timeSlice += mode.quantum;
|
||||
cpuTime += mode.quantum;
|
||||
queue.event[i].thread->burst->cpuTime -= mode.quantum;
|
||||
queue.event[i].thread->data.serviceTime += mode.quantum;
|
||||
} else {
|
||||
timeSlice += queue.event[i].thread->burst->cpuTime;
|
||||
cpuTime += queue.event[i].thread->burst->cpuTime;
|
||||
queue.event[i].thread->data.serviceTime += queue.event[i].thread->burst->cpuTime;
|
||||
queue.event[i].thread->data.ioTime += queue.event[i].thread->burst->ioTime;
|
||||
queue.event[i].thread->burst->cpuTime = 0;
|
||||
}
|
||||
} else {
|
||||
timeSlice += queue.event[i].thread->burst->cpuTime;
|
||||
cpuTime += queue.event[i].thread->burst->cpuTime;
|
||||
queue.event[i].thread->data.ioTime += queue.event[i].thread->burst->ioTime;
|
||||
queue.event[i].thread->data.serviceTime += queue.event[i].thread->burst->cpuTime;
|
||||
}
|
||||
queue.event[i].thread->data.turnAroundTime = timeSlice - queue.event[i].thread->arriveTime;
|
||||
queue.event[i].thread->data.finishTime = timeSlice;
|
||||
|
||||
if(mode.roundRobin && queue.event[i].thread->burst->cpuTime > 0) {
|
||||
queue.event = realloc(queue.event, (queue.size+1)*sizeof(Event));
|
||||
assert(queue.event);
|
||||
queue.event[queue.size] = queue.event[i];
|
||||
queue.event[queue.size].ready = timeSlice;
|
||||
queue.size++;
|
||||
qsort(queue.event, queue.size, sizeof(Event), compareEvent);
|
||||
|
||||
if(mode.verbose) {
|
||||
char buff[BUFF_LEN];
|
||||
|
||||
sprintf(buff, "At time %d: Thread %d of Process %d moves from running to blocked\n",
|
||||
timeSlice, queue.event[i].thread->threadNum, queue.event[i].ofProcess);
|
||||
verbose = realloc(verbose, strlen(verbose)+strlen(buff)+1);
|
||||
assert(verbose);
|
||||
strcat(verbose, buff);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// place unfinished threads back into the queue with their apropriate ready time
|
||||
if(queue.event[i].thread->burst->next) {
|
||||
Burst* temp = queue.event[i].thread->burst;
|
||||
|
||||
if(mode.verbose) {
|
||||
char buff[BUFF_LEN];
|
||||
|
||||
sprintf(buff, "At time %d: Thread %d of Process %d moves from running to blocked\n",
|
||||
timeSlice, queue.event[i].thread->threadNum, queue.event[i].ofProcess);
|
||||
verbose = realloc(verbose, strlen(verbose)+strlen(buff)+1);
|
||||
assert(verbose);
|
||||
strcat(verbose, buff);
|
||||
}
|
||||
queue.event = realloc(queue.event, (queue.size+1)*sizeof(Event));
|
||||
assert(queue.event);
|
||||
queue.event[queue.size] = queue.event[i];
|
||||
queue.event[queue.size].thread->burst = queue.event[queue.size].thread->burst->next;
|
||||
queue.event[queue.size].ready = timeSlice + queue.event[i].thread->burst->ioTime;
|
||||
queue.size++;
|
||||
qsort(queue.event, queue.size, sizeof(Event), compareEvent);
|
||||
free(temp);
|
||||
} else if(mode.verbose) {
|
||||
char buff[BUFF_LEN];
|
||||
|
||||
sprintf(buff, "At time %d: Thread %d of Process %d moves from running to terminated\n",
|
||||
timeSlice, queue.event[i].thread->threadNum, queue.event[i].ofProcess);
|
||||
verbose = realloc(verbose, strlen(verbose)+strlen(buff)+1);
|
||||
assert(verbose);
|
||||
strcat(verbose, buff);
|
||||
}
|
||||
}
|
||||
|
||||
// simulation is over, begin calculating and displaying stats
|
||||
|
||||
totalTime = timeSlice;
|
||||
printf("Total Time required is %d time units.\n", totalTime);
|
||||
|
||||
for(int i=0; i<schedule.nprocesses; i++) {
|
||||
Thread* thread = proc->thread;
|
||||
|
||||
for(int j=0; j<proc->nthreads; j++) {
|
||||
turnAround += thread->data.turnAroundTime;
|
||||
thread = thread->next;
|
||||
nthreads++;
|
||||
}
|
||||
proc = proc->next;
|
||||
}
|
||||
|
||||
printf("Average Turnaround Time is %d time units.\n", turnAround/nthreads);
|
||||
printf("CPU Utilization is %.1f%%.\n", ((float)cpuTime/(float)totalTime)*100);
|
||||
|
||||
if(mode.detailed) {
|
||||
proc = schedule.process;
|
||||
|
||||
printf("\n");
|
||||
|
||||
for(int i=0; i<schedule.nprocesses; i++) {
|
||||
Thread* thread = proc->thread;
|
||||
|
||||
for(int j=0; j<proc->nthreads; j++) {
|
||||
printf("Thread %d of Process %d:\n", thread->threadNum, proc->processNum);
|
||||
printf(" arrival time: %d\n", thread->arriveTime);
|
||||
printf(" service time: %d units, I/O time: %d units, turnaround time: %d units\n"
|
||||
, thread->data.serviceTime, thread->data.ioTime, thread->data.turnAroundTime);
|
||||
printf(" finish time: %d\n", thread->data.finishTime);
|
||||
thread = thread->next;
|
||||
}
|
||||
proc = proc->next;
|
||||
}
|
||||
}
|
||||
|
||||
if(mode.verbose) {
|
||||
printf("\n%s", verbose);
|
||||
}
|
||||
|
||||
free(verbose);
|
||||
free(queue.event);
|
||||
}
|
||||
11
simulation.h
Normal file
11
simulation.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef _SIMULATION_H_
|
||||
#define _SIMULATION_H_
|
||||
|
||||
#include "schedule.h"
|
||||
#include "mode.h"
|
||||
|
||||
/* Simulates a cpu thread scheduler for rr or fcfs.
|
||||
* args: the schedule to simulate, and the mode in which to simulate it */
|
||||
void simulate(Schedule schedule, Mode mode);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user