From 3eaf16e12bffae9550d1b2ca59c07192f3853a79 Mon Sep 17 00:00:00 2001 From: Isaac Shoebottom Date: Thu, 2 Nov 2023 21:08:48 -0300 Subject: [PATCH] Mostly working a5 --- .../.idea/codeStyles/codeStyleConfig.xml | 5 + Assignment5/hard_affinity.c | 217 ++++++++++-------- 2 files changed, 126 insertions(+), 96 deletions(-) create mode 100644 Assignment5/.idea/codeStyles/codeStyleConfig.xml diff --git a/Assignment5/.idea/codeStyles/codeStyleConfig.xml b/Assignment5/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..df5f35d --- /dev/null +++ b/Assignment5/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/Assignment5/hard_affinity.c b/Assignment5/hard_affinity.c index 68bc3cc..9ef4c82 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -4,15 +4,8 @@ #include #include "lib/queue.h" -// TODO: Look into semaphore increment too much in print function, look into synchronization - -// TODO: Need to use semaphore for thread synchronization, and mutex for shared variables - -// Need to make sure both threads read time once, or only tick once per time increment - - #define MAX_USERNAME_LENGTH 100 -int QUANTUM; +int *QUANTUM; int CPUS; // Semaphore for the threads to simulate @@ -53,7 +46,13 @@ Queue *input_queue() { scanf("%d", &CPUS); while (getchar() != '\n'); // clear the newline from the buffer - scanf("%d", &QUANTUM); + // Allocate dynamic quantum array + QUANTUM = malloc(sizeof(int) * CPUS); + int i = 0; + while (i < CPUS) { + scanf("%d", &QUANTUM[i]); + i++; + } while (getchar() != '\n'); // clear the newline from the buffer while (getchar() != '\n'); // ignore the rest of the line, this is the table line @@ -66,15 +65,29 @@ Queue *input_queue() { } int getTime() { - pthread_mutex_lock(&time_mutex); - int time = TIME; - pthread_mutex_unlock(&time_mutex); - return time; + pthread_mutex_lock(&time_mutex); + int time = TIME; + pthread_mutex_unlock(&time_mutex); + return time; } + void incrementTime() { - pthread_mutex_lock(&time_mutex); - TIME++; - pthread_mutex_unlock(&time_mutex); + pthread_mutex_lock(&time_mutex); + TIME++; + pthread_mutex_unlock(&time_mutex); +} + +int getFinishCount() { + pthread_mutex_lock(&finish_mutex); + int count = finish_count; + pthread_mutex_unlock(&finish_mutex); + return count; +} + +void incrementFinishCount() { + pthread_mutex_lock(&finish_mutex); + finish_count++; + pthread_mutex_unlock(&finish_mutex); } void *print(void *args) { @@ -82,7 +95,6 @@ void *print(void *args) { 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"); @@ -92,28 +104,32 @@ void *print(void *args) { printf("\n"); while (true) { - sem_wait(&print_sem); - int time = getTime(); + // Wait for all the simulation threads to finish + for (int i = 0; i < CPUS - getFinishCount(); ++i) { + sem_wait(&print_sem); + } - // Print the time and the print buffer + int time = getTime(); + + // Print the time and the print buffer printf("%d", time); for (int i = 0; i < CPUS; ++i) { - printf("\t%c", print_buffer[i]); + printf("\t%c", print_buffer[i]); } - printf("\n"); + printf("\n"); - // Check if every process is done - if (finish_count == CPUS) { - break; - } + // Check if every process is done + if (getFinishCount() == CPUS) { + break; + } - incrementTime(); - - // Increment the simulation semaphore to let the simulation threads run - for (int i = 0; i < CPUS; ++i) { - sem_post(&sim_sem); - } + // Essentially increase the time right before simulating + incrementTime(); + // Increment the simulation semaphore to let the simulation threads run + for (int i = 0; i < CPUS - getFinishCount(); ++i) { + sem_post(&sim_sem); + } } // Print the summary @@ -133,73 +149,77 @@ void *simulation(void *args) { int cpu_id = thread_args->cpu_id; // Loop variables - int quantum = QUANTUM; + int quantum = QUANTUM[cpu_id]; int addedJobs = 0; - Process *process = NULL; - int numberOfJobsForThisCPU = 0; + int numberOfJobsForThisCPU = 0; - // Count number of jobs this CPU has to do - process = in_queue->end; - for (int i = 0; i < in_queue->size; ++i) { - if (process->affinity == cpu_id) { - numberOfJobsForThisCPU++; - } - process = process->prev_elem; - } + int previousTime; + Process *process = NULL; + + // Count number of jobs this CPU has to do + process = in_queue->end; + for (int i = 0; i < in_queue->size; ++i) { + if (process->affinity == cpu_id) { + numberOfJobsForThisCPU++; + } + process = process->prev_elem; + } + + int time = 0; // Create a queue for the simulation Queue *sim_queue = createQueue(); while (true) { - sem_wait(&sim_sem); - int time = getTime(); - - // 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->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); - addedJobs++; + // Only simulate if the time has changed + previousTime = time; + time = getTime(); + if (previousTime != time) { + sem_wait(&sim_sem); + // 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->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); + addedJobs++; + } + process = process->prev_elem; } - process = process->prev_elem; + + // Begin printing the current job + process = sim_queue->end; + if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer + print_buffer[cpu_id] = '-'; + if (addedJobs >= numberOfJobsForThisCPU) { + break; // If all jobs have been added, and the simulation queue is empty, then we are done + } + } else { + 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 + destroyProcess(temp); // This should be called on every process + quantum = QUANTUM[cpu_id]; // 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 + process = dequeue(sim_queue); + enqueue(sim_queue, process); + quantum = QUANTUM[cpu_id]; + } + } + // Allow the print thread to print because the simulation for this tick is done + sem_post(&print_sem); } - - // Begin printing the current job - process = sim_queue->end; - if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer - print_buffer[cpu_id] = '-'; - if (addedJobs >= numberOfJobsForThisCPU) { - - break; // If all jobs have been added, and the simulation queue is empty, then we are done - } - } else { - 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 - 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 - process = dequeue(sim_queue); - enqueue(sim_queue, process); - quantum = QUANTUM; - } - } - // Allow the print thread to print - sem_post(&print_sem); } // Free memory for the simulation queue. There should be nothing left in it stop(sim_queue); // Signal that the thread is done - pthread_mutex_lock(&finish_mutex); - finish_count++; - pthread_mutex_unlock(&finish_mutex); - // Allow the print thread to print one last time - sem_post(&print_sem); + incrementFinishCount(); + // Allow the print thread to print one last time + sem_post(&print_sem); return NULL; } @@ -210,9 +230,9 @@ int main() { // Make sure sem is init right after getting cpus, which is done in input_queue sem_init(&print_sem, 0, 0); // Initialize the semaphore - sem_init(&sim_sem, 0, CPUS); // Initialize the semaphore + sem_init(&sim_sem, 0, CPUS); // Initialize the semaphore pthread_mutex_init(&finish_mutex, NULL); // Initialize the mutex - pthread_mutex_init(&time_mutex, NULL); // Initialize the mutex + pthread_mutex_init(&time_mutex, NULL); // Initialize the mutex Queue *summary_queue = createQueue(); // Create the summary queue char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer @@ -227,11 +247,6 @@ int main() { process = process->prev_elem; } - // Create the print thread - pthread_t print_thread; - 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 @@ -240,15 +255,25 @@ int main() { 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 - pthread_join(print_thread, NULL); - // Just to make sure all threads are done + + // Create the print thread + pthread_t print_thread; + ThreadArgs *print_args = createArgs(0, print_buffer, summary_queue, in_queue); + pthread_create(&print_thread, NULL, &print, print_args); + + + + // Threads simulate, then print for (int i = 0; i < CPUS; i++) { pthread_join(threads[i], NULL); free(args[i]); } + pthread_join(print_thread, NULL); + free(print_args); + stop(in_queue); // Free memory for input queue stop(summary_queue); // Free memory for summary queue free(print_buffer); // Free memory for print buffer + free(QUANTUM); // Free memory for quantum array return 0; }