From 72ab0d8fe93665b1f1fc831d656bb1282f94f7df Mon Sep 17 00:00:00 2001 From: Isaac Shoebottom Date: Fri, 27 Oct 2023 12:23:06 -0300 Subject: [PATCH] Work on A5 --- Assignment5/hard_affinity.c | 120 +++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 36 deletions(-) diff --git a/Assignment5/hard_affinity.c b/Assignment5/hard_affinity.c index 5f817c0..ce54943 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -1,10 +1,35 @@ #include #include +#include +#include #include "lib/queue.h" +// TODO: Look into semaphore increment too much in print function, look into synchronization + + #define MAX_USERNAME_LENGTH 100 int QUANTUM; int CPUS; +int TIME = 0; + +// Semaphore for the print function +sem_t print_semaphore; + +typedef struct ThreadArgs { + int cpu_id; + char *print_buffer; + Queue *summary_queue; + Queue *in_queue; +} ThreadArgs; + +ThreadArgs *createArgs(int cpu_id, char* print_buffer, Queue *summary_queue, Queue *in_queue) { + ThreadArgs *args = malloc(sizeof(ThreadArgs)); + args->cpu_id = cpu_id; + args->print_buffer = print_buffer; + args->summary_queue = summary_queue; + args->in_queue = in_queue; + return args; +} Queue *input_queue() { Queue *queue = createQueue(); @@ -18,6 +43,9 @@ Queue *input_queue() { scanf("%d", &CPUS); while (getchar() != '\n'); // clear the newline from the buffer + // Make sure sem is init right after getting cpus + sem_init(&print_semaphore, 0, CPUS); // Initialize the semaphore + while (getchar() != '\n'); // ignore the rest of the line, this is the table line // Loop through the process table and enqueue each process while (scanf("%99s %c %d %d %d", username, &job, &arrival_time, &duration, &affinity) != EOF) { @@ -27,9 +55,12 @@ Queue *input_queue() { return queue; } -void* print(void *print_queue_void) { - // Cast the input queue to a Queue pointer - Queue *print_queue = (Queue*) print_queue_void; +void* print(void *args) { + // Cast args and create local variables + ThreadArgs *thread_args = (ThreadArgs*) args; + char *print_buffer = thread_args->print_buffer; + Queue *summary_queue = thread_args->summary_queue; + Queue *in_queue = thread_args->in_queue; // Print the Time label as well as the CPU labels printf("Time"); @@ -37,43 +68,48 @@ void* print(void *print_queue_void) { printf("\tCPU%d", i); } printf("\n"); - + for (int i = 0; i < in_queue->size; ++i) { + TIME++; + // Allow the simulation to begin + sem_post(&print_semaphore); + for (int j = 0; j < CPUS; ++j) { + printf("%d\t%c", TIME, print_buffer[i]); + } + printf("\n"); + } + // Print the summary + printf("\nSummary\n"); + printList(summary_queue); + + return NULL; } -void* simulation(void *in_queue_void) { - // Cast the input queue to a Queue pointer - Queue *in_queue = (Queue*) in_queue_void; +void* simulation(void *args) { + // Cast args and create local variables + ThreadArgs *thread_args = (ThreadArgs*) args; + Queue *in_queue = thread_args->in_queue; + Queue *summary_queue = thread_args->summary_queue; + char *print_buffer = thread_args->print_buffer; + int cpu_id = thread_args->cpu_id; - // Summary creation - Process *process = in_queue->end; - Queue *summary_queue = createQueue(); - for (int i = 0; i < in_queue->size; ++i) { - if (contains(summary_queue, process->username) == false) { - Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity); - enqueue(summary_queue, copy); - } - process = process->prev_elem; - } // Loop variables int quantum = QUANTUM; int addedJobs = 0; - int time = 0; + Process *process = NULL; // Create a queue for the simulation Queue *sim_queue = createQueue(); - - printf("Time\tJob\n"); while (true) { - time++; + sem_wait(&print_semaphore); // Wait for the print semaphore // Begin going through all jobs and enqueueing them if they have arrived process = in_queue->end; for (int i = 0; i < in_queue->size; i++) { - if (process->arrival_time == time) { + if (process->affinity == cpu_id && process->arrival_time == TIME) { // Create copy to keep the queues separate Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity); enqueue(sim_queue, copy); @@ -84,18 +120,18 @@ void* simulation(void *in_queue_void) { // Begin printing the current job process = sim_queue->end; - if (sim_queue->size == 0) { //If there is nothing in sim_queue, print "-" - printf("%d\t-\n", time); + if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer + print_buffer[cpu_id] = '-'; if (addedJobs == in_queue->size) { break; // If all jobs have been added, and the simulation queue is empty, then we are done } } else { - printf("%d\t%c\n", time, process->job); // Print the current job + print_buffer[cpu_id] = process->job; process->duration--; quantum--; if (process->duration == 0) { // If the process is done, delete it Process *temp = dequeue(sim_queue); // Store the process in a temp variable for deletion - search(summary_queue, temp->username)->finish_time = time; // Set the finish time for the summary queue + search(summary_queue, temp->username)->finish_time = TIME; // Set the finish time for the summary queue destroyProcess(temp); // This should be called on every process quantum = QUANTUM; // Make sure to reset the quantum when a process is done } else if (quantum == 0) { // If the quantum is 0, then we need to dequeue the process and enqueue it again @@ -105,30 +141,39 @@ void* simulation(void *in_queue_void) { } } } - - // Print the summary - printf("\nSummary\n"); - printList(summary_queue); - // Free memory for the simulation queue. There should be nothing left in it stop(sim_queue); - // We never dequeue from the summary queue, so we don't need to make sure about freeing dequeued processes - stop(summary_queue); + return NULL; } + int main() { Queue *in_queue = input_queue(); // Create the input queue - Queue *print_queue = createQueue(); // Create the print queue + Queue *summary_queue = createQueue(); // Create the summary queue + char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer + + // Summary creation + Process *process = in_queue->end; + for (int i = 0; i < in_queue->size; ++i) { + if (contains(summary_queue, process->username) == false) { + Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity); + enqueue(summary_queue, copy); + } + process = process->prev_elem; + } // Create the print thread pthread_t print_thread; - pthread_create(&print_thread, NULL, &print, print_queue); + ThreadArgs *print_args = createArgs(0, print_buffer, summary_queue, in_queue); + pthread_create(&print_thread, NULL, &print, print_args); // Create the simulation threads pthread_t threads[CPUS]; + ThreadArgs* args[CPUS]; // Array of arguments for each thread, so we can free them later for (int i = 0; i < CPUS; i++) { - pthread_create(&threads[i], NULL, &simulation, in_queue); + args[i] = createArgs(i, print_buffer, summary_queue, in_queue); + pthread_create(&threads[i], NULL, &simulation, args[i]); } // This should make sure all threads are done simulating, as the print function exits after simulation is done @@ -136,7 +181,10 @@ int main() { // Just to make sure all threads are done for (int i = 0; i < CPUS; i++) { pthread_join(threads[i], NULL); + free(args[i]); } stop(in_queue); // Free memory for input queue + stop(summary_queue); // Free memory for summary queue + free(print_buffer); // Free memory for print buffer return 0; }