Work on A5
This commit is contained in:
		@@ -1,10 +1,35 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "lib/queue.h"
 | 
			
		||||
 | 
			
		||||
// TODO: Look into semaphore increment too much in print function, look into synchronization
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MAX_USERNAME_LENGTH 100
 | 
			
		||||
int QUANTUM;
 | 
			
		||||
int CPUS;
 | 
			
		||||
int TIME = 0;
 | 
			
		||||
 | 
			
		||||
// Semaphore for the print function
 | 
			
		||||
sem_t print_semaphore;
 | 
			
		||||
 | 
			
		||||
typedef struct ThreadArgs {
 | 
			
		||||
	int cpu_id;
 | 
			
		||||
	char *print_buffer;
 | 
			
		||||
	Queue *summary_queue;
 | 
			
		||||
	Queue *in_queue;
 | 
			
		||||
} ThreadArgs;
 | 
			
		||||
 | 
			
		||||
ThreadArgs *createArgs(int cpu_id, char* print_buffer, Queue *summary_queue, Queue *in_queue) {
 | 
			
		||||
	ThreadArgs *args = malloc(sizeof(ThreadArgs));
 | 
			
		||||
	args->cpu_id = cpu_id;
 | 
			
		||||
	args->print_buffer = print_buffer;
 | 
			
		||||
	args->summary_queue = summary_queue;
 | 
			
		||||
	args->in_queue = in_queue;
 | 
			
		||||
	return args;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Queue *input_queue() {
 | 
			
		||||
    Queue *queue = createQueue();
 | 
			
		||||
@@ -18,6 +43,9 @@ Queue *input_queue() {
 | 
			
		||||
	scanf("%d", &CPUS);
 | 
			
		||||
	while (getchar() != '\n'); // clear the newline from the buffer
 | 
			
		||||
 | 
			
		||||
	// Make sure sem is init right after getting cpus
 | 
			
		||||
	sem_init(&print_semaphore, 0, CPUS); // Initialize the semaphore
 | 
			
		||||
 | 
			
		||||
    while (getchar() != '\n'); // ignore the rest of the line, this is the table line
 | 
			
		||||
    // Loop through the process table and enqueue each process
 | 
			
		||||
    while (scanf("%99s %c %d %d %d", username, &job, &arrival_time, &duration, &affinity) != EOF) {
 | 
			
		||||
@@ -27,9 +55,12 @@ Queue *input_queue() {
 | 
			
		||||
    return queue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* print(void *print_queue_void) {
 | 
			
		||||
	// Cast the input queue to a Queue pointer
 | 
			
		||||
	Queue *print_queue = (Queue*) print_queue_void;
 | 
			
		||||
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;
 | 
			
		||||
	Queue *in_queue = thread_args->in_queue;
 | 
			
		||||
 | 
			
		||||
	// Print the Time label as well as the CPU labels
 | 
			
		||||
	printf("Time");
 | 
			
		||||
@@ -37,43 +68,48 @@ void* print(void *print_queue_void) {
 | 
			
		||||
		printf("\tCPU%d", i);
 | 
			
		||||
	}
 | 
			
		||||
	printf("\n");
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < in_queue->size; ++i) {
 | 
			
		||||
		TIME++;
 | 
			
		||||
		// Allow the simulation to begin
 | 
			
		||||
		sem_post(&print_semaphore);
 | 
			
		||||
 | 
			
		||||
		for (int j = 0; j < CPUS; ++j) {
 | 
			
		||||
			printf("%d\t%c", TIME, print_buffer[i]);
 | 
			
		||||
		}
 | 
			
		||||
		printf("\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Print the summary
 | 
			
		||||
	printf("\nSummary\n");
 | 
			
		||||
	printList(summary_queue);
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* simulation(void *in_queue_void) {
 | 
			
		||||
	// Cast the input queue to a Queue pointer
 | 
			
		||||
	Queue *in_queue = (Queue*) in_queue_void;
 | 
			
		||||
void* simulation(void *args) {
 | 
			
		||||
	// Cast args and create local variables
 | 
			
		||||
	ThreadArgs *thread_args = (ThreadArgs*) args;
 | 
			
		||||
	Queue *in_queue = thread_args->in_queue;
 | 
			
		||||
	Queue *summary_queue = thread_args->summary_queue;
 | 
			
		||||
	char *print_buffer = thread_args->print_buffer;
 | 
			
		||||
	int cpu_id = thread_args->cpu_id;
 | 
			
		||||
 | 
			
		||||
	// Summary creation
 | 
			
		||||
    Process *process = in_queue->end;
 | 
			
		||||
    Queue *summary_queue = createQueue();
 | 
			
		||||
    for (int i = 0; i < in_queue->size; ++i) {
 | 
			
		||||
        if (contains(summary_queue, process->username) == false) {
 | 
			
		||||
            Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity);
 | 
			
		||||
            enqueue(summary_queue, copy);
 | 
			
		||||
        }
 | 
			
		||||
        process = process->prev_elem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Loop variables
 | 
			
		||||
    int quantum = QUANTUM;
 | 
			
		||||
    int addedJobs = 0;
 | 
			
		||||
    int time = 0;
 | 
			
		||||
	Process *process = NULL;
 | 
			
		||||
 | 
			
		||||
    // Create a queue for the simulation
 | 
			
		||||
    Queue *sim_queue = createQueue();
 | 
			
		||||
 | 
			
		||||
    printf("Time\tJob\n");
 | 
			
		||||
    while (true) {
 | 
			
		||||
        time++;
 | 
			
		||||
		sem_wait(&print_semaphore); // Wait for the print semaphore
 | 
			
		||||
        // 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->arrival_time == time) {
 | 
			
		||||
            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);
 | 
			
		||||
@@ -84,18 +120,18 @@ void* simulation(void *in_queue_void) {
 | 
			
		||||
 | 
			
		||||
        // Begin printing the current job
 | 
			
		||||
        process = sim_queue->end;
 | 
			
		||||
        if (sim_queue->size == 0) { //If there is nothing in sim_queue, print "-"
 | 
			
		||||
            printf("%d\t-\n", time);
 | 
			
		||||
        if (sim_queue->size == 0) { //If there is nothing in sim_queue, put '-' in the print buffer
 | 
			
		||||
            print_buffer[cpu_id] = '-';
 | 
			
		||||
            if (addedJobs == in_queue->size) {
 | 
			
		||||
                break; // If all jobs have been added, and the simulation queue is empty, then we are done
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("%d\t%c\n", time, process->job); // Print the current job
 | 
			
		||||
            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
 | 
			
		||||
                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
 | 
			
		||||
@@ -105,30 +141,39 @@ void* simulation(void *in_queue_void) {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Print the summary
 | 
			
		||||
    printf("\nSummary\n");
 | 
			
		||||
    printList(summary_queue);
 | 
			
		||||
 | 
			
		||||
    // Free memory for the simulation queue. There should be nothing left in it
 | 
			
		||||
    stop(sim_queue);
 | 
			
		||||
 | 
			
		||||
    // We never dequeue from the summary queue, so we don't need to make sure about freeing dequeued processes
 | 
			
		||||
    stop(summary_queue);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    Queue *in_queue = input_queue(); // Create the input queue
 | 
			
		||||
	Queue *print_queue = createQueue(); // Create the print queue
 | 
			
		||||
	Queue *summary_queue = createQueue(); // Create the summary queue
 | 
			
		||||
	char *print_buffer = malloc(sizeof(char) * CPUS); // Create the print buffer
 | 
			
		||||
 | 
			
		||||
	// Summary creation
 | 
			
		||||
	Process *process = in_queue->end;
 | 
			
		||||
	for (int i = 0; i < in_queue->size; ++i) {
 | 
			
		||||
		if (contains(summary_queue, process->username) == false) {
 | 
			
		||||
			Process *copy = createProcess(process->username, process->job, process->arrival_time, process->duration, process->affinity);
 | 
			
		||||
			enqueue(summary_queue, copy);
 | 
			
		||||
		}
 | 
			
		||||
		process = process->prev_elem;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the print thread
 | 
			
		||||
	pthread_t print_thread;
 | 
			
		||||
	pthread_create(&print_thread, NULL, &print, print_queue);
 | 
			
		||||
	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];
 | 
			
		||||
	ThreadArgs* args[CPUS]; // Array of arguments for each thread, so we can free them later
 | 
			
		||||
	for (int i = 0; i < CPUS; i++) {
 | 
			
		||||
		pthread_create(&threads[i], NULL, &simulation, in_queue);
 | 
			
		||||
		args[i] = createArgs(i, print_buffer, summary_queue, in_queue);
 | 
			
		||||
		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
 | 
			
		||||
@@ -136,7 +181,10 @@ int main() {
 | 
			
		||||
	// Just to make sure all threads are done
 | 
			
		||||
	for (int i = 0; i < CPUS; i++) {
 | 
			
		||||
		pthread_join(threads[i], NULL);
 | 
			
		||||
		free(args[i]);
 | 
			
		||||
	}
 | 
			
		||||
    stop(in_queue); // Free memory for input queue
 | 
			
		||||
	stop(summary_queue); // Free memory for summary queue
 | 
			
		||||
	free(print_buffer); // Free memory for print buffer
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user