From 64d3af7762749a9d5dc9e873dfb1498ef6d239c6 Mon Sep 17 00:00:00 2001 From: Isaac Shoebottom Date: Thu, 2 Nov 2023 18:20:54 -0300 Subject: [PATCH] Add working? solution --- .../documentation/a5_sample_input_1.txt | 8 +- Assignment5/hard_affinity.c | 104 ++++++++++-------- 2 files changed, 63 insertions(+), 49 deletions(-) diff --git a/Assignment5/documentation/a5_sample_input_1.txt b/Assignment5/documentation/a5_sample_input_1.txt index 10aab23..0601f6b 100644 --- a/Assignment5/documentation/a5_sample_input_1.txt +++ b/Assignment5/documentation/a5_sample_input_1.txt @@ -1,7 +1,7 @@ 1 3 User Process Arrival Duration Affinity -Jim A 2 5 0 -Mary B 2 2 0 -Sue C 5 5 0 -Mary D 6 2 0 +Jim A 2 5 0 +Mary B 2 2 0 +Sue C 5 5 0 +Mary D 6 2 0 diff --git a/Assignment5/hard_affinity.c b/Assignment5/hard_affinity.c index f137be9..68bc3cc 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -8,25 +8,26 @@ // 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 CPUS; -int TIME = 0; // Semaphore for the threads to simulate -sem_t sim_sem; - -// Semaphore for the thread to control printing sem_t print_sem; -// Mutex for simulation -pthread_mutex_t sim_mutex; +sem_t sim_sem; // Mutex for thread finish count pthread_mutex_t finish_mutex; int finish_count = 0; +// Mutex for global time +pthread_mutex_t time_mutex; +int TIME = 1; + typedef struct ThreadArgs { int cpu_id; char *print_buffer; @@ -64,6 +65,18 @@ Queue *input_queue() { return queue; } +int getTime() { + 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); +} + void *print(void *args) { // Cast args and create local variables ThreadArgs *thread_args = (ThreadArgs *) args; @@ -78,38 +91,29 @@ void *print(void *args) { } printf("\n"); - int test = 0; - while (true) { - pthread_mutex_lock(&sim_mutex); - if (finish_count == CPUS) { - break; - } - - printf("%d", TIME); + sem_wait(&print_sem); + int time = getTime(); + // Print the time and the print buffer + printf("%d", time); for (int i = 0; i < CPUS; ++i) { - // Allow the simulation to begin - //sem_post(&sim_sem); - - // Wait for the simulation to finish - //sem_wait(&print_sem); - - - for (int j = 0; j < CPUS; ++j) { - - printf("\t%c", print_buffer[j]); - } - + printf("\t%c", print_buffer[i]); } - printf("\n"); - TIME++; + printf("\n"); + + // Check if every process is done + if (finish_count == CPUS) { + break; + } + + incrementTime(); + + // Increment the simulation semaphore to let the simulation threads run + for (int i = 0; i < CPUS; ++i) { + sem_post(&sim_sem); + } - test++; - if (test == 35) { - break; - } - pthread_mutex_unlock(&sim_mutex); } // Print the summary @@ -128,22 +132,31 @@ void *simulation(void *args) { char *print_buffer = thread_args->print_buffer; int cpu_id = thread_args->cpu_id; - // Loop variables int quantum = QUANTUM; int addedJobs = 0; Process *process = NULL; + 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; + } // Create a queue for the simulation Queue *sim_queue = createQueue(); while (true) { - pthread_mutex_lock(&sim_mutex); + sem_wait(&sim_sem); + int time = getTime(); - //sem_wait(&sim_sem); // Wait for the thread to be allowed to start // 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) { + 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); @@ -156,7 +169,8 @@ void *simulation(void *args) { 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 == in_queue->size) { + if (addedJobs >= numberOfJobsForThisCPU) { + break; // If all jobs have been added, and the simulation queue is empty, then we are done } } else { @@ -165,7 +179,7 @@ void *simulation(void *args) { 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 @@ -175,8 +189,7 @@ void *simulation(void *args) { } } // Allow the print thread to print - //sem_post(&print_sem); - pthread_mutex_unlock(&sim_mutex); + sem_post(&print_sem); } // Free memory for the simulation queue. There should be nothing left in it stop(sim_queue); @@ -185,7 +198,8 @@ void *simulation(void *args) { 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); return NULL; } @@ -195,10 +209,10 @@ int main() { Queue *in_queue = input_queue(); // Create the input queue // Make sure sem is init right after getting cpus, which is done in input_queue - //sem_init(&sim_sem, 0, CPUS); // Initialize the semaphore - //sem_init(&print_sem, 0, 0); // Initialize the semaphore + sem_init(&print_sem, 0, 0); // Initialize the semaphore + sem_init(&sim_sem, 0, CPUS); // Initialize the semaphore pthread_mutex_init(&finish_mutex, NULL); // Initialize the mutex - pthread_mutex_init(&sim_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