diff --git a/Assignment5/hard_affinity.c b/Assignment5/hard_affinity.c index c699295..abda2b3 100644 --- a/Assignment5/hard_affinity.c +++ b/Assignment5/hard_affinity.c @@ -25,10 +25,9 @@ int *QUANTUM; int CPUS; sem_t print_sem; -sem_t sim_sem; +sem_t *sim_sems; pthread_mutex_t finish_mutex; pthread_mutex_t time_mutex; - pthread_mutex_t summary_mutex; int finish_count = 0; @@ -115,11 +114,11 @@ void *print(void *args) { } printf("\n"); - bool finished = false; - while (finished == false) { + while (getFinishCount() < CPUS) { // Wait for all the simulation threads to finish - for (int i = getFinishCount(); i < CPUS; ++i) { + for (int i = 0; i < CPUS; ++i) { + //printf("print wait cpu_id: %d\n", i); sem_wait(&print_sem); } @@ -132,17 +131,12 @@ void *print(void *args) { } printf("\n"); - // Check if every process is done - if (getFinishCount() == CPUS) { - finished = true; - } - // Essentially increase the time right before simulating incrementTime(); // Increment the simulation semaphore to let the simulation threads run - for (int i = getFinishCount(); i < CPUS; ++i) { - sem_post(&sim_sem); + for (int i = 0; i < CPUS; ++i) { + sem_post(&sim_sems[i]); } } @@ -151,6 +145,14 @@ void *print(void *args) { pthread_mutex_lock(&summary_mutex); printList(thread_args->summary_queue); pthread_mutex_unlock(&summary_mutex); + + // let the simulation threads finish + // for some reason, if this is not here, the simulation threads will not finish + for (int i = 0; i < CPUS; ++i) { + sem_post(&sim_sems[i]); + } + + //printf("print thread done\n"); return NULL; } @@ -167,8 +169,8 @@ void *simulation(void *args) { int quantum = QUANTUM[cpu_id]; int addedJobs = 0; int numberOfJobsForThisCPU = 0; - int time = 0; - int previousTime; + int time; + bool doneSimulating = false; Process *process = NULL; // Count number of jobs this CPU has to do @@ -180,59 +182,65 @@ void *simulation(void *args) { process = process->prev_elem; } - bool finished = false; // Create a queue for the simulation Queue *sim_queue = createQueue(); - while (finished == false) { + while (getFinishCount() < CPUS) { // 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++; + //printf("sim wait cpu_id: %d\n", cpu_id); + sem_wait(&sim_sems[cpu_id]); + if (!doneSimulating) { + 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++; + } + process = process->prev_elem; } - process = process->prev_elem; - } - // Begin simulating the current job - process = sim_queue->end; - 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 - process = dequeue(sim_queue); - 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 + // Begin simulating the current job + process = sim_queue->end; + 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 + process = dequeue(sim_queue); + 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) { + // Need to do this while finish is locked, otherwise the print thread will exit early + incrementFinishCount(); + // If all jobs have been added, and the simulation queue is empty, then we are done + doneSimulating = true; + } } + } // Allow the print thread to print because the simulation for this tick is done sem_post(&print_sem); - } + //printf("sim post cpu_id: %d\n", cpu_id); } + // Let the print thread one last time + 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 - incrementFinishCount(); + + //printf("sim thread done: %d\n", cpu_id); return NULL; } @@ -243,7 +251,13 @@ 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 + + // Array of semaphores, one for each CPU + sim_sems = malloc(sizeof(sem_t) * CPUS); + for (int i = 0; i < CPUS; ++i) { + sem_init(&sim_sems[i], 0, 1); + } + 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 @@ -273,19 +287,47 @@ int main() { pthread_create(&threads[i], NULL, &simulation, args[i]); } + // Wait for print thread to finish + int r = pthread_join(print_thread, NULL); + free(print_args); + //printf("joined print thread\n"); + //printf("thread result: %d\n", r); + // Threads simulate, then print for (int i = 0; i < CPUS; i++) { - pthread_join(threads[i], NULL); + r = pthread_join(threads[i], NULL); + //printf("joined sim thread: %d\n", i); + //printf("thread result: %d\n", r); free(args[i]); } - // Wait for print thread to finish - pthread_join(print_thread, NULL); - free(print_args); + + + // Stop semaphores + for (int i = 0; i < CPUS; ++i) { + sem_destroy(&sim_sems[i]); + //printf("destroyed sim sem: %d\n", i); + } + free(sim_sems); + sem_destroy(&print_sem); + + + // Stop mutexes + + pthread_mutex_unlock(&finish_mutex); + pthread_mutex_unlock(&summary_mutex); + pthread_mutex_unlock(&time_mutex); + + + pthread_mutex_destroy(&finish_mutex); + pthread_mutex_destroy(&summary_mutex); + pthread_mutex_destroy(&time_mutex); + 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; + + return EXIT_SUCCESS; } diff --git a/Assignment5/testing/output3_3.txt b/Assignment5/testing/output3_3.txt new file mode 100644 index 0000000..83b42c0 --- /dev/null +++ b/Assignment5/testing/output3_3.txt @@ -0,0 +1,49 @@ +Time CPU0 CPU1 +sim post cpu_id: 0 +sim post cpu_id: 1 +1 - - +sim post cpu_id: 0 +sim post cpu_id: 1 +2 A B +sim post cpu_id: 0 +sim post cpu_id: 1 +3 A B +sim post cpu_id: 0 +sim post cpu_id: 1 +4 A C +sim post cpu_id: 0 +sim post cpu_id: 1 +5 A C +sim post cpu_id: 0 +sim post cpu_id: 1 +6 A D +sim post cpu_id: 0 +sim post cpu_id: 1 +7 E D +sim post cpu_id: 0 +sim post cpu_id: 1 +8 E C +sim post cpu_id: 0 +sim post cpu_id: 1 +9 - C +sim post cpu_id: 0 +sim post cpu_id: 1 +10 - D +sim post cpu_id: 0 +sim post cpu_id: 1 +11 - D +sim post cpu_id: 0 +sim post cpu_id: 1 +12 - D +sim post cpu_id: 0 +sim post cpu_id: 1 +sim thread done: 1 +13 - - + +Summary +Jim 6 +Mary 9 +Sue 12 +print thread done +sim post cpu_id: 0 +sim thread done: 0 diff --git a/Assignment5/testing/test2.sh b/Assignment5/testing/test2.sh index 7500a6b..6b9ee36 100644 --- a/Assignment5/testing/test2.sh +++ b/Assignment5/testing/test2.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +counter=1 + # Do this forever while true; do # Capture output of the command @@ -11,5 +13,6 @@ while true; do echo "$output" exit 1 fi - echo "Test 2 passed" + echo "Test 2 passed $counter times" + counter=$((counter+1)) done \ No newline at end of file diff --git a/Assignment5/testing/test2simple.sh b/Assignment5/testing/test2simple.sh new file mode 100644 index 0000000..a59ce1d --- /dev/null +++ b/Assignment5/testing/test2simple.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +counter=0 + +# Do this forever +while true; do + (../build/Assignment5 < ../documentation/a5_sample_input_2.txt) + counter=$((counter+1)) + echo $counter +done \ No newline at end of file diff --git a/Assignment5/testing/test3.sh b/Assignment5/testing/test3.sh index 7b73acc..ba54e50 100644 --- a/Assignment5/testing/test3.sh +++ b/Assignment5/testing/test3.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +counter=1 + # Do this forever while true; do # Capture output of the command @@ -11,4 +13,6 @@ while true; do echo "$output" exit 1 fi + echo "Test 3 passed $counter times" + counter=$((counter+1)) done \ No newline at end of file