From 9327437424f50b521ba266deb21b8a96a7ec6945 Mon Sep 17 00:00:00 2001 From: Amber Date: Sun, 21 Feb 2021 21:21:55 -0500 Subject: [PATCH] Initial commit. --- programming-assignment.c | 172 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 programming-assignment.c diff --git a/programming-assignment.c b/programming-assignment.c new file mode 100644 index 0000000..65ccd38 --- /dev/null +++ b/programming-assignment.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include + +/************************************************************************** + * Authors: Gary Fleming, Amber McCloughan + * Class: CIS452 - Operating Systems Concepts + * Professor: Dr. Greg Wolffe + * Date: 2/14/2019 + * + * Program that starts out with a dispatcher thread. This thread + * waits on user input. When it receives a filename string from + * the user, it spawns a worker thread that goes out to + * "retrieve" the filename from the "file server". On an exit, + * the program prints statistics about files serviced. + * + * To end the program, do a Ctrl + C. +***************************************************************************/ + +// Input limit. +#define CHAR_LIMIT 1024 + +// See function implementations for information. +void *file_request(void *arg); +void sigHandler(int); + +// File counter. +int counter; + +// File access time counter. +int timeCounter; + +// Mutex. +pthread_mutex_t lock; + +// Input buffer. +char *input; + +/** + * The main function for driving the program. + */ +int main() +{ + // Seeding randomness. + srand(time(NULL)); + + /* + * Initializing the mutex. + * I figured out how to do this using the following article: + * https://www.geeksforgeeks.org/mutex-lock-for-linux-thread-synchronization/ + */ + pthread_mutex_init(&lock, NULL); + + // Thread ID holder. + pthread_t thread1; + + // Status variable for checking if pthread_create failed. + int status; + + // Initializing file counter. + counter = 0; + + // Allocating memory for input buffer. + input = malloc(CHAR_LIMIT * sizeof(char)); + + // Binding signal handler for keyboard interrupt. + signal(SIGINT, sigHandler); + + // The dispatching loop. + while (1) + { + // User input for filename. + fprintf(stderr, "Enter file name: "); + input = fgets(input, CHAR_LIMIT, stdin); + + // Removing newline character from input. + strtok(input, "\n"); + + // Spawning a thread to deal with the "file" requested. + if ((status = pthread_create(&thread1, NULL, file_request, strdup(input))) != 0) + { + fprintf(stderr, "Thread creation error %d: %s.\n", status, strerror(status)); + exit(1); + } + } + + return 0; +} + +/** + * Function executed by worked threads. Randomly decides + * whether the "file" can be accessed from the disk cache + * (80% chance) or if it has to be fetched from the hard + * drive (20% chance). If the "file" is accessed from cache, + * the thread sleeps for a second. If the "file" is accessed + * from the hard drive, the thread sleeps for 7-10 seconds. + * A mutex is used to ensure mutual exclusion for writes. + * + * @param arg, the name of the "file" to be handled by the + * worker thread. + */ +void *file_request(void *arg) +{ + // Probability roll for HDD or cache. + int val = (rand() % 5) + 1; + + // Variable used for sleep time. + int val2; + + // File accessed from disk. + if (val == 5) + { + // 7-10 seconds. + val2 = (rand() % 4) + 7; + } + // File accessed from cache. + else + { + // 1 second. + val2 = 1; + } + + // Sleep for seconds decided on above. + sleep(val2); + + // Serving the file. + fprintf(stderr, "\nServing file \"%s\" after %i seconds.\n", (char *)arg, val2); + + // Writing to global variables. Mutex lock! + pthread_mutex_lock(&lock); + counter++; + timeCounter += val2; + pthread_mutex_unlock(&lock); + + // Freeing allocated memory. + free(arg); + + // Goodbye (no need to return anything). + return NULL; +} + +/** + * Handler for signals. Bound for the one signal handled + * in this application: SIGINT (program interrupt signal ^C). + * + * @param sigNum, the identifying number of the signal + * sent and now being handled. According to the + * man page for signal, SIGINT = 2. + */ +void sigHandler(int sigNum) +{ + if (sigNum == SIGINT) + { + // Exit message. + printf(" received. That's it, I'm shutting you down...\n"); + printf("Files serviced: %i.\n", counter); + printf("Avg. file access time: %lf seconds.\n", (double)timeCounter / (double)counter); + + // Destroying mutex. + pthread_mutex_destroy(&lock); + + // Freeing user input pointer. + free(input); + + // Exiting program. + exit(0); + } +} \ No newline at end of file