Mostly working a5

This commit is contained in:
Isaac Shoebottom 2023-11-02 21:08:48 -03:00
parent 64d3af7762
commit 3eaf16e12b
2 changed files with 126 additions and 96 deletions

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -4,15 +4,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "lib/queue.h" #include "lib/queue.h"
// 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
// Need to make sure both threads read time once, or only tick once per time increment
#define MAX_USERNAME_LENGTH 100 #define MAX_USERNAME_LENGTH 100
int QUANTUM; int *QUANTUM;
int CPUS; int CPUS;
// Semaphore for the threads to simulate // Semaphore for the threads to simulate
@ -53,7 +46,13 @@ Queue *input_queue() {
scanf("%d", &CPUS); scanf("%d", &CPUS);
while (getchar() != '\n'); // clear the newline from the buffer while (getchar() != '\n'); // clear the newline from the buffer
scanf("%d", &QUANTUM); // Allocate dynamic quantum array
QUANTUM = malloc(sizeof(int) * CPUS);
int i = 0;
while (i < CPUS) {
scanf("%d", &QUANTUM[i]);
i++;
}
while (getchar() != '\n'); // clear the newline from the buffer while (getchar() != '\n'); // clear the newline from the buffer
while (getchar() != '\n'); // ignore the rest of the line, this is the table line while (getchar() != '\n'); // ignore the rest of the line, this is the table line
@ -66,15 +65,29 @@ Queue *input_queue() {
} }
int getTime() { int getTime() {
pthread_mutex_lock(&time_mutex); pthread_mutex_lock(&time_mutex);
int time = TIME; int time = TIME;
pthread_mutex_unlock(&time_mutex); pthread_mutex_unlock(&time_mutex);
return time; return time;
} }
void incrementTime() { void incrementTime() {
pthread_mutex_lock(&time_mutex); pthread_mutex_lock(&time_mutex);
TIME++; TIME++;
pthread_mutex_unlock(&time_mutex); pthread_mutex_unlock(&time_mutex);
}
int getFinishCount() {
pthread_mutex_lock(&finish_mutex);
int count = finish_count;
pthread_mutex_unlock(&finish_mutex);
return count;
}
void incrementFinishCount() {
pthread_mutex_lock(&finish_mutex);
finish_count++;
pthread_mutex_unlock(&finish_mutex);
} }
void *print(void *args) { void *print(void *args) {
@ -82,7 +95,6 @@ void *print(void *args) {
ThreadArgs *thread_args = (ThreadArgs *) args; ThreadArgs *thread_args = (ThreadArgs *) args;
char *print_buffer = thread_args->print_buffer; char *print_buffer = thread_args->print_buffer;
Queue *summary_queue = thread_args->summary_queue; Queue *summary_queue = thread_args->summary_queue;
Queue *in_queue = thread_args->in_queue;
// Print the Time label as well as the CPU labels // Print the Time label as well as the CPU labels
printf("Time"); printf("Time");
@ -92,28 +104,32 @@ void *print(void *args) {
printf("\n"); printf("\n");
while (true) { while (true) {
sem_wait(&print_sem); // Wait for all the simulation threads to finish
int time = getTime(); for (int i = 0; i < CPUS - getFinishCount(); ++i) {
sem_wait(&print_sem);
}
// Print the time and the print buffer int time = getTime();
// Print the time and the print buffer
printf("%d", time); printf("%d", time);
for (int i = 0; i < CPUS; ++i) { for (int i = 0; i < CPUS; ++i) {
printf("\t%c", print_buffer[i]); printf("\t%c", print_buffer[i]);
} }
printf("\n"); printf("\n");
// Check if every process is done // Check if every process is done
if (finish_count == CPUS) { if (getFinishCount() == CPUS) {
break; break;
} }
incrementTime(); // Essentially increase the time right before simulating
incrementTime();
// Increment the simulation semaphore to let the simulation threads run
for (int i = 0; i < CPUS; ++i) {
sem_post(&sim_sem);
}
// Increment the simulation semaphore to let the simulation threads run
for (int i = 0; i < CPUS - getFinishCount(); ++i) {
sem_post(&sim_sem);
}
} }
// Print the summary // Print the summary
@ -133,73 +149,77 @@ void *simulation(void *args) {
int cpu_id = thread_args->cpu_id; int cpu_id = thread_args->cpu_id;
// Loop variables // Loop variables
int quantum = QUANTUM; int quantum = QUANTUM[cpu_id];
int addedJobs = 0; int addedJobs = 0;
Process *process = NULL; int numberOfJobsForThisCPU = 0;
int numberOfJobsForThisCPU = 0;
// Count number of jobs this CPU has to do int previousTime;
process = in_queue->end; Process *process = NULL;
for (int i = 0; i < in_queue->size; ++i) {
if (process->affinity == cpu_id) { // Count number of jobs this CPU has to do
numberOfJobsForThisCPU++; process = in_queue->end;
} for (int i = 0; i < in_queue->size; ++i) {
process = process->prev_elem; if (process->affinity == cpu_id) {
} numberOfJobsForThisCPU++;
}
process = process->prev_elem;
}
int time = 0;
// Create a queue for the simulation // Create a queue for the simulation
Queue *sim_queue = createQueue(); Queue *sim_queue = createQueue();
while (true) { while (true) {
sem_wait(&sim_sem); // Only simulate if the time has changed
int time = getTime(); previousTime = time;
time = getTime();
// Begin going through all jobs and enqueueing them if they have arrived if (previousTime != time) {
process = in_queue->end; sem_wait(&sim_sem);
for (int i = 0; i < in_queue->size; i++) { // Begin going through all jobs and enqueueing them if they have arrived
if (process->affinity == cpu_id && process->arrival_time == time) { process = in_queue->end;
// Create copy to keep the queues separate for (int i = 0; i < in_queue->size; i++) {
Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity); if (process->affinity == cpu_id && process->arrival_time == time) {
enqueue(sim_queue, copy); // Create copy to keep the queues separate
addedJobs++; 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 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 {
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[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];
}
}
// Allow the print thread to print because the simulation for this tick is done
sem_post(&print_sem);
} }
// 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 {
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);
} }
// 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 // Signal that the thread is done
pthread_mutex_lock(&finish_mutex); incrementFinishCount();
finish_count++; // Allow the print thread to print one last time
pthread_mutex_unlock(&finish_mutex); sem_post(&print_sem);
// Allow the print thread to print one last time
sem_post(&print_sem);
return NULL; return NULL;
} }
@ -210,9 +230,9 @@ 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 sem_init(&sim_sem, 0, CPUS); // Initialize the semaphore
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
Queue *summary_queue = createQueue(); // Create the summary queue Queue *summary_queue = createQueue(); // Create the summary queue
char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer
@ -227,11 +247,6 @@ int main() {
process = process->prev_elem; 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 // Create the simulation threads
pthread_t threads[CPUS]; 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
@ -240,15 +255,25 @@ int main() {
pthread_create(&threads[i], NULL, &simulation, args[i]); pthread_create(&threads[i], NULL, &simulation, args[i]);
} }
// This should make sure all threads are done simulating, as the print function exits after simulation is done
pthread_join(print_thread, NULL); // Create the print thread
// Just to make sure all threads are done 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++) { for (int i = 0; i < CPUS; i++) {
pthread_join(threads[i], NULL); pthread_join(threads[i], NULL);
free(args[i]); free(args[i]);
} }
pthread_join(print_thread, NULL);
free(print_args);
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
return 0; return 0;
} }