Make a5 better?

This commit is contained in:
Isaac Shoebottom 2023-11-02 22:46:14 -03:00
parent 3eaf16e12b
commit d4f9dd0c5b
10 changed files with 161 additions and 45 deletions

7
Assignment5/Process.md Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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