diff --git a/Assignment5/Process.md b/Assignment5/Process.md new file mode 100644 index 0000000..ff6d964 --- /dev/null +++ b/Assignment5/Process.md @@ -0,0 +1,7 @@ +1. The print sem is initialized to 0, because the print needs to first wait for the first simulation tick to happen. +2. The simulation sem is initialized to the number of cpus, since each cpu needs to tick once before the print can happen. +3. The simulation on each cpu is started, and at the end of each simulation, the sim thread will post to the print sem, so the print thread can print the results. The sim thread will now wait for the print sem, since it needs to wait for the print to finish before it can start the next simulation. +4. The print thread will wait on the sim sem for each CPU thread, and this should leave the sem at 0 again. +5. At the end of the print function, before the simulation is allowed to print again, the print thread will increase the time, and then post to the sim sem for each CPU thread, so the simulation can start again. +6. Repeat steps 3-5 until the simulation is done. +7. \ No newline at end of file diff --git a/Assignment5/documentation/a5_sample_input_2.txt b/Assignment5/documentation/a5_sample_input_2.txt index 397c2d3..df07e48 100644 --- a/Assignment5/documentation/a5_sample_input_2.txt +++ b/Assignment5/documentation/a5_sample_input_2.txt @@ -1,7 +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 +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 index a0502bd..7693e89 100644 --- a/Assignment5/documentation/a5_sample_input_3.txt +++ b/Assignment5/documentation/a5_sample_input_3.txt @@ -1,8 +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 +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/hard_affinity.c b/Assignment5/hard_affinity.c index 9ef4c82..9d07f01 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -8,19 +8,15 @@ int *QUANTUM; int CPUS; -// Semaphore for the threads to simulate sem_t print_sem; - 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; +pthread_mutex_t summary_mutex; + +int finish_count = 0; +int TIME = 1; typedef struct ThreadArgs { int cpu_id; char *print_buffer; @@ -94,7 +90,6 @@ 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; // Print the Time label as well as the CPU labels printf("Time"); @@ -103,9 +98,11 @@ void *print(void *args) { } printf("\n"); - while (true) { + bool finished = false; + + while (finished == false) { // Wait for all the simulation threads to finish - for (int i = 0; i < CPUS - getFinishCount(); ++i) { + for (int i = getFinishCount(); i < CPUS; ++i) { sem_wait(&print_sem); } @@ -120,22 +117,23 @@ void *print(void *args) { // Check if every process is done if (getFinishCount() == CPUS) { - break; + finished = true; } // 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) { + for (int i = getFinishCount(); i < CPUS; ++i) { sem_post(&sim_sem); } } // Print the summary printf("\nSummary\n"); - printList(summary_queue); - + pthread_mutex_lock(&summary_mutex); + printList(thread_args->summary_queue); + pthread_mutex_unlock(&summary_mutex); return NULL; } @@ -152,7 +150,7 @@ void *simulation(void *args) { int quantum = QUANTUM[cpu_id]; int addedJobs = 0; int numberOfJobsForThisCPU = 0; - + int time = 0; int previousTime; Process *process = NULL; @@ -165,11 +163,10 @@ void *simulation(void *args) { process = process->prev_elem; } - int time = 0; - + bool finished = false; // Create a queue for the simulation Queue *sim_queue = createQueue(); - while (true) { + while (finished == false) { // Only simulate if the time has changed previousTime = time; time = getTime(); @@ -189,18 +186,15 @@ void *simulation(void *args) { // 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 { + if (sim_queue->size != 0) { 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 + pthread_mutex_lock(&summary_mutex); search(summary_queue, temp->username)->finish_time = time; // Set the finish time for the summary queue + pthread_mutex_unlock(&summary_mutex); 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 @@ -208,6 +202,11 @@ void *simulation(void *args) { enqueue(sim_queue, process); quantum = QUANTUM[cpu_id]; } + } else { //If there is nothing in sim_queue, put '-' in the print buffer + print_buffer[cpu_id] = '-'; + if (addedJobs >= numberOfJobsForThisCPU) { + finished = true; // If all jobs have been added, and the simulation queue is empty, then we are done + } } // Allow the print thread to print because the simulation for this tick is done sem_post(&print_sem); @@ -215,11 +214,8 @@ void *simulation(void *args) { } // Free memory for the simulation queue. There should be nothing left in it stop(sim_queue); - // Signal that the thread is done incrementFinishCount(); - // Allow the print thread to print one last time - sem_post(&print_sem); return NULL; } @@ -233,6 +229,7 @@ int main() { 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(&summary_mutex, NULL); // Initialize the mutex Queue *summary_queue = createQueue(); // Create the summary queue char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer @@ -246,6 +243,10 @@ 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]; @@ -255,19 +256,13 @@ int main() { pthread_create(&threads[i], NULL, &simulation, args[i]); } - - // 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]); } + + // Wait for print thread to finish pthread_join(print_thread, NULL); free(print_args); diff --git a/Assignment5/testing/output2.txt b/Assignment5/testing/output2.txt new file mode 100644 index 0000000..6eab355 --- /dev/null +++ b/Assignment5/testing/output2.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/testing/output3-1.txt b/Assignment5/testing/output3-1.txt new file mode 100644 index 0000000..ee6ec0b --- /dev/null +++ b/Assignment5/testing/output3-1.txt @@ -0,0 +1,32 @@ +Time CPU0 CPU1 +finish count: 0 +1 - - +finish count: 0 +2 A B +finish count: 0 +3 A B +finish count: 0 +4 A C +finish count: 0 +5 A C +finish count: 0 +6 A D +finish count: 0 +7 E D +finish count: 0 +8 E C +finish count: 1 +9 - C +finish count: 1 +10 - D +finish count: 1 +11 - D +finish count: 1 +12 - D +finish count: 1 +13 - - + +Summary +Jim 6 +Mary 9 +Sue 12 diff --git a/Assignment5/testing/output3-2.txt b/Assignment5/testing/output3-2.txt new file mode 100644 index 0000000..e238937 --- /dev/null +++ b/Assignment5/testing/output3-2.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/testing/output3.txt b/Assignment5/testing/output3.txt new file mode 100644 index 0000000..e238937 --- /dev/null +++ b/Assignment5/testing/output3.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/testing/test2.sh b/Assignment5/testing/test2.sh new file mode 100644 index 0000000..099c932 --- /dev/null +++ b/Assignment5/testing/test2.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Do this forever +while true; do + # Capture output of the command + output=$(../build/Assignment5 < ../documentation/a5_sample_input_2.txt) + # compare against output3.txt + if [ "$output" != "$(cat output2.txt)" ]; then + echo "Test 2 failed" + # show output + echo "$output" + exit 1 + fi +done \ No newline at end of file diff --git a/Assignment5/testing/test3.sh b/Assignment5/testing/test3.sh new file mode 100644 index 0000000..7b73acc --- /dev/null +++ b/Assignment5/testing/test3.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Do this forever +while true; do + # Capture output of the command + output=$(../build/Assignment5 < ../documentation/a5_sample_input_3.txt) + # compare against output3.txt + if [ "$output" != "$(cat output3.txt)" ]; then + echo "Test 3 failed" + # show output + echo "$output" + exit 1 + fi +done \ No newline at end of file