Add working? solution

This commit is contained in:
Isaac Shoebottom 2023-11-02 18:20:54 -03:00
parent 3b149882ee
commit 64d3af7762
2 changed files with 63 additions and 49 deletions

View File

@ -8,25 +8,26 @@
// TODO: Need to use semaphore for thread synchronization, and mutex for shared variables // 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;
int TIME = 0;
// Semaphore for the threads to simulate // Semaphore for the threads to simulate
sem_t sim_sem;
// Semaphore for the thread to control printing
sem_t print_sem; sem_t print_sem;
// Mutex for simulation sem_t sim_sem;
pthread_mutex_t sim_mutex;
// Mutex for thread finish count // Mutex for thread finish count
pthread_mutex_t finish_mutex; pthread_mutex_t finish_mutex;
int finish_count = 0; int finish_count = 0;
// Mutex for global time
pthread_mutex_t time_mutex;
int TIME = 1;
typedef struct ThreadArgs { typedef struct ThreadArgs {
int cpu_id; int cpu_id;
char *print_buffer; char *print_buffer;
@ -64,6 +65,18 @@ Queue *input_queue() {
return queue; return queue;
} }
int getTime() {
pthread_mutex_lock(&time_mutex);
int time = TIME;
pthread_mutex_unlock(&time_mutex);
return time;
}
void incrementTime() {
pthread_mutex_lock(&time_mutex);
TIME++;
pthread_mutex_unlock(&time_mutex);
}
void *print(void *args) { void *print(void *args) {
// Cast args and create local variables // Cast args and create local variables
ThreadArgs *thread_args = (ThreadArgs *) args; ThreadArgs *thread_args = (ThreadArgs *) args;
@ -78,39 +91,30 @@ void *print(void *args) {
} }
printf("\n"); printf("\n");
int test = 0;
while (true) { while (true) {
pthread_mutex_lock(&sim_mutex); sem_wait(&print_sem);
int time = getTime();
// Print the time and the print buffer
printf("%d", time);
for (int i = 0; i < CPUS; ++i) {
printf("\t%c", print_buffer[i]);
}
printf("\n");
// Check if every process is done
if (finish_count == CPUS) { if (finish_count == CPUS) {
break; break;
} }
printf("%d", TIME); incrementTime();
// Increment the simulation semaphore to let the simulation threads run
for (int i = 0; i < CPUS; ++i) { for (int i = 0; i < CPUS; ++i) {
// Allow the simulation to begin sem_post(&sim_sem);
//sem_post(&sim_sem);
// Wait for the simulation to finish
//sem_wait(&print_sem);
for (int j = 0; j < CPUS; ++j) {
printf("\t%c", print_buffer[j]);
} }
} }
printf("\n");
TIME++;
test++;
if (test == 35) {
break;
}
pthread_mutex_unlock(&sim_mutex);
}
// Print the summary // Print the summary
printf("\nSummary\n"); printf("\nSummary\n");
@ -128,22 +132,31 @@ void *simulation(void *args) {
char *print_buffer = thread_args->print_buffer; char *print_buffer = thread_args->print_buffer;
int cpu_id = thread_args->cpu_id; int cpu_id = thread_args->cpu_id;
// Loop variables // Loop variables
int quantum = QUANTUM; int quantum = QUANTUM;
int addedJobs = 0; int addedJobs = 0;
Process *process = NULL; Process *process = NULL;
int numberOfJobsForThisCPU = 0;
// Count number of jobs this CPU has to do
process = in_queue->end;
for (int i = 0; i < in_queue->size; ++i) {
if (process->affinity == cpu_id) {
numberOfJobsForThisCPU++;
}
process = process->prev_elem;
}
// Create a queue for the simulation // Create a queue for the simulation
Queue *sim_queue = createQueue(); Queue *sim_queue = createQueue();
while (true) { while (true) {
pthread_mutex_lock(&sim_mutex); sem_wait(&sim_sem);
int time = getTime();
//sem_wait(&sim_sem); // Wait for the thread to be allowed to start
// 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);
@ -156,7 +169,8 @@ void *simulation(void *args) {
process = sim_queue->end; process = sim_queue->end;
if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer
print_buffer[cpu_id] = '-'; print_buffer[cpu_id] = '-';
if (addedJobs == in_queue->size) { if (addedJobs >= numberOfJobsForThisCPU) {
break; // If all jobs have been added, and the simulation queue is empty, then we are done break; // If all jobs have been added, and the simulation queue is empty, then we are done
} }
} else { } else {
@ -165,7 +179,7 @@ void *simulation(void *args) {
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
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
destroyProcess(temp); // This should be called on every process destroyProcess(temp); // This should be called on every process
quantum = QUANTUM; // Make sure to reset the quantum when a process is done 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 } else if (quantum == 0) { // If the quantum is 0, then we need to dequeue the process and enqueue it again
@ -175,8 +189,7 @@ void *simulation(void *args) {
} }
} }
// Allow the print thread to print // Allow the print thread to print
//sem_post(&print_sem); sem_post(&print_sem);
pthread_mutex_unlock(&sim_mutex);
} }
// 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);
@ -185,7 +198,8 @@ void *simulation(void *args) {
pthread_mutex_lock(&finish_mutex); pthread_mutex_lock(&finish_mutex);
finish_count++; finish_count++;
pthread_mutex_unlock(&finish_mutex); pthread_mutex_unlock(&finish_mutex);
// Allow the print thread to print one last time
sem_post(&print_sem);
return NULL; return NULL;
} }
@ -195,10 +209,10 @@ int main() {
Queue *in_queue = input_queue(); // Create the input queue Queue *in_queue = input_queue(); // Create the input queue
// 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(&sim_sem, 0, CPUS); // Initialize the semaphore 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
pthread_mutex_init(&finish_mutex, NULL); // Initialize the mutex pthread_mutex_init(&finish_mutex, NULL); // Initialize the mutex
pthread_mutex_init(&sim_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