Mostly correct solution

This commit is contained in:
Isaac Shoebottom 2023-11-04 23:34:31 -03:00
parent 552f95fe99
commit c3faf35400
5 changed files with 170 additions and 62 deletions

View File

@ -25,10 +25,9 @@ int *QUANTUM;
int CPUS; int CPUS;
sem_t print_sem; sem_t print_sem;
sem_t sim_sem; sem_t *sim_sems;
pthread_mutex_t finish_mutex; pthread_mutex_t finish_mutex;
pthread_mutex_t time_mutex; pthread_mutex_t time_mutex;
pthread_mutex_t summary_mutex; pthread_mutex_t summary_mutex;
int finish_count = 0; int finish_count = 0;
@ -115,11 +114,11 @@ void *print(void *args) {
} }
printf("\n"); printf("\n");
bool finished = false;
while (finished == false) { while (getFinishCount() < CPUS) {
// Wait for all the simulation threads to finish // 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); sem_wait(&print_sem);
} }
@ -132,17 +131,12 @@ void *print(void *args) {
} }
printf("\n"); printf("\n");
// Check if every process is done
if (getFinishCount() == CPUS) {
finished = true;
}
// Essentially increase the time right before simulating // Essentially increase the time right before simulating
incrementTime(); incrementTime();
// Increment the simulation semaphore to let the simulation threads run // Increment the simulation semaphore to let the simulation threads run
for (int i = getFinishCount(); i < CPUS; ++i) { for (int i = 0; i < CPUS; ++i) {
sem_post(&sim_sem); sem_post(&sim_sems[i]);
} }
} }
@ -151,6 +145,14 @@ void *print(void *args) {
pthread_mutex_lock(&summary_mutex); pthread_mutex_lock(&summary_mutex);
printList(thread_args->summary_queue); printList(thread_args->summary_queue);
pthread_mutex_unlock(&summary_mutex); 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; return NULL;
} }
@ -167,8 +169,8 @@ void *simulation(void *args) {
int quantum = QUANTUM[cpu_id]; int quantum = QUANTUM[cpu_id];
int addedJobs = 0; int addedJobs = 0;
int numberOfJobsForThisCPU = 0; int numberOfJobsForThisCPU = 0;
int time = 0; int time;
int previousTime; bool doneSimulating = false;
Process *process = NULL; Process *process = NULL;
// Count number of jobs this CPU has to do // Count number of jobs this CPU has to do
@ -180,59 +182,65 @@ void *simulation(void *args) {
process = process->prev_elem; process = process->prev_elem;
} }
bool finished = false;
// Create a queue for the simulation // Create a queue for the simulation
Queue *sim_queue = createQueue(); Queue *sim_queue = createQueue();
while (finished == false) { while (getFinishCount() < CPUS) {
// Only simulate if the time has changed // Only simulate if the time has changed
previousTime = time; //printf("sim wait cpu_id: %d\n", cpu_id);
time = getTime(); sem_wait(&sim_sems[cpu_id]);
if (previousTime != time) { if (!doneSimulating) {
sem_wait(&sim_sem); time = getTime();
// Begin going through all jobs and enqueueing them if they have arrived // Begin going through all jobs and enqueueing them if they have arrived
process = in_queue->end; process = in_queue->end;
for (int i = 0; i < in_queue->size; i++) { 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 // Create copy to keep the queues separate
Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity); Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity);
enqueue(sim_queue, copy); enqueue(sim_queue, copy);
addedJobs++; addedJobs++;
}
process = process->prev_elem;
} }
process = process->prev_elem;
}
// Begin simulating the current job // Begin simulating the current job
process = sim_queue->end; process = sim_queue->end;
if (sim_queue->size != 0) { if (sim_queue->size != 0) {
print_buffer[cpu_id] = process->job; print_buffer[cpu_id] = process->job;
process->duration--; process->duration--;
quantum--; quantum--;
if (process->duration == 0) { // If the process is done, delete it 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 Process *temp = dequeue(sim_queue); // Store the process in a temp variable for deletion
pthread_mutex_lock(&summary_mutex); pthread_mutex_lock(&summary_mutex);
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
pthread_mutex_unlock(&summary_mutex); pthread_mutex_unlock(&summary_mutex);
destroyProcess(temp); // This should be called on every process destroyProcess(temp); // This should be called on every process
quantum = QUANTUM[cpu_id]; // Make sure to reset the quantum when a process is done 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 } else if (quantum == 0) { // If the quantum is 0, then we need to dequeue the process and enqueue it again
process = dequeue(sim_queue); process = dequeue(sim_queue);
enqueue(sim_queue, process); enqueue(sim_queue, process);
quantum = QUANTUM[cpu_id]; quantum = QUANTUM[cpu_id];
} }
} else { //If there is nothing in sim_queue, put '-' in the print buffer } else { //If there is nothing in sim_queue, put '-' in the print buffer
print_buffer[cpu_id] = '-'; print_buffer[cpu_id] = '-';
if (addedJobs >= numberOfJobsForThisCPU) { if (addedJobs >= numberOfJobsForThisCPU) {
finished = true; // If all jobs have been added, and the simulation queue is empty, then we are done // 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 // Allow the print thread to print because the simulation for this tick is done
sem_post(&print_sem); 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 // Free memory for the simulation queue. There should be nothing left in it
stop(sim_queue); stop(sim_queue);
// Signal that the thread is done
incrementFinishCount(); //printf("sim thread done: %d\n", cpu_id);
return NULL; return NULL;
} }
@ -243,7 +251,13 @@ int main() {
// Make sure sem is init right after getting cpus, which is done in input_queue // 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(&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(&finish_mutex, NULL); // Initialize the mutex
pthread_mutex_init(&time_mutex, NULL); // Initialize the mutex pthread_mutex_init(&time_mutex, NULL); // Initialize the mutex
pthread_mutex_init(&summary_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]); 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 // Threads simulate, then print
for (int i = 0; i < CPUS; i++) { 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]); 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(in_queue); // Free memory for input queue
stop(summary_queue); // Free memory for summary queue stop(summary_queue); // Free memory for summary queue
free(print_buffer); // Free memory for print buffer free(print_buffer); // Free memory for print buffer
free(QUANTUM); // Free memory for quantum array free(QUANTUM); // Free memory for quantum array
return 0;
return EXIT_SUCCESS;
} }

View File

@ -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

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
counter=1
# Do this forever # Do this forever
while true; do while true; do
# Capture output of the command # Capture output of the command
@ -11,5 +13,6 @@ while true; do
echo "$output" echo "$output"
exit 1 exit 1
fi fi
echo "Test 2 passed" echo "Test 2 passed $counter times"
counter=$((counter+1))
done done

View File

@ -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

View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
counter=1
# Do this forever # Do this forever
while true; do while true; do
# Capture output of the command # Capture output of the command
@ -11,4 +13,6 @@ while true; do
echo "$output" echo "$output"
exit 1 exit 1
fi fi
echo "Test 3 passed $counter times"
counter=$((counter+1))
done done