From 3b149882eec77a4b9a98e01e8885ab2f36c0ac31 Mon Sep 17 00:00:00 2001 From: Isaac Shoebottom Date: Mon, 30 Oct 2023 12:21:07 -0300 Subject: [PATCH] Work on a5 --- .../documentation/a5_sample_input_1.txt | 10 +- .../documentation/a5_sample_input_2.txt | 7 + .../documentation/a5_sample_input_3.txt | 8 + .../documentation/a5_sample_output_2.txt | 16 ++ .../documentation/a5_sample_output_3.txt | 19 ++ Assignment5/hard_affinity.c | 202 +++++++++++------- 6 files changed, 181 insertions(+), 81 deletions(-) create mode 100644 Assignment5/documentation/a5_sample_input_2.txt create mode 100644 Assignment5/documentation/a5_sample_input_3.txt create mode 100644 Assignment5/documentation/a5_sample_output_2.txt create mode 100644 Assignment5/documentation/a5_sample_output_3.txt diff --git a/Assignment5/documentation/a5_sample_input_1.txt b/Assignment5/documentation/a5_sample_input_1.txt index 6c15b97..10aab23 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 -Jim A 2 5 -Mary B 2 2 -Sue C 5 5 -Mary D 6 2 \ No newline at end of file +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 diff --git a/Assignment5/documentation/a5_sample_input_2.txt b/Assignment5/documentation/a5_sample_input_2.txt new file mode 100644 index 0000000..397c2d3 --- /dev/null +++ b/Assignment5/documentation/a5_sample_input_2.txt @@ -0,0 +1,7 @@ +2 +3 2 +User Process Arrival Duration Affinity +Jim A 2 5 0 +Mary B 2 2 1 +Sue C 5 5 1 +Mary D 6 2 0 diff --git a/Assignment5/documentation/a5_sample_input_3.txt b/Assignment5/documentation/a5_sample_input_3.txt new file mode 100644 index 0000000..a0502bd --- /dev/null +++ b/Assignment5/documentation/a5_sample_input_3.txt @@ -0,0 +1,8 @@ +2 +3 2 +User Process Arrival Duration Affinity +Jim A 2 5 0 +Mary B 2 2 1 +Mary C 3 4 1 +Sue D 5 5 1 +Mary E 6 2 0 diff --git a/Assignment5/documentation/a5_sample_output_2.txt b/Assignment5/documentation/a5_sample_output_2.txt new file mode 100644 index 0000000..7444d8f --- /dev/null +++ b/Assignment5/documentation/a5_sample_output_2.txt @@ -0,0 +1,16 @@ +Time CPU0 CPU1 +1 - - +2 A B +3 A B +4 A - +5 A C +6 A C +7 D C +8 D C +9 - C +10 - - + +Summary +Jim 6 +Mary 8 +Sue 9 diff --git a/Assignment5/documentation/a5_sample_output_3.txt b/Assignment5/documentation/a5_sample_output_3.txt new file mode 100644 index 0000000..56bf132 --- /dev/null +++ b/Assignment5/documentation/a5_sample_output_3.txt @@ -0,0 +1,19 @@ +Time CPU0 CPU1 +1 - - +2 A B +3 A B +4 A C +5 A C +6 A D +7 E D +8 E C +9 - C +10 - D +11 - D +12 - D +13 - - + +Summary +Jim 6 +Mary 9 +Sue 12 diff --git a/Assignment5/hard_affinity.c b/Assignment5/hard_affinity.c index ce54943..f137be9 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -6,14 +6,26 @@ // 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 + #define MAX_USERNAME_LENGTH 100 int QUANTUM; int CPUS; int TIME = 0; -// Semaphore for the print function -sem_t print_semaphore; +// 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; + +// Mutex for thread finish count +pthread_mutex_t finish_mutex; +int finish_count = 0; typedef struct ThreadArgs { int cpu_id; @@ -22,7 +34,7 @@ typedef struct ThreadArgs { Queue *in_queue; } ThreadArgs; -ThreadArgs *createArgs(int cpu_id, char* print_buffer, Queue *summary_queue, Queue *in_queue) { +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; @@ -32,32 +44,29 @@ ThreadArgs *createArgs(int cpu_id, char* print_buffer, Queue *summary_queue, Que } Queue *input_queue() { - Queue *queue = createQueue(); - char username[MAX_USERNAME_LENGTH]; // username buffer - char job; - int arrival_time, duration, affinity; - - scanf("%d", &QUANTUM); - while (getchar() != '\n'); // clear the newline from the buffer + Queue *queue = createQueue(); + char username[MAX_USERNAME_LENGTH]; // username buffer + char job; + int arrival_time, duration, affinity; 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 + scanf("%d", &QUANTUM); + while (getchar() != '\n'); // clear the newline from the buffer - 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) { - Process *process = createProcess(username, job, arrival_time, duration, affinity); - enqueue(queue, process); - } - return queue; + 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) { + Process *process = createProcess(username, job, arrival_time, duration, affinity); + enqueue(queue, process); + } + return queue; } -void* print(void *args) { +void *print(void *args) { // Cast args and create local variables - ThreadArgs *thread_args = (ThreadArgs*) 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; @@ -69,15 +78,38 @@ void* print(void *args) { } printf("\n"); - for (int i = 0; i < in_queue->size; ++i) { - TIME++; - // Allow the simulation to begin - sem_post(&print_semaphore); + int test = 0; + + while (true) { + pthread_mutex_lock(&sim_mutex); + if (finish_count == CPUS) { + break; + } + + 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]); + } - for (int j = 0; j < CPUS; ++j) { - printf("%d\t%c", TIME, print_buffer[i]); } printf("\n"); + TIME++; + + test++; + if (test == 35) { + break; + } + pthread_mutex_unlock(&sim_mutex); } // Print the summary @@ -88,68 +120,86 @@ void* print(void *args) { } -void* simulation(void *args) { +void *simulation(void *args) { // Cast args and create local variables - ThreadArgs *thread_args = (ThreadArgs*) args; + 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; - // Loop variables - int quantum = QUANTUM; - int addedJobs = 0; + // Loop variables + int quantum = QUANTUM; + int addedJobs = 0; Process *process = NULL; - // Create a queue for the simulation - Queue *sim_queue = createQueue(); - while (true) { - 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->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; - } + // Create a queue for the simulation + Queue *sim_queue = createQueue(); + while (true) { + pthread_mutex_lock(&sim_mutex); - // 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 == in_queue->size) { - 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; - } - } - } - // Free memory for the simulation queue. There should be nothing left in it - stop(sim_queue); + //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) { + // 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; + } + + // 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 == in_queue->size) { + 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); + pthread_mutex_unlock(&sim_mutex); + } + // 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); return NULL; } int main() { - Queue *in_queue = input_queue(); // Create the input queue + setvbuf(stdout, NULL, _IONBF, 0); + 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 + pthread_mutex_init(&finish_mutex, NULL); // Initialize the mutex + pthread_mutex_init(&sim_mutex, NULL); // Initialize the mutex + Queue *summary_queue = createQueue(); // Create the summary queue char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer @@ -170,7 +220,7 @@ int main() { // Create the simulation threads pthread_t threads[CPUS]; - ThreadArgs* args[CPUS]; // Array of arguments for each thread, so we can free them later + ThreadArgs *args[CPUS]; // Array of arguments for each thread, so we can free them later for (int i = 0; i < CPUS; i++) { args[i] = createArgs(i, print_buffer, summary_queue, in_queue); pthread_create(&threads[i], NULL, &simulation, args[i]); @@ -183,8 +233,8 @@ int main() { pthread_join(threads[i], NULL); free(args[i]); } - stop(in_queue); // Free memory for input queue + 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; + return 0; }