Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pthread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <semaphore.h>
- #include "so_scheduler.h"
- #define DIE(assertion, call_description) \
- do { \
- if (assertion) { \
- fprintf(stderr, "(%s, %d): ", \
- __FILE__, __LINE__); \
- perror(call_description); \
- exit(EXIT_FAILURE); \
- } \
- } while (0)
- #define READY 0
- #define RUNNING 1
- #define WAITING 2
- #define TERMINATED 3
- #define MAX_LEN 1000000
- struct my_thread {
- so_handler *func;
- unsigned int priority;
- unsigned int state;
- tid_t id;
- sem_t semaphore;
- unsigned int time_thread;
- unsigned int last_run;
- unsigned int blocking_event;
- unsigned int sort_rule;
- struct my_thread *next;
- };
- int init, global_time;
- unsigned int quantum, io_devices;
- struct my_thread *queue, *default_thread;
- void add_thread(struct my_thread *new_thread)
- {
- if (queue == NULL) {
- queue = new_thread;
- return;
- }
- /*
- * first element has max priority and min last_run
- */
- struct my_thread *aux = queue;
- if (new_thread->sort_rule > queue->sort_rule) {
- new_thread->next = queue;
- queue = new_thread;
- } else {
- /*
- * traverse the list and find a
- * position to insert new my_thread
- */
- while (aux->next != NULL &&
- aux->next->sort_rule >= new_thread->sort_rule) {
- aux = aux->next;
- }
- /*
- * either at the ends of the list
- * or at required position
- */
- new_thread->next = aux->next;
- aux->next = new_thread;
- }
- }
- /*
- * get the element from pq with maximum priority
- * but minimum last_run
- */
- struct my_thread *get_thread()
- {
- struct my_thread *ret = default_thread, *aux = NULL;
- int flag = 0, min_run = global_time + 1;
- aux = queue;
- while (aux != NULL) {
- if (aux->state == READY) {
- flag = 1;
- if (min_run > aux->last_run) {
- min_run = aux->last_run;
- ret = aux;
- }
- }
- if (aux->next != NULL) {
- if (aux->priority > aux->next->priority && flag == 1)
- break;
- }
- aux = aux->next;
- }
- return ret;
- }
- /*
- * returns a thread with specified id
- */
- struct my_thread *search_thread(tid_t id)
- {
- struct my_thread *aux = NULL, *found = default_thread;
- int flag = 0;
- aux = queue;
- while (aux != NULL) {
- if (aux->id == id) {
- flag = 1;
- found = aux;
- }
- if (aux->next != NULL) {
- if (aux->priority > aux->next->priority && flag == 1)
- return found;
- }
- aux = aux->next;
- }
- return found;
- }
- /*
- * Round Robin Algorithm
- */
- void schedule(struct my_thread *thread)
- {
- global_time++;
- thread->time_thread++;
- /*
- * if current overlayed it's time quantum
- * then change it's values
- */
- if (thread->time_thread >= quantum) {
- thread->last_run = global_time;
- thread->time_thread = 0;
- thread->sort_rule =
- thread->priority * MAX_LEN +
- MAX_LEN - thread->last_run;
- }
- struct my_thread *to_execute = get_thread();
- to_execute->state = RUNNING;
- sem_post(&to_execute->semaphore);
- if (thread->state != TERMINATED)
- sem_wait(&thread->semaphore);
- }
- /*
- * creates and initializes scheduler
- * + time quantum for each thread
- * + number of IO devices supported
- * returns: 0 on success or negative on error
- */
- int so_init(unsigned int time_quantum, unsigned int io)
- {
- if (io < 0 || io > SO_MAX_NUM_EVENTS)
- return -1;
- if (io_devices > 0)
- return -1;
- if (time_quantum <= 0)
- return -1;
- init++;
- if (init > 1)
- return -1;
- quantum = time_quantum;
- io_devices = io;
- queue = NULL;
- default_thread = malloc(sizeof(struct my_thread));
- DIE(default_thread == NULL, "malloc\n");
- default_thread->priority = 0;
- default_thread->state = READY;
- default_thread->id = pthread_self();
- sem_init(&default_thread->semaphore, 0, 0);
- default_thread->time_thread = 0;
- default_thread->last_run = global_time;
- default_thread->blocking_event = -1;
- default_thread->sort_rule = 0;
- default_thread->next = NULL;
- return 0;
- }
- void *start_thread(void *arg)
- {
- struct my_thread *aux = (struct my_thread *) arg;
- so_handler *func = aux->func;
- unsigned int priority = aux->priority;
- sem_wait(&aux->semaphore);
- func(priority);
- aux->state = TERMINATED;
- schedule(aux);
- return NULL;
- }
- /*
- * creates a new so_task_t and runs it according to the scheduler
- * + handler function
- * + priority
- * returns: tid of the new task if successful or INVALID_TID
- */
- tid_t so_fork(so_handler *func, unsigned int priority)
- {
- if (func == NULL)
- return INVALID_TID;
- if (priority > SO_MAX_PRIO)
- return INVALID_TID;
- if (io_devices < 0)
- return INVALID_TID;
- int rc;
- struct my_thread *current_thread = NULL;
- current_thread = malloc(sizeof(struct my_thread));
- DIE(current_thread == NULL, "malloc\n");
- current_thread->func = func;
- current_thread->priority = priority;
- current_thread->state = READY;
- sem_init(¤t_thread->semaphore, 0, 0);
- current_thread->time_thread = 0;
- current_thread->last_run = global_time;
- current_thread->blocking_event = -1;
- current_thread->sort_rule =
- current_thread->priority * MAX_LEN +
- MAX_LEN - current_thread->last_run;
- current_thread->next = NULL;
- rc = pthread_create(¤t_thread->id, NULL,
- start_thread, current_thread);
- DIE(rc != 0, "pthread_create");
- add_thread(current_thread);
- so_exec();
- return current_thread->id;
- }
- /*
- * waits for an IO device
- * + device index
- * returns: -1 if the device does not exist or 0 on success
- */
- int so_wait(unsigned int io)
- {
- if (io_devices < 0 || io >= io_devices)
- return -1;
- struct my_thread *wait_thread = default_thread;
- wait_thread = search_thread(pthread_self());
- wait_thread->state = WAITING;
- wait_thread->blocking_event = io;
- schedule(wait_thread);
- return 0;
- }
- /*
- * signals an IO device
- * + device index
- * return the number of tasks woke or -1 on error
- */
- int so_signal(unsigned int io)
- {
- if (io_devices < 0 || io >= io_devices)
- return -1;
- int woke = 0;
- for (struct my_thread *aux = queue; aux != NULL; aux = aux->next) {
- if (aux->state == WAITING
- && aux->blocking_event == io) {
- aux->state = READY;
- woke++;
- }
- }
- so_exec();
- return woke;
- }
- /*
- * does whatever operation
- */
- void so_exec(void)
- {
- struct my_thread *exec_thread
- = search_thread(pthread_self());
- exec_thread->state = READY;
- schedule(exec_thread);
- }
- /*
- * destroys a scheduler
- */
- void so_end(void)
- {
- int rc;
- struct my_thread *q = queue;
- init = 0;
- sem_destroy(&default_thread->semaphore);
- while (q != NULL) {
- rc = pthread_join(q->id, NULL);
- DIE(rc == -1, "pthread_join");
- sem_destroy(&q->semaphore);
- q = q->next;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement