From db2f77e3a5a57dba99f6ec22c26c1f3a5ed2ae4b Mon Sep 17 00:00:00 2001 From: AhmedHamed3699 Date: Sun, 14 Apr 2024 01:33:24 +0200 Subject: [PATCH 1/3] fix(DS): add free function --- code/list.c | 363 ++++++++++++++++++++++++--------------------------- code/list.h | 25 ++-- code/queue.c | 96 ++++++-------- code/queue.h | 9 +- 4 files changed, 233 insertions(+), 260 deletions(-) diff --git a/code/list.c b/code/list.c index 2701311..911d7a5 100644 --- a/code/list.c +++ b/code/list.c @@ -6,18 +6,18 @@ * * Return: pointer to new list, NULL on failure */ -d_list *createList() -{ - d_list *newList; +d_list *createList(void (*free_func)(void *)) { + d_list *newList; - newList = malloc(sizeof(*newList)); - if (!newList) - return (NULL); + newList = malloc(sizeof(*newList)); + if (!newList) + return (NULL); - newList->size = 0; - newList->head = newList->tail = NULL; + newList->size = 0; + newList->head = newList->tail = NULL; + newList->free_func = free_func; - return (newList); + return (newList); } /** @@ -27,40 +27,34 @@ d_list *createList() * * Return: pointer to node at index */ -d_node *getNode(d_list *list, unsigned int index) -{ - d_node *ptr; - int dir = FORWARD; - unsigned int i = 0; - - if (!list) - return (NULL); - - ptr = list->head; - if (index > (list->size / 2)) - { - dir = BACKWARD; - ptr = list->tail; - i = list->size - 1; - } - - while (ptr) - { - if (i == index) - return (ptr); - - if (dir == FORWARD) - { - i++; - ptr = ptr->next; - } - else - { - i--; - ptr = ptr->prev; - } - } - return (NULL); +d_node *getNode(d_list *list, unsigned int index) { + d_node *ptr; + int dir = FORWARD; + unsigned int i = 0; + + if (!list) + return (NULL); + + ptr = list->head; + if (index > (list->size / 2)) { + dir = BACKWARD; + ptr = list->tail; + i = list->size - 1; + } + + while (ptr) { + if (i == index) + return (ptr); + + if (dir == FORWARD) { + i++; + ptr = ptr->next; + } else { + i--; + ptr = ptr->prev; + } + } + return (NULL); } /** @@ -70,28 +64,27 @@ d_node *getNode(d_list *list, unsigned int index) * * Return: pointer to new node, NULL in failure */ -d_node *insertNodeStart(d_list *list, void *n) -{ - d_node *newNode; +d_node *insertNodeStart(d_list *list, void *n) { + d_node *newNode; - if (!list) - return (NULL); + if (!list) + return (NULL); - newNode = malloc(sizeof(*newNode)); - if (!newNode) - return (NULL); + newNode = malloc(sizeof(*newNode)); + if (!newNode) + return (NULL); - newNode->data = n, newNode->prev = NULL; - newNode->next = list->head; + newNode->data = n, newNode->prev = NULL; + newNode->next = list->head; - if (list->head) - list->head->prev = newNode; - else - list->tail = newNode; - list->head = newNode; - list->size++; + if (list->head) + list->head->prev = newNode; + else + list->tail = newNode; + list->head = newNode; + list->size++; - return (newNode); + return (newNode); } /** @@ -101,28 +94,27 @@ d_node *insertNodeStart(d_list *list, void *n) * * Return: pointer to new node, NULL in failure */ -d_node *insertNodeEnd(d_list *list, void *n) -{ - d_node *newNode; +d_node *insertNodeEnd(d_list *list, void *n) { + d_node *newNode; - if (!list) - return (NULL); + if (!list) + return (NULL); - newNode = malloc(sizeof(*newNode)); - if (!newNode) - return (NULL); + newNode = malloc(sizeof(*newNode)); + if (!newNode) + return (NULL); - newNode->data = n, newNode->next = NULL; - newNode->prev = list->tail; + newNode->data = n, newNode->next = NULL; + newNode->prev = list->tail; - if (list->tail) - list->tail->next = newNode; - else - list->head = newNode; - list->tail = newNode; - list->size++; + if (list->tail) + list->tail->next = newNode; + else + list->head = newNode; + list->tail = newNode; + list->size++; - return (newNode); + return (newNode); } /** @@ -133,32 +125,31 @@ d_node *insertNodeEnd(d_list *list, void *n) * * Return: pointet to new node, NULL in failure */ -d_node *insertNode(d_list *list, unsigned int index, void *n) -{ - d_node *newNode, *ptr; - - if (!list) - return (NULL); - if (!index) - return (insertNodeStart(list, n)); - if (index == list->size) - return (insertNodeEnd(list, n)); - if (index > list->size) - return (NULL); - - ptr = getNode(list, index); - newNode = malloc(sizeof(*newNode)); - if (!newNode) - return (NULL); - - newNode->data = n; - newNode->next = ptr; - newNode->prev = ptr->prev; - newNode->prev->next = newNode; - newNode->next->prev = newNode; - list->size++; - - return (newNode); +d_node *insertNode(d_list *list, unsigned int index, void *n) { + d_node *newNode, *ptr; + + if (!list) + return (NULL); + if (!index) + return (insertNodeStart(list, n)); + if (index == list->size) + return (insertNodeEnd(list, n)); + if (index > list->size) + return (NULL); + + ptr = getNode(list, index); + newNode = malloc(sizeof(*newNode)); + if (!newNode) + return (NULL); + + newNode->data = n; + newNode->next = ptr; + newNode->prev = ptr->prev; + newNode->prev->next = newNode; + newNode->next->prev = newNode; + list->size++; + + return (newNode); } /** @@ -167,25 +158,24 @@ d_node *insertNode(d_list *list, unsigned int index, void *n) * * Return: 1 on success, 0 on failure */ -int deleteNodeStart(d_list *list) -{ - d_node *toRemove; - - if (!list) - return (0); - if (!list->size) - return (0); - - toRemove = list->head; - list->head = list->head->next; - freeNode(toRemove); - if (list->head) - list->head->prev = NULL; - else - list->tail = NULL; - list->size--; - - return (1); +int deleteNodeStart(d_list *list) { + d_node *toRemove; + + if (!list) + return (0); + if (!list->size) + return (0); + + toRemove = list->head; + list->head = list->head->next; + freeNode(list, toRemove); + if (list->head) + list->head->prev = NULL; + else + list->tail = NULL; + list->size--; + + return (1); } /** @@ -194,25 +184,24 @@ int deleteNodeStart(d_list *list) * * Return: 1 on success, 0 on failure */ -int deleteNodeEnd(d_list *list) -{ - d_node *toRemove; - - if (!list) - return (0); - if (!list->size) - return (0); - - toRemove = list->tail; - list->tail = list->tail->prev; - freeNode(toRemove); - if (list->tail) - list->tail->next = NULL; - else - list->head = NULL; - list->size--; - - return (1); +int deleteNodeEnd(d_list *list) { + d_node *toRemove; + + if (!list) + return (0); + if (!list->size) + return (0); + + toRemove = list->tail; + list->tail = list->tail->prev; + freeNode(list, toRemove); + if (list->tail) + list->tail->next = NULL; + else + list->head = NULL; + list->size--; + + return (1); } /** @@ -222,69 +211,65 @@ int deleteNodeEnd(d_list *list) * * Return: 1 on success, 0 on failure */ -int deleteNode(d_list *list, unsigned int index) -{ - d_node *toRemove; - - if (!list) - return (0); - if (index >= list->size) - return (0); - if (!index) - return (deleteNodeStart(list)); - if (index == list->size - 1) - return (deleteNodeEnd(list)); - - toRemove = getNode(list, index); - toRemove->prev->next = toRemove->next; - toRemove->next->prev = toRemove->prev; - freeNode(toRemove); - list->size--; - - return (-1); +int deleteNode(d_list *list, unsigned int index) { + d_node *toRemove; + + if (!list) + return (0); + if (index >= list->size) + return (0); + if (!index) + return (deleteNodeStart(list)); + if (index == list->size - 1) + return (deleteNodeEnd(list)); + + toRemove = getNode(list, index); + toRemove->prev->next = toRemove->next; + toRemove->next->prev = toRemove->prev; + freeNode(list, toRemove); + list->size--; + + return (-1); } /** * freeNode - free a node * @list: pointer to node */ -void freeNode(d_node *node) -{ - if (!node) - return; - - node->prev = node->next = NULL; - free(node->data); - free(node); +void freeNode(d_list *list, d_node *node) { + if (!node) + return; + + node->prev = node->next = NULL; + list->free_func(node->data); + node->data = NULL; } /** * freeList - frees all nodes in a d_list * @list: pointer to list */ -void freeList(d_list *list) -{ - d_node *ptr, *prv; - - if (!list) - return; - - ptr = prv = list->head; - while (ptr) - { - ptr = ptr->next; - freeNode(prv); - prv = ptr; - } - list->head = list->tail = NULL; - list->size = 0; +void freeList(d_list *list) { + d_node *ptr, *prv; + + if (!list) + return; + + ptr = prv = list->head; + while (ptr) { + ptr = ptr->next; + freeNode(list, prv); + prv = ptr; + } + list->head = list->tail = NULL; + list->size = 0; } /** * destroyList - destroy a list with all nodes * @list: pointer to list */ -void destroyList(d_list *list) -{ - freeList(list); - free(list); +void destroyList(d_list **list) { + freeList(*list); + free(*list); + *list = NULL; } diff --git a/code/list.h b/code/list.h index 5dd733f..32625cb 100644 --- a/code/list.h +++ b/code/list.h @@ -14,11 +14,10 @@ * * Description: doubly linked list node structure */ -typedef struct d_node -{ - void *data; - struct d_node *prev; - struct d_node *next; +typedef struct d_node { + void *data; + struct d_node *prev; + struct d_node *next; } d_node; /** @@ -29,14 +28,14 @@ typedef struct d_node * * Description: doubly linked list structure */ -typedef struct d_list -{ - size_t size; - d_node *head; - d_node *tail; +typedef struct d_list { + size_t size; + void (*free_func)(void *); + d_node *head; + d_node *tail; } d_list; -d_list *createList(); +d_list *createList(void (*free_func)(void *)); d_node *getNode(d_list *list, unsigned int index); d_node *insertNodeStart(d_list *list, void *n); d_node *insertNodeEnd(d_list *list, void *n); @@ -44,8 +43,8 @@ d_node *insertNode(d_list *list, unsigned int index, void *n); int deleteNodeStart(d_list *list); int deleteNodeEnd(d_list *list); int deleteNode(d_list *list, unsigned int index); -void freeNode(d_node *node); +void freeNode(d_list *list, d_node *node); void freeList(d_list *list); -void destroyList(d_list *list); +void destroyList(d_list **list); #endif diff --git a/code/queue.c b/code/queue.c index f26c067..c3ef7d3 100644 --- a/code/queue.c +++ b/code/queue.c @@ -7,63 +7,56 @@ * * return a pointer to the queue, NULL on failure */ -queue *createQueue() -{ - queue *newQueue = malloc(sizeof(*newQueue)); +queue *createQueue(void (*free_func)(void *)) { + queue *newQueue = malloc(sizeof(*newQueue)); - if (!newQueue) - return NULL; + if (!newQueue) + return NULL; - newQueue->list = createList(); + newQueue->list = createList(free_func); - if (!newQueue->list) - return NULL; + if (!newQueue->list) + return NULL; - return newQueue; + return newQueue; } /** * return 1 if the queue is empty or not created, 0 otherwise -*/ -int empty(queue *q) -{ - if (!q) - return 1; //! may need to change this + */ +int empty(queue *q) { + if (!q) + return 1; //! may need to change this - return (q->list->size == 0); + return (q->list->size == 0); } /** * get number of elements in queue -*/ -size_t size(queue *q) -{ - return q->list->size; -} + */ +size_t size(queue *q) { return q->list->size; } /** * add an item to the end of the queue * @q: pointer to queue * @item: element to add (pointer) */ -void push(queue *q, void *item) -{ - if (!q) - return; +void push(queue *q, void *item) { + if (!q) + return; - insertNodeEnd(q->list, item); + insertNodeEnd(q->list, item); } /** * remove the first element from the queue * @q: pointer to queue */ -void pop(queue *q) -{ - if (empty(q)) - return; - - deleteNodeStart(q->list); +void pop(queue *q) { + if (empty(q)) + return; + + deleteNodeStart(q->list); } /** @@ -71,14 +64,13 @@ void pop(queue *q) * without removing it, * NULL if empty * @q: pointer to queue -*/ -void *front(queue *q) -{ - if (empty(q)) - return NULL; - - d_node *n = getNode(q->list, 0); - return n->data; + */ +void *front(queue *q) { + if (empty(q)) + return NULL; + + d_node *n = getNode(q->list, 0); + return n->data; } /** @@ -86,22 +78,20 @@ void *front(queue *q) * without removing it * NULL if empty * @q: pointer to queue -*/ -void *back(queue *q) -{ - if (empty(q)) - return NULL; - - d_node *n = getNode(q->list, q->list->size - 1); - return n->data; + */ +void *back(queue *q) { + if (empty(q)) + return NULL; + + d_node *n = getNode(q->list, q->list->size - 1); + return n->data; } /** * clear all and free memory * @q: pointer to queue -*/ -void destroyQueue(queue * q) -{ - destroyList(q->list); - free(q); -} \ No newline at end of file + */ +void destroyQueue(queue *q) { + destroyList(&q->list); + free(q); +} diff --git a/code/queue.h b/code/queue.h index 55518dd..21d3f16 100644 --- a/code/queue.h +++ b/code/queue.h @@ -1,14 +1,13 @@ #pragma once -#include #include "list.h" +#include -typedef struct queue -{ - d_list *list; +typedef struct queue { + d_list *list; } queue; -queue *createQueue(); +queue *createQueue(void (*free_func)(void *)); int empty(queue *q); size_t size(queue *q); void push(queue *q, void *item); From c6058e21f154f701c9c008e3b059e8d81cad412e Mon Sep 17 00:00:00 2001 From: AhmedHamed3699 Date: Sun, 14 Apr 2024 01:36:12 +0200 Subject: [PATCH 2/3] feat(scheduler): Main setup for scheduler --- code/Makefile | 6 +- code/headers.h | 28 +++++-- code/keyfiles/SCH_GEN_COM | 0 code/process.c | 10 ++- code/process_generator.c | 68 +++++++++------ code/scheduler.c | 171 ++++++++++++++++++++++++++++++++++---- code/structs.h | 20 ++++- 7 files changed, 253 insertions(+), 50 deletions(-) create mode 100644 code/keyfiles/SCH_GEN_COM diff --git a/code/Makefile b/code/Makefile index 51c2bb9..f518067 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1,8 +1,10 @@ +.PHONY: build all clean test + build: gcc list.c queue.c process_generator.c -o process_generator.out gcc clk.c -o clk.out - gcc scheduler.c -o scheduler.out - gcc process.c -o process.out + gcc list.c scheduler.c -o scheduler.out + gcc list.c process.c -o process.out gcc test_generator.c -o test_generator.out clean: diff --git a/code/headers.h b/code/headers.h index 63ca5a0..2e26426 100644 --- a/code/headers.h +++ b/code/headers.h @@ -1,3 +1,4 @@ +#include #include #include #include //if you don't use scanf/printf change this include @@ -37,6 +38,9 @@ #define true 1 #define false 0 +// key proj_ids +#define SCH_GEN_COM 5 + #define SHKEY 300 ///============================== @@ -51,10 +55,9 @@ int *shmaddr; // queue *readInputFile(); void printBanner(); -enum scheduler_type getSchedulerType(); -void getInput(enum scheduler_type *, int *); -void clearResources(int); -void createSchedulerAndClock(pid_t *, pid_t *); +scheduler_type getSchedulerType(); +void getInput(scheduler_type *, int *); +void createSchedulerAndClock(pid_t *, pid_t *, int); void sendProcessesToScheduler(queue *, int); int intiSchGenCom(); @@ -85,10 +88,25 @@ void initClk() { * Input: terminateAll: a flag to indicate whether that this is the end of * simulation. It terminates the whole system and releases resources. */ - void destroyClk(bool terminateAll) { shmdt(shmaddr); if (terminateAll) { killpg(getpgrp(), SIGINT); } } + +void cleanUp() { + destroyClk(true); + killpg(getpgrp(), SIGINT); +} + +/** + * clearResources - Clears all resources in case of interruption. + * + * @signum: the signal number + */ +void clearResources(int signum) { + // TODO: Clears all resources in case of interruption + cleanUp(); + exit(0); +} diff --git a/code/keyfiles/SCH_GEN_COM b/code/keyfiles/SCH_GEN_COM new file mode 100644 index 0000000..e69de29 diff --git a/code/process.c b/code/process.c index 9a4fc6a..5685b06 100644 --- a/code/process.c +++ b/code/process.c @@ -1,9 +1,17 @@ #include "headers.h" /* Modify this file as needed*/ -int remainingtime; +int remainingtime = 1; int main(int agrc, char *argv[]) { + + signal(SIGINT, clearResources); + signal(SIGTERM, clearResources); + if (atexit(cleanUp) != 0) { + perror("atexit"); + exit(1); + } + initClk(); // TODO it needs to get the remaining time from somewhere diff --git a/code/process_generator.c b/code/process_generator.c index 74ca3b7..ba8402d 100644 --- a/code/process_generator.c +++ b/code/process_generator.c @@ -19,12 +19,17 @@ */ int main(int argc, char *argv[]) { queue *processes; - enum scheduler_type schedulerType; + scheduler_type schedulerType; int quantum; pid_t schedulerPid, clockPid; int msgQID; signal(SIGINT, clearResources); + signal(SIGTERM, clearResources); + if (atexit(cleanUp) != 0) { + perror("atexit"); + exit(1); + } printBanner(); @@ -33,14 +38,18 @@ int main(int argc, char *argv[]) { getInput(&schedulerType, &quantum); - createSchedulerAndClock(&schedulerPid, &clockPid); + createSchedulerAndClock(&schedulerPid, &clockPid, (int)schedulerType); initClk(); msgQID = intiSchGenCom(); sendProcessesToScheduler(processes, msgQID); - destroyQueue(processes); + + if (wait(NULL) == -1) { + perror("wait"); + exit(1); + } destroyClk(true); } @@ -54,7 +63,7 @@ queue *readInputFile() { FILE *file; char *line = NULL; size_t len = 0; - queue *processes = createQueue(); + queue *processes = createQueue(free); printf(ANSI_YELLOW "============================" ANSI_RESET "\n"); printf(ANSI_YELLOW "|| Reading processes file ||" ANSI_RESET "\n"); @@ -97,7 +106,7 @@ queue *readInputFile() { * * return: the chosen scheduler type */ -enum scheduler_type getSchedulerType() { +scheduler_type getSchedulerType() { int choice; printf(ANSI_TEAL "===========================================================" @@ -123,7 +132,7 @@ enum scheduler_type getSchedulerType() { case 3: return RR; default: - return -1; + exit(-1); } } @@ -134,7 +143,7 @@ enum scheduler_type getSchedulerType() { * @schedulerType: a pointer to the chosen scheduler type * @quantum: a pointer to the quantum value */ -void getInput(enum scheduler_type *schedulerType, int *quantum) { +void getInput(scheduler_type *schedulerType, int *quantum) { *schedulerType = getSchedulerType(); if (*schedulerType == -1) { @@ -214,7 +223,8 @@ void printBanner() { * @schedulerPid: a pointer to the scheduler process id * @clockPid: a pointer to the clock process id */ -void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid) { +void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid, + int schedulerType) { *clockPid = fork(); @@ -237,7 +247,23 @@ void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid) { } if (*schedulerPid == 0) { - char *args[] = {"./scheduler.out", NULL}; + char *type; + + switch (schedulerType) { + case 0: + type = "0"; + break; + case 1: + type = "1"; + break; + case 2: + type = "2"; + break; + default: + exit(-1); + } + + char *args[] = {"./scheduler.out", type, NULL}; execvp(args[0], args); exit(0); } @@ -247,18 +273,6 @@ void createSchedulerAndClock(pid_t *schedulerPid, pid_t *clockPid) { printf(ANSI_PURPLE "|| ==> Clock PID: %d\n" ANSI_RESET, *clockPid); } -/** - * clearResources - Clears all resources in case of interruption. - * - * @signum: the signal number - */ -void clearResources(int signum) { - // TODO: Clears all resources in case of interruption - destroyClk(true); - killpg(getpgrp(), SIGINT); - exit(0); -} - /** * sendProcessesToScheduler - Sends the processes to the scheduler at the * appropriate time. @@ -293,14 +307,20 @@ void sendProcessesToScheduler(queue *processes, int msgQID) { response = msgsnd(msgQID, process, sizeof(process_t), !IPC_NOWAIT); if (response == -1) { - fprintf(stderr, - ANSI_RED "==>Error in sending process to scheduler\n" ANSI_RESET); + perror("Error in sending process to scheduler\n"); exit(-1); } pop(processes); lastTime = currentTime; } + + process->id = -1; + response = msgsnd(msgQID, process, sizeof(process_t), !IPC_NOWAIT); + if (response == -1) { + perror("Error in terminating sending processes to scheduler\n"); + exit(-1); + } } /** @@ -310,7 +330,7 @@ void sendProcessesToScheduler(queue *processes, int msgQID) { * return: the message queue id */ int intiSchGenCom() { - int key = ftok("SCH_GEN_COM", 18); + int key = ftok("keyfiles/SCH_GEN_COM", SCH_GEN_COM); int msgQID = msgget(key, 0666 | IPC_CREAT); if (msgQID == -1) { diff --git a/code/scheduler.c b/code/scheduler.c index 3108180..7b2e23e 100644 --- a/code/scheduler.c +++ b/code/scheduler.c @@ -1,35 +1,172 @@ #include "headers.h" +#include "list.h" + +int msgQID; +d_list *p_table = NULL; + +void cleanUpScheduler() { + msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); + destroyClk(true); + if (p_table) + destroyList(&p_table); + killpg(getpgrp(), SIGINT); +} + +/** + * clearResources - Clears all resources in case of interruption. + * + * @signum: the signal number + */ +void clearSchResources(int signum) { + cleanUpScheduler(); + exit(0); +} + +scheduler_type getScType(int schedulerType) { + switch (schedulerType) { + case 0: + return HPF; + case 1: + return SRTN; + case 2: + return RR; + default: + exit(-1); + } +} + +void freeProcessEntry(void *processEntry) { + if (processEntry) + free(((process_entry_t *)processEntry)->PCB); + free(processEntry); +} + +void createProcess(d_list *processTable, process_t *process) { + pid_t pid; + process_entry_t *processEntry; + PCB_t *pcb; + + pid = fork(); + + if (pid == -1) { + perror("fork"); + exit(-1); + } + + if (pid == 0) { + char *args[] = {"./process.out", NULL}; + execvp(args[0], args); + exit(0); + } + + processEntry = malloc(sizeof(*processEntry)); + if (!processEntry) { + perror("malloc"); + exit(-1); + } + + pcb = malloc(sizeof(*pcb)); + if (!pcb) { + perror("malloc"); + exit(-1); + } + + pcb->state = READY; + pcb->process = *process; + processEntry->p_id = pid; + processEntry->PCB = pcb; + if (!insertNodeEnd(processTable, processEntry)) { + perror("insertNodeEnd"); + exit(-1); + } + + printf(ANSI_GREEN "==>SCH: Added process to processes table\n" ANSI_RESET); +} int main(int argc, char *argv[]) { - initClk(); + int key, gen_msgQID, response; + scheduler_type schedulerType; + process_t tmpProcess; + d_list *processTable = NULL; - // TODO implement the scheduler :) - // upon termination release the clock resources. + signal(SIGINT, clearSchResources); + signal(SIGTERM, clearSchResources); + if (atexit(cleanUpScheduler) != 0) { + perror("atexit"); + exit(1); + } - // init msgs queue with process generator + initClk(); - while (1) { - // TODO: change this later just for testing - int key = ftok("SCH_GEN_COM", 18); - int msgQID = msgget(key, 0666 | IPC_CREAT); + schedulerType = getScType(atoi(argv[1])); + printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, + (int)schedulerType); - if (msgQID == -1) { - perror("Error in creating message queue"); - exit(-1); - } + p_table = processTable = createList(freeProcessEntry); + if (!processTable) { + perror("Error while creating process table"); + exit(-1); + } - process_t process; + key = ftok("keyfiles/SCH_GEN_COM", SCH_GEN_COM); + msgQID = gen_msgQID = + msgget(key, 0666 | IPC_CREAT); // COM with process_generator - // FIXME: doesn't seem to be recieving the process check later - int response = msgrcv(msgQID, &process, sizeof(process_t), 0, !IPC_NOWAIT); + if (gen_msgQID == -1) { + perror("Error in creating message queue"); + exit(-1); + } + + while (1) { + response = + msgrcv(gen_msgQID, &tmpProcess, sizeof(process_t), 0, !IPC_NOWAIT); if (response == -1) { perror("Error in receiving process from process generator"); exit(-1); - } else { - printf(ANSI_BLUE "==>SCH: Received process" ANSI_RESET); } + + if (tmpProcess.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, + tmpProcess.id); + createProcess(processTable, &tmpProcess); } + msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); + + // TODO Initialize Scheduler + // Create Ready queue & (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) + // + // TODO Clean everything when Scheduler finishes or if it is killed + // Calculate all needed stats + // create pref file + // kill all living processes and destroy its PCB (is this right?) + // destroy process table + // destroy clk + // Any other clean up + destroyClk(true); } diff --git a/code/structs.h b/code/structs.h index 61f0357..4cd5cb0 100644 --- a/code/structs.h +++ b/code/structs.h @@ -1,5 +1,10 @@ // copyright 2024: Abderlrahman Samy - George Magdy - Ahmed Hamed - Amir Anwar +#include +typedef enum scheduler_type { HPF, SRTN, RR } scheduler_type; + +typedef enum process_state { READY, RUNNING, BLOCKED } process_state; + typedef struct process { int id; // unique identifier int AT; // arrival time @@ -8,4 +13,17 @@ typedef struct process { // TODO: add more attributes here when needed } process_t; -enum scheduler_type { HPF, SRTN, RR }; +typedef struct PCB { + process_state state; + process_t process; +} PCB_t; + +typedef struct process_entry { + int p_id; + PCB_t *PCB; +} process_entry_t; + +typedef struct cleanup_data { + int msgQID; + void *processTable; +} cleanup_data_t; From 82d9a9622b83c6f527819492bddf94439e5e7a4b Mon Sep 17 00:00:00 2001 From: AhmedHamed3699 Date: Sun, 14 Apr 2024 02:27:47 +0200 Subject: [PATCH 3/3] refactor: organize functions and header files --- code/clk.c | 4 +- code/headers.h | 52 +++++---- code/list.h | 5 +- code/process_generator.c | 24 +--- code/process_generator.h | 16 +++ code/scheduler.c | 231 ++++++++++++++++++++++----------------- code/scheduler.h | 11 ++ code/structs.h | 2 +- 8 files changed, 196 insertions(+), 149 deletions(-) create mode 100644 code/process_generator.h create mode 100644 code/scheduler.h diff --git a/code/clk.c b/code/clk.c index d8443eb..2483967 100644 --- a/code/clk.c +++ b/code/clk.c @@ -10,7 +10,7 @@ int shmid; /* Clear the resources before exit */ -void cleanup(int signum) { +void cleanUpClk(int signum) { shmctl(shmid, IPC_RMID, NULL); printf("Clock terminating!\n"); exit(0); @@ -19,7 +19,7 @@ void cleanup(int signum) { /* This file represents the system clock for ease of calculations */ int main(int argc, char *argv[]) { printf("Clock starting\n"); - signal(SIGINT, cleanup); + signal(SIGINT, cleanUpClk); int clk = 0; // Create shared memory for one integer variable 4 bytes shmid = shmget(SHKEY, 4, IPC_CREAT | 0644); diff --git a/code/headers.h b/code/headers.h index 2e26426..f5ab7d9 100644 --- a/code/headers.h +++ b/code/headers.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -12,11 +14,6 @@ #include #include #include -///============================== -// CUSTOM INCLUDES -//=============================== -#include "./queue.h" -#include "./structs.h" //=============================== // CONSTANTS @@ -38,31 +35,15 @@ #define true 1 #define false 0 -// key proj_ids #define SCH_GEN_COM 5 #define SHKEY 300 ///============================== // don't mess with this variable// -int *shmaddr; // +int *shmaddr; //=============================== -// =================================== -// ====== PROCESS GENERATOR ====== -// ====== FUNCTION DECLARATIONS ====== -// =================================== - -queue *readInputFile(); -void printBanner(); -scheduler_type getSchedulerType(); -void getInput(scheduler_type *, int *); -void createSchedulerAndClock(pid_t *, pid_t *, int); -void sendProcessesToScheduler(queue *, int); -int intiSchGenCom(); - -// =================================== - int getClk() { return *shmaddr; } /* @@ -95,7 +76,15 @@ void destroyClk(bool terminateAll) { } } +//=============================== +// CUSTOM COMMON FUNCTIONS +//=============================== + +/** + * cleanUp - Make necessary cleaning + */ void cleanUp() { + // TODO any other needed clean up destroyClk(true); killpg(getpgrp(), SIGINT); } @@ -106,7 +95,24 @@ void cleanUp() { * @signum: the signal number */ void clearResources(int signum) { - // TODO: Clears all resources in case of interruption cleanUp(); exit(0); } + +/** + * intiSchGenCom - Initializes the message queue between the scheduler and the + * process generator. + * + * return: the message queue id + */ +int initSchGenCom() { + int key = ftok("keyfiles/SCH_GEN_COM", SCH_GEN_COM); + int msgQID = msgget(key, 0666 | IPC_CREAT); + + if (msgQID == -1) { + perror("Error in creating message queue"); + exit(-1); + } + + return msgQID; +} diff --git a/code/list.h b/code/list.h index 32625cb..c096083 100644 --- a/code/list.h +++ b/code/list.h @@ -1,5 +1,4 @@ -#ifndef LIST -#define LIST +#pragma once #include @@ -46,5 +45,3 @@ int deleteNode(d_list *list, unsigned int index); void freeNode(d_list *list, d_node *node); void freeList(d_list *list); void destroyList(d_list **list); - -#endif diff --git a/code/process_generator.c b/code/process_generator.c index ba8402d..5b094ac 100644 --- a/code/process_generator.c +++ b/code/process_generator.c @@ -7,8 +7,8 @@ * ==================================================================== */ -#include "./headers.h" -#include "queue.h" +#include "process_generator.h" +#include "headers.h" /** * main - The main function of the process generator. @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { createSchedulerAndClock(&schedulerPid, &clockPid, (int)schedulerType); initClk(); - msgQID = intiSchGenCom(); + msgQID = initSchGenCom(); sendProcessesToScheduler(processes, msgQID); destroyQueue(processes); @@ -322,21 +322,3 @@ void sendProcessesToScheduler(queue *processes, int msgQID) { exit(-1); } } - -/** - * intiSchGenCom - Initializes the message queue between the scheduler and the - * process generator. - * - * return: the message queue id - */ -int intiSchGenCom() { - int key = ftok("keyfiles/SCH_GEN_COM", SCH_GEN_COM); - int msgQID = msgget(key, 0666 | IPC_CREAT); - - if (msgQID == -1) { - perror("Error in creating message queue"); - exit(-1); - } - - return msgQID; -} diff --git a/code/process_generator.h b/code/process_generator.h new file mode 100644 index 0000000..9551f27 --- /dev/null +++ b/code/process_generator.h @@ -0,0 +1,16 @@ +#pragma once + +#include "queue.h" +#include "structs.h" + +// =================================== +// ====== PROCESS GENERATOR ====== +// ====== FUNCTION DECLARATIONS ====== +// =================================== +// +queue *readInputFile(); +void printBanner(); +scheduler_type getSchedulerType(); +void getInput(scheduler_type *, int *); +void createSchedulerAndClock(pid_t *, pid_t *, int); +void sendProcessesToScheduler(queue *, int); diff --git a/code/scheduler.c b/code/scheduler.c index 7b2e23e..cfcf21d 100644 --- a/code/scheduler.c +++ b/code/scheduler.c @@ -1,27 +1,90 @@ +/* ==================================================================== + * scheduler.c + * + * scheduler is responsible for creating and managing processes + * according to a specific algorithm + * ==================================================================== + */ + +#include "scheduler.h" #include "headers.h" -#include "list.h" int msgQID; d_list *p_table = NULL; -void cleanUpScheduler() { - msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); - destroyClk(true); - if (p_table) - destroyList(&p_table); - killpg(getpgrp(), SIGINT); -} - /** - * clearResources - Clears all resources in case of interruption. + * main - The main function of the scheduler. * - * @signum: the signal number + * @argc: the number of arguments + * @argv: the arguments + * return: 0 on success, -1 on failure */ -void clearSchResources(int signum) { - cleanUpScheduler(); - exit(0); +int main(int argc, char *argv[]) { + int key, gen_msgQID, response; + scheduler_type schedulerType; + d_list *processTable = NULL; + + signal(SIGINT, clearSchResources); + signal(SIGTERM, clearSchResources); + if (atexit(cleanUpScheduler) != 0) { + perror("atexit"); + exit(1); + } + + initClk(); + + schedulerType = getScType(atoi(argv[1])); + printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, + (int)schedulerType); + + p_table = processTable = createList(freeProcessEntry); + if (!processTable) { + perror("Error while creating process table"); + exit(-1); + } + + msgQID = gen_msgQID = initSchGenCom(); + + getProcesses(gen_msgQID, processTable); + + // TODO Initialize Scheduler + // Create Ready queue & (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) + // + // TODO Clean everything when Scheduler finishes or if it is killed + // Calculate all needed stats + // create pref file + // kill all living processes and destroy its PCB (is this right?) + // destroy process table + // destroy clk + // Any other clean up } +/** + * getScType - gets scheduler type + * + * @schedulerType: scheduler type + * return: scheduler type enum + */ scheduler_type getScType(int schedulerType) { switch (schedulerType) { case 0: @@ -35,12 +98,51 @@ scheduler_type getScType(int schedulerType) { } } +/** + * 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); + } +} + +/** + * freeProcessEntry - process entry free function + * + * @processEntry: process entry + */ void freeProcessEntry(void *processEntry) { if (processEntry) free(((process_entry_t *)processEntry)->PCB); free(processEntry); } +/** + * createProcess - create a new process and add it to process table + * + * @processTable: pointer to process table + * @process: pointer to new process info + */ void createProcess(d_list *processTable, process_t *process) { pid_t pid; process_entry_t *processEntry; @@ -83,90 +185,23 @@ void createProcess(d_list *processTable, process_t *process) { printf(ANSI_GREEN "==>SCH: Added process to processes table\n" ANSI_RESET); } -int main(int argc, char *argv[]) { - int key, gen_msgQID, response; - scheduler_type schedulerType; - process_t tmpProcess; - d_list *processTable = NULL; - - signal(SIGINT, clearSchResources); - signal(SIGTERM, clearSchResources); - if (atexit(cleanUpScheduler) != 0) { - perror("atexit"); - exit(1); - } - - initClk(); - - schedulerType = getScType(atoi(argv[1])); - printf(ANSI_YELLOW "==>SCH: My Scheduler Type is %i\n" ANSI_RESET, - (int)schedulerType); - - p_table = processTable = createList(freeProcessEntry); - if (!processTable) { - perror("Error while creating process table"); - exit(-1); - } - - key = ftok("keyfiles/SCH_GEN_COM", SCH_GEN_COM); - msgQID = gen_msgQID = - msgget(key, 0666 | IPC_CREAT); // COM with process_generator - - if (gen_msgQID == -1) { - perror("Error in creating message queue"); - exit(-1); - } - - while (1) { - response = - msgrcv(gen_msgQID, &tmpProcess, sizeof(process_t), 0, !IPC_NOWAIT); - - if (response == -1) { - perror("Error in receiving process from process generator"); - exit(-1); - } - - if (tmpProcess.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, - tmpProcess.id); - createProcess(processTable, &tmpProcess); - } - +/** + * cleanUpScheduler - Make necessary cleaning + */ +void cleanUpScheduler() { msgctl(msgQID, IPC_RMID, (struct msqid_ds *)0); - - // TODO Initialize Scheduler - // Create Ready queue & (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) - // - // TODO Clean everything when Scheduler finishes or if it is killed - // Calculate all needed stats - // create pref file - // kill all living processes and destroy its PCB (is this right?) - // destroy process table - // destroy clk - // Any other clean up - 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 new file mode 100644 index 0000000..285fbb5 --- /dev/null +++ b/code/scheduler.h @@ -0,0 +1,11 @@ +#pragma once + +#include "list.h" +#include "structs.h" + +scheduler_type getScType(int schedulerType); +void getProcesses(int gen_msgQID, d_list *processTable); +void freeProcessEntry(void *processEntry); +void createProcess(d_list *processTable, process_t *process); +void cleanUpScheduler(); +void clearSchResources(int signum); diff --git a/code/structs.h b/code/structs.h index 4cd5cb0..c10517c 100644 --- a/code/structs.h +++ b/code/structs.h @@ -1,6 +1,6 @@ // copyright 2024: Abderlrahman Samy - George Magdy - Ahmed Hamed - Amir Anwar +#pragma once -#include typedef enum scheduler_type { HPF, SRTN, RR } scheduler_type; typedef enum process_state { READY, RUNNING, BLOCKED } process_state;