From 7071def097ec5e7491002d0b373dc6cbe0ea753b Mon Sep 17 00:00:00 2001 From: AhmedHamed3699 Date: Mon, 22 Apr 2024 14:10:32 +0200 Subject: [PATCH 1/2] feat(scheduler): Create RR Scheduling Algorithm --- code/process_generator.c | 32 ++++----- code/process_generator.h | 2 +- code/scheduler.c | 138 ++++++++++++++++++++++++++------------- code/scheduler.h | 9 ++- 4 files changed, 112 insertions(+), 69 deletions(-) diff --git a/code/process_generator.c b/code/process_generator.c index 67f61d5..bfa785f 100644 --- a/code/process_generator.c +++ b/code/process_generator.c @@ -9,6 +9,7 @@ #include "process_generator.h" #include "headers.h" +#include /** * main - The main function of the process generator. @@ -20,7 +21,7 @@ int main(int argc, char *argv[]) { queue *processes; scheduler_type schedulerType; - int quantum; + int quantum = 0; pid_t schedulerPid, clockPid; int msgQID; @@ -38,7 +39,8 @@ int main(int argc, char *argv[]) { getInput(&schedulerType, &quantum); - createSchedulerAndClock(&schedulerPid, &clockPid, (int)schedulerType); + createSchedulerAndClock(&schedulerPid, &clockPid, (int)schedulerType, + quantum); initClk(); msgQID = initSchGenCom(); @@ -226,7 +228,7 @@ void printBanner() { * @clockPid: a pointer to the clock process id */ void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid, - int schedulerType) { + int schedulerType, int quantum) { *clockPid = fork(); @@ -249,23 +251,13 @@ void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid, } if (*schedulerPid == 0) { - char *type; - - switch (schedulerType) { - case 0: - type = "0"; - break; - case 1: - type = "1"; - break; - case 2: - type = "2"; - break; - default: - exit(-1); - } + char type[2]; + char q[(int)(ceil(log10(quantum)) + 2) * sizeof(char)]; + + sprintf(type, "%d", schedulerType); + sprintf(q, "%d", quantum); - char *args[] = {"./scheduler.out", type, NULL}; + char *args[] = {"./scheduler.out", type, q, NULL}; execvp(args[0], args); exit(0); } @@ -303,7 +295,7 @@ void sendProcessesToScheduler(queue *processes, int msgQID) { printf(ANSI_PURPLE "=>GEN:Sending process with id: %d, AT: %d, BT: %d, " "priority: %d to scheduler\n" ANSI_RESET, process->id, process->AT, process->BT, process->priority); - // TODO: check this intial values later + // TODO: check this initial values later process->RT = 0; process->WT = 0; process->TA = 0; diff --git a/code/process_generator.h b/code/process_generator.h index 9551f27..dc5dfb9 100644 --- a/code/process_generator.h +++ b/code/process_generator.h @@ -12,5 +12,5 @@ queue *readInputFile(); void printBanner(); scheduler_type getSchedulerType(); void getInput(scheduler_type *, int *); -void createSchedulerAndClock(pid_t *, pid_t *, int); +void createSchedulerAndClock(pid_t *, pid_t *, int, int); void sendProcessesToScheduler(queue *, int); diff --git a/code/scheduler.c b/code/scheduler.c index 3955016..86aea27 100644 --- a/code/scheduler.c +++ b/code/scheduler.c @@ -8,6 +8,8 @@ #include "scheduler.h" #include "headers.h" +#include "queue.h" +#include "structs.h" int msgQID; d_list *p_table = NULL; @@ -20,7 +22,7 @@ d_list *p_table = NULL; * return: 0 on success, -1 on failure */ int main(int argc, char *argv[]) { - int key, gen_msgQID, response; + int key, gen_msgQID, response, quantem; scheduler_type schedulerType; d_list *processTable = NULL; @@ -34,7 +36,7 @@ int main(int argc, char *argv[]) { initClk(); - schedulerType = getScType(atoi(argv[1])); + schedulerType = getScParams(argv, &quantem); printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, (int)schedulerType); @@ -46,7 +48,19 @@ int main(int argc, char *argv[]) { msgQID = gen_msgQID = initSchGenCom(); - getProcesses(gen_msgQID, processTable); + switch (schedulerType) { + case HPF: + // HPFScheduling(); + break; + case SRTN: + // SRTNScheduling(); + break; + case RR: + RRScheduling(quantem, gen_msgQID, processTable); + break; + default: + exit(-1); + } // TODO Initialize Scheduler // Create Ready queue & (Wait queue ??) @@ -80,67 +94,99 @@ int main(int argc, char *argv[]) { // Any other clean up } +int RRScheduling(int quantem, int gen_msgQID, d_list *processTable) { + queue *readyQ; + int processesFlag = 1; // to know when to stop getting processes from gen + process_t process; + int currentTime = getClk(); + int lastTime = currentTime; + + readyQ = createQueue(free); + while (1) { + currentTime = getClk(); + if (currentTime == lastTime) + continue; + + if (processesFlag) { + if (getProcess(&processesFlag, gen_msgQID, &process)) { + createProcess(processTable, &process); + + // TODO: change later + // change this later instead of preempting just stop + // because of the stats effect + preemptProcessByIndex(processTable, process.id - 1); + + // FIXME: delete later just for testing + { + sleep(3); + preemptProcessByIndex(processTable, 0); + sleep(1); + resumeProcessByIndex(processTable, 0); + preemptProcessByIndex(processTable, 1); + sleep(1); + resumeProcessByIndex(processTable, 1); + } + } + } + lastTime = currentTime; + } +} + +int SRTNScheduling(); +int HPFScheduling(); + +/** + * getProcess - gets ap process from generator + * + * @gen_msgQID: msg queue with process generator + * @processTable: process table + * + * Return: 0 if no process, 1 if got the process + */ +int getProcess(int *processesFlag, int gen_msgQID, process_t *process) { + int response; + + response = msgrcv(gen_msgQID, process, sizeof(process_t), 0, IPC_NOWAIT); + + if (response == -1) { + if (errno == ENOMSG) + return 0; + perror("Error in receiving process from process generator"); + exit(-1); + } + + if (process->id == -1) { + printf(ANSI_YELLOW "==>SCH: Received All Processes\n" ANSI_RESET); + *processesFlag = 0; + return 0; + } + printf(ANSI_BLUE "==>SCH: Received process with id = %i\n" ANSI_RESET, + process->id); + return 1; +} + /** * getScType - gets scheduler type * * @schedulerType: scheduler type * return: scheduler type enum */ -scheduler_type getScType(int schedulerType) { +scheduler_type getScParams(char *argv[], int *quantem) { + int schedulerType = atoi(argv[1]); + switch (schedulerType) { case 0: return HPF; case 1: return SRTN; case 2: + *quantem = atoi(argv[2]); return RR; default: exit(-1); } } -/** - * getProcesses - gets processes from generator - * - * @gen_msgQID: msg queue with process generator - * @processTable: process table - */ -void getProcesses(int gen_msgQID, d_list *processTable) { - int response; - process_t process; - - while (1) { - response = msgrcv(gen_msgQID, &process, sizeof(process_t), 0, !IPC_NOWAIT); - - if (response == -1) { - perror("Error in receiving process from process generator"); - exit(-1); - } - - if (process.id == -1) { - printf(ANSI_YELLOW "==>SCH: Received All Processes\n" ANSI_RESET); - break; - } - printf(ANSI_BLUE "==>SCH: Received process with id = %i\n" ANSI_RESET, - process.id); - createProcess(processTable, &process); - // TODO: change later - // change this later instead of preempting just stop - // because of the stats effect - preemptProcessByIndex(processTable, process.id - 1); - } - // FIXME: delete later just for testing - { - sleep(3); - preemptProcessByIndex(processTable, 0); - sleep(1); - resumeProcessByIndex(processTable, 0); - preemptProcessByIndex(processTable, 1); - sleep(1); - resumeProcessByIndex(processTable, 1); - } -} - /** * freeProcessEntry - process entry free function * diff --git a/code/scheduler.h b/code/scheduler.h index 9f964a3..3b8a821 100644 --- a/code/scheduler.h +++ b/code/scheduler.h @@ -3,13 +3,18 @@ #include "list.h" #include "structs.h" -scheduler_type getScType(int schedulerType); -void getProcesses(int gen_msgQID, d_list *processTable); +scheduler_type getScParams(char *argv[], int *quantem); +int getProcess(int *processesFlag, int gen_msgQID, process_t *process); void freeProcessEntry(void *processEntry); void createProcess(d_list *processTable, process_t *process); void cleanUpScheduler(); void clearSchResources(int signum); +//=============================== +// Scheduling Algorithms +//=============================== +int RRScheduling(int quantem, int gen_msgQID, d_list *processTable); + //=============================== // Preempting Functions //=============================== From d66edd82531f1a35f5e2867e891191cf676133f1 Mon Sep 17 00:00:00 2001 From: AhmedHamed3699 Date: Mon, 22 Apr 2024 23:44:33 +0200 Subject: [PATCH 2/2] feat(scheduler): Create base functionality of all algorithms --- code/Makefile | 4 +- code/minHeap.c | 202 ++++++++++++++-------------- code/minHeap.h | 43 +++--- code/process_generator.c | 4 +- code/scheduler.c | 276 ++++++++++++++++++++++++++------------- code/scheduler.h | 13 +- code/structs.h | 4 +- 7 files changed, 326 insertions(+), 220 deletions(-) diff --git a/code/Makefile b/code/Makefile index f518067..ed334e1 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1,9 +1,9 @@ .PHONY: build all clean test build: - gcc list.c queue.c process_generator.c -o process_generator.out + gcc list.c queue.c process_generator.c -o process_generator.out -lm gcc clk.c -o clk.out - gcc list.c scheduler.c -o scheduler.out + gcc list.c queue.c minHeap.c scheduler.c -o scheduler.out gcc list.c process.c -o process.out gcc test_generator.c -o test_generator.out diff --git a/code/minHeap.c b/code/minHeap.c index 6527cac..e259bdf 100644 --- a/code/minHeap.c +++ b/code/minHeap.c @@ -3,142 +3,136 @@ /** * @comp: pass a function to be used to compare between any two heap elements - return: + return: - 1: element1 > element2 - -1: element1 < element1 - - 0: element1 = element2 + - 0: element1 = element2 */ -min_heap* createMinHeap(int (*comp)(void *, void *)) -{ - min_heap* newHeap = malloc(sizeof(*newHeap)); - newHeap->arr = malloc(sizeof(void*)); - newHeap->capacity = 1; - newHeap->size = 0; - newHeap->compare = comp; - - return newHeap; +min_heap *createMinHeap(int (*comp)(void *, void *)) { + min_heap *newHeap = malloc(sizeof(*newHeap)); + newHeap->arr = malloc(sizeof(void *)); + newHeap->capacity = 1; + newHeap->size = 0; + newHeap->compare = comp; + + return newHeap; } /** * insert in the heap * pass a void pointer to the element you want to insert -*/ -void insertMinHeap(min_heap** heap, void * element) -{ - printf("entered insertion safely\n"); - printHeap((*heap)); - - if((*heap)->size == (*heap)->capacity) - (*heap) = *doubleCapacity((*heap)); - - (*heap)->arr[(*heap)->size] = element; - (*heap)->size++; - printf("arr[%ld]: %d\n" , (*heap)->size-1 , (int*)(*heap)->arr[(*heap)->size-1]); - decreaseKey((*heap) , (*heap)->size-1); + */ +void insertMinHeap(min_heap **heap, void *element) { + if ((*heap)->size == (*heap)->capacity) + (*heap) = *doubleCapacity((*heap)); + + (*heap)->arr[(*heap)->size] = element; + (*heap)->size++; + decreaseKey((*heap), (*heap)->size - 1); } /** * get the min element in the heap -*/ -void * extractMin(min_heap * heap) -{ - printf("entered extraction!!\n"); - printHeap(heap); - - void* minElement = heap->arr[0]; - heap->size--; - heap->arr[0] = heap->arr[heap->size]; - heap->arr[heap->size]=0; - minHeapify(heap , 0); - - return minElement; + */ +void *extractMin(min_heap *heap) { + void *minElement; + if (!heap || heap->size <= 0) + return NULL; + + minElement = heap->arr[0]; + heap->size--; + heap->arr[0] = heap->arr[heap->size]; + heap->arr[heap->size] = 0; + minHeapify(heap, 0); + + return minElement; +} + +/** + * get the min element in the heap without extracting + */ +void *getMin(min_heap *heap) { + if (!heap || heap->size <= 0) + return NULL; + return heap->arr[0]; } /** * Shift-up operation, called on decreasing the priority value */ -void decreaseKey(min_heap* heap ,int ind){ - if(ind >= heap->size) - return; - - void** arr = heap->arr; - int parentInd = (ind-1)/2; - - while(parentInd >= 0 && arr[parentInd] > arr[ind]){ - swap(arr , ind , parentInd); - ind = parentInd; - parentInd = (ind-1)/2; - } +void decreaseKey(min_heap *heap, int ind) { + if (ind >= heap->size) + return; -} + void **arr = heap->arr; + int parentInd = (ind - 1) / 2; + while (parentInd >= 0 && heap->compare(arr[parentInd], arr[ind]) > 0) { + swap(arr, ind, parentInd); + ind = parentInd; + parentInd = (ind - 1) / 2; + } +} /** * Shift-down operation, used locally -*/ -void minHeapify(min_heap * heap, int ind) -{ - int chInd = 2*ind+1 , minInd = ind; - - bool flag = true; - void** arr = heap->arr; - - while(flag && chInd < heap->size){ - if(heap->compare(arr[ind] , arr[chInd]) > 0) - minInd = chInd; - - - if(chInd+1 < heap->size && heap->compare(arr[minInd] , arr[chInd+1])>0) - minInd = chInd+1; - - if(minInd == ind) - flag = false; - else{ - swap(arr , ind , minInd); - ind = minInd; - chInd = 2*ind+1; - } - } - + */ +void minHeapify(min_heap *heap, int ind) { + int chInd = 2 * ind + 1, minInd = ind; + + bool flag = true; + void **arr = heap->arr; + + while (flag && chInd < heap->size) { + if (heap->compare(arr[ind], arr[chInd]) > 0) + minInd = chInd; + + if (chInd + 1 < heap->size && + heap->compare(arr[minInd], arr[chInd + 1]) > 0) + minInd = chInd + 1; + + if (minInd == ind) + flag = false; + else { + swap(arr, ind, minInd); + ind = minInd; + chInd = 2 * ind + 1; + } + } } - /** - * Description: doubles the size of the array if the max capacity is reached. + * Description: doubles the size of the array if the max capacity is reached. * used in insert function * - initializing new heap by double capacity * - copying data * - freeing memory of the old heap */ -min_heap** doubleCapacity(min_heap *heap) -{ - min_heap* newHeap = malloc(sizeof(*newHeap)); - newHeap->capacity = 2*heap->capacity; - newHeap->arr = calloc(newHeap->capacity , sizeof(void*)); - newHeap->size = heap->size; - newHeap->compare = heap->compare; - for(int i = 0 ; isize ; i++) - newHeap->arr[i] = heap->arr[i]; - - printf("doubling occured!!\n"); - min_heap** returnval = &newHeap; - printHeap(*returnval); - return returnval; +min_heap **doubleCapacity(min_heap *heap) { + min_heap *newHeap = malloc(sizeof(*newHeap)); + newHeap->capacity = 2 * heap->capacity; + newHeap->arr = calloc(newHeap->capacity, sizeof(void *)); + newHeap->size = heap->size; + newHeap->compare = heap->compare; + for (int i = 0; i < heap->size; i++) + newHeap->arr[i] = heap->arr[i]; + + min_heap **returnval = &newHeap; + return returnval; } -void swap(void ** arr, int ind1, int ind2) -{ - void* temp = arr[ind1]; - arr[ind1] = arr[ind2]; - arr[ind2] = temp; - return; +void swap(void **arr, int ind1, int ind2) { + void *temp = arr[ind1]; + arr[ind1] = arr[ind2]; + arr[ind2] = temp; + return; } -void printHeap(min_heap* heap){ - printf("\n=============================\n"); - printf("capacity: %d \nsize: %d\narr:",heap->capacity , heap->size); - for(int i =0 ; i< heap->capacity ; i++) - printf("%d ", heap->arr[i]); - printf("\n=============================\n\n"); -} \ No newline at end of file +void printHeap(min_heap *heap) { + printf("\n=============================\n"); + printf("capacity: %d \nsize: %d\narr:", (int)heap->capacity, (int)heap->size); + for (int i = 0; i < heap->capacity; i++) + printf("%d ", *(int *)heap->arr[i]); + printf("\n=============================\n\n"); +} diff --git a/code/minHeap.h b/code/minHeap.h index 0a6a4c7..c328134 100644 --- a/code/minHeap.h +++ b/code/minHeap.h @@ -1,31 +1,36 @@ #pragma once -#include #include +#include /** * @list: array of data * @size: number of elements in the heap - * @compare: - returns: + * @compare: + returns: - 1: element1 > element2 - - -1: element1 < element1 + - -1: element1 < element2 - 0: element1 = element2 - + * Description: minimum heap structure */ -typedef struct min_heap{ - size_t capacity; - void** arr; - size_t size; - int (*compare)(void* e1, void* e2); -}min_heap; +typedef struct min_heap { + size_t capacity; + void **arr; + size_t size; + int (*compare)(void *e1, void *e2); +} min_heap; -min_heap* createMinHeap(int comp(void* , void* )); //returns pointer on the heap to start using it -void insertMinHeap(min_heap** heap , void* element); //insert new element in the heap -void* extractMin(min_heap* heap); //get the min element -void decreaseKey(min_heap* heap ,int ind); //shift-up operation, called on decreasing the priority value -void minHeapify(min_heap* heap , int ind); -min_heap** doubleCapacity(min_heap* heap); -void swap(void** arr, int ind1, int ind2); -void printHeap(min_heap* heap); \ No newline at end of file +// returns pointer on the heap to start using it +min_heap *createMinHeap(int comp(void *, void *)); +// insert new element in the heap +void insertMinHeap(min_heap **heap, void *element); +// get the min element +void *extractMin(min_heap *heap); +void *getMin(min_heap *heap); +// shift-up operation, called on decreasing the priority value +void decreaseKey(min_heap *heap, int ind); +void minHeapify(min_heap *heap, int ind); +min_heap **doubleCapacity(min_heap *heap); +void swap(void **arr, int ind1, int ind2); +void printHeap(min_heap *heap); diff --git a/code/process_generator.c b/code/process_generator.c index bfa785f..0447287 100644 --- a/code/process_generator.c +++ b/code/process_generator.c @@ -252,7 +252,7 @@ void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid, if (*schedulerPid == 0) { char type[2]; - char q[(int)(ceil(log10(quantum)) + 2) * sizeof(char)]; + char q[5]; sprintf(type, "%d", schedulerType); sprintf(q, "%d", quantum); @@ -296,7 +296,7 @@ void sendProcessesToScheduler(queue *processes, int msgQID) { "priority: %d to scheduler\n" ANSI_RESET, process->id, process->AT, process->BT, process->priority); // TODO: check this initial values later - process->RT = 0; + process->RT = process->BT; process->WT = 0; process->TA = 0; process->LST = currentTime; diff --git a/code/scheduler.c b/code/scheduler.c index 86aea27..f2e966f 100644 --- a/code/scheduler.c +++ b/code/scheduler.c @@ -8,8 +8,6 @@ #include "scheduler.h" #include "headers.h" -#include "queue.h" -#include "structs.h" int msgQID; d_list *p_table = NULL; @@ -37,8 +35,9 @@ int main(int argc, char *argv[]) { initClk(); schedulerType = getScParams(argv, &quantem); - printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, - (int)schedulerType); + if (DEBUG) + printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, + (int)schedulerType); p_table = processTable = createList(freeProcessEntry); if (!processTable) { @@ -47,40 +46,15 @@ int main(int argc, char *argv[]) { } msgQID = gen_msgQID = initSchGenCom(); - - switch (schedulerType) { - case HPF: - // HPFScheduling(); - break; - case SRTN: - // SRTNScheduling(); - break; - case RR: - RRScheduling(quantem, gen_msgQID, processTable); - break; - default: - exit(-1); - } + schedule(schedulerType, quantem, gen_msgQID, processTable); // TODO Initialize Scheduler - // Create Ready queue & (Wait queue ??) + // Create Wait queue ?? // Create log file // // TODO Create process when generator tells you it is time // Setup COM between process and Scheduler (init msgs queue) // - // TODO Context Switch (print to log file in start and finish) - // When SRT process comes to ready queue (by myself) - // When quantem ends (communicate with clk) - // When a process finishes (process get SIGTRM) - // When a process gets a signal (SIGKILL, SIGINT, SIGSTP, ...etc) - // The Switch - // Move old process to ready or wait or (clear after, if it has terminated) - // Save PCB if it still exist (set attributes) - // Schedule new Process (We need the algo here) - // Load PCB (set attributes) - // Tell the process to start - // // TODO Clear After process termination // Calculate all needed values (till now) // Remove process from processes Table (Delete its PCB) @@ -92,48 +66,155 @@ int main(int argc, char *argv[]) { // destroy process table // destroy clk // Any other clean up + return (0); } -int RRScheduling(int quantem, int gen_msgQID, d_list *processTable) { - queue *readyQ; +/** + * Schedule - Main loop of scheduler + * + * @schedulerType: scheduler type + * @quantem: RR quantem + * @gen_msgQID: msg queue ID between generator & scheduler + * @processTable: pointer to process table + */ +void schedule(scheduler_type schType, int quantem, int gen_msgQID, + d_list *processTable) { + void *readyQ; + process_t process, *newProcess; int processesFlag = 1; // to know when to stop getting processes from gen - process_t process; + int rQuantem = quantem; int currentTime = getClk(); int lastTime = currentTime; + int (*algorithm)(void *readyQ, process_t *newProcess, int *rQuantem); + + switch (schType) { + case HPF: + readyQ = createMinHeap(compareHPF); + algorithm = HPFScheduling; + break; + case SRTN: + readyQ = createMinHeap(compareSRTN); + algorithm = SRTNScheduling; + break; + case RR: + readyQ = createQueue(free); + algorithm = RRScheduling; + break; + default: + exit(-1); + } - readyQ = createQueue(free); while (1) { currentTime = getClk(); if (currentTime == lastTime) continue; + newProcess = NULL; if (processesFlag) { - if (getProcess(&processesFlag, gen_msgQID, &process)) { - createProcess(processTable, &process); - - // TODO: change later - // change this later instead of preempting just stop - // because of the stats effect - preemptProcessByIndex(processTable, process.id - 1); - - // FIXME: delete later just for testing - { - sleep(3); - preemptProcessByIndex(processTable, 0); - sleep(1); - resumeProcessByIndex(processTable, 0); - preemptProcessByIndex(processTable, 1); - sleep(1); - resumeProcessByIndex(processTable, 1); - } - } - } + if (getProcess(&processesFlag, gen_msgQID, &process)) + newProcess = createProcess(processTable, &process); + + algorithm(readyQ, newProcess, &rQuantem); + if (rQuantem <= 0) + rQuantem = quantem; + } else + break; // TODO Change it later lastTime = currentTime; } } -int SRTNScheduling(); -int HPFScheduling(); +/** + * compareHPF - compare function for HPF ready queue + * + * @e1: pointer to first element + * @e2: pointer to first element + * Return: 1 if e1 priority is higher, -1 if e2 is higher, 0 if they are equal + */ +int compareHPF(void *e1, void *e2) { + if (((process_t *)e1)->priority < ((process_t *)e2)->priority) + return -1; + else if (((process_t *)e1)->priority > ((process_t *)e2)->priority) + return 1; + return 0; +} + +/** + * compareSRTN - compare function for SRTN ready queue + * + * @e1: pointer to first element + * @e2: pointer to first element + * Return: 1 if e2 Remaining Time is less, -1 if e1 is less, 0 if they are equal + */ +int compareSRTN(void *e1, void *e2) { + if (((process_t *)e1)->RT < ((process_t *)e2)->RT) + return -1; + else if (((process_t *)e1)->RT > ((process_t *)e2)->RT) + return 1; + return 0; +} + +/** + * HPFScheduling - HPF scheduling algorithm + * + * @readyQueue: scheduler ready queue + * @process: pointer to process + * @rQuantem: remaining quantem time + * + * Return: 1 on success, 0 on failure + */ +int HPFScheduling(void *readyQueue, process_t *process, int *rQuantem) { + min_heap *readyQ = (min_heap *)readyQueue; + + if (process) + insertMinHeap(&readyQ, process); + return 1; +} + +/** + * SRTNScheduling - HPF scheduling algorithm + * + * @readyQueue: scheduler ready queue + * @process: pointer to process + * @rQuantem: remaining quantem time + * + * Return: 1 on success, 0 on failure + */ +int SRTNScheduling(void *readyQueue, process_t *process, int *rQuantem) { + min_heap *readyQ = (min_heap *)readyQueue; + process_t *currentProcess; + + if (process) { + insertMinHeap(&readyQ, process); + currentProcess = (process_t *)getMin(readyQ); + if (process == currentProcess) + contextSwitch(); + } + + return 1; +} + +/** + * RRScheduling - RR scheduling algorithm + * + * @readyQueue: scheduler ready queue + * @process: pointer to process + * @rQuantem: remaining quantem time + * + * Return: 1 on success, 0 on failure + */ +int RRScheduling(void *readyQueue, process_t *process, int *rQuantem) { + queue *readyQ = (queue *)readyQueue; + + if (process) + push(readyQ, process); + + if (!empty(readyQ)) { + (*rQuantem)--; + if (*rQuantem <= 0) + contextSwitch(); + } + return 1; +} /** * getProcess - gets ap process from generator @@ -149,8 +230,9 @@ int getProcess(int *processesFlag, int gen_msgQID, process_t *process) { response = msgrcv(gen_msgQID, process, sizeof(process_t), 0, IPC_NOWAIT); if (response == -1) { - if (errno == ENOMSG) + if (errno == ENOMSG) { return 0; + } perror("Error in receiving process from process generator"); exit(-1); } @@ -194,7 +276,7 @@ scheduler_type getScParams(char *argv[], int *quantem) { */ void freeProcessEntry(void *processEntry) { if (processEntry) - free(((process_entry_t *)processEntry)->PCB); + free(((process_entry_t *)processEntry)->PCB.process); free(processEntry); } @@ -204,10 +286,10 @@ void freeProcessEntry(void *processEntry) { * @processTable: pointer to process table * @process: pointer to new process info */ -void createProcess(d_list *processTable, process_t *process) { +process_t *createProcess(d_list *processTable, process_t *process) { pid_t pid; process_entry_t *processEntry; - PCB_t *pcb; + process_t *pcbProcess; pid = fork(); @@ -228,43 +310,38 @@ void createProcess(d_list *processTable, process_t *process) { exit(-1); } - pcb = malloc(sizeof(*pcb)); - if (!pcb) { + pcbProcess = malloc(sizeof(*pcbProcess)); + if (!pcbProcess) { perror("malloc"); exit(-1); } - pcb->state = READY; - pcb->process = *process; + *pcbProcess = *process; processEntry->p_id = pid; - processEntry->PCB = pcb; + processEntry->PCB.state = READY; + processEntry->PCB.process = pcbProcess; if (!insertNodeEnd(processTable, processEntry)) { perror("insertNodeEnd"); exit(-1); } printf(ANSI_GREEN "==>SCH: Added process to processes table\n" ANSI_RESET); + return pcbProcess; } -/** - * cleanUpScheduler - Make necessary cleaning - */ -void cleanUpScheduler() { - msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); - destroyClk(true); - if (p_table) - destroyList(&p_table); - killpg(getpgrp(), SIGINT); -} - -/** - * clearSchResources - Clears all resources in case of interruption. - * - * @signum: the signal number - */ -void clearSchResources(int signum) { - cleanUpScheduler(); - exit(0); +void contextSwitch() { + printf(ANSI_BLUE "==>SCH: Context Switching\n" ANSI_RESET); + // TODO Context Switch (print to log file in start and finish) + // When SRT process comes to ready queue (by myself) + // When quantem ends (communicate with clk) + // When a process finishes (process get SIGTRM) + // When a process gets a signal (SIGKILL, SIGINT, SIGSTP, ...etc) + // The Switch + // Move old process to ready or wait or (clear after, if it has terminated) + // Save PCB if it still exist (set attributes) + // Schedule new Process (We need the algo here) + // Load PCB (set attributes) + // Tell the process to start } /** @@ -274,7 +351,7 @@ void clearSchResources(int signum) { */ void preemptProcessByIndex(d_list *processTable, unsigned int index) { process_entry_t *processEntry = getNode(processTable, index)->data; - PCB_t *pcb = processEntry->PCB; + PCB_t *pcb = &processEntry->PCB; if (DEBUG) printf(ANSI_GREY "==>SCH: Preempting process with id = %i\n" ANSI_RESET, @@ -283,7 +360,7 @@ void preemptProcessByIndex(d_list *processTable, unsigned int index) { if (pcb->state == RUNNING) { kill(processEntry->p_id, SIGSTOP); pcb->state = READY; - pcb->process.LST = getClk(); + pcb->process->LST = getClk(); } } @@ -294,7 +371,7 @@ void preemptProcessByIndex(d_list *processTable, unsigned int index) { */ void resumeProcessByIndex(d_list *processTable, unsigned int index) { process_entry_t *processEntry = getNode(processTable, index)->data; - PCB_t *pcb = processEntry->PCB; + PCB_t *pcb = &processEntry->PCB; if (DEBUG) printf(ANSI_GREEN "==>SCH: Resuming process with id = %i\n" ANSI_RESET, @@ -303,6 +380,27 @@ void resumeProcessByIndex(d_list *processTable, unsigned int index) { if (pcb->state == READY) { kill(processEntry->p_id, SIGCONT); pcb->state = RUNNING; - pcb->process.WT += getClk() - pcb->process.LST; + pcb->process->WT += getClk() - pcb->process->LST; } } + +/** + * cleanUpScheduler - Make necessary cleaning + */ +void cleanUpScheduler() { + msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); + destroyClk(true); + if (p_table) + destroyList(&p_table); + killpg(getpgrp(), SIGINT); +} + +/** + * clearSchResources - Clears all resources in case of interruption. + * + * @signum: the signal number + */ +void clearSchResources(int signum) { + cleanUpScheduler(); + exit(0); +} diff --git a/code/scheduler.h b/code/scheduler.h index 3b8a821..b3323f5 100644 --- a/code/scheduler.h +++ b/code/scheduler.h @@ -1,19 +1,28 @@ #pragma once #include "list.h" +#include "minHeap.h" +#include "queue.h" #include "structs.h" scheduler_type getScParams(char *argv[], int *quantem); int getProcess(int *processesFlag, int gen_msgQID, process_t *process); void freeProcessEntry(void *processEntry); -void createProcess(d_list *processTable, process_t *process); +process_t *createProcess(d_list *processTable, process_t *process); void cleanUpScheduler(); void clearSchResources(int signum); //=============================== // Scheduling Algorithms //=============================== -int RRScheduling(int quantem, int gen_msgQID, d_list *processTable); +void schedule(scheduler_type schType, int quantem, int gen_msgQID, + d_list *processTable); +int compareHPF(void *e1, void *e2); +int compareSRTN(void *e1, void *e2); +int HPFScheduling(void *readyQueue, process_t *process, int *rQuantem); +int SRTNScheduling(void *readyQueue, process_t *process, int *rQuantem); +int RRScheduling(void *readyQueue, process_t *process, int *rQuantem); +void contextSwitch(); //=============================== // Preempting Functions diff --git a/code/structs.h b/code/structs.h index a8d29ef..c3e49b3 100644 --- a/code/structs.h +++ b/code/structs.h @@ -21,12 +21,12 @@ typedef struct process { typedef struct PCB { process_state state; - process_t process; + process_t *process; } PCB_t; typedef struct process_entry { int p_id; - PCB_t *PCB; + PCB_t PCB; } process_entry_t; typedef struct cleanup_data {