Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Dumitrache Adrian 332CA
- * Tema4 SO
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h>
- #include "so_scheduler.h"
- #include <semaphore.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 RESET 0
- #define MAX_LAST 10000000
- struct my_thread{
- so_handler *func;
- unsigned int priority;
- unsigned int state;
- tid_t id;
- sem_t semaphore;
- unsigned int thread_time;
- unsigned int last_run;
- unsigned int blocking_event;
- unsigned int sort_rule;
- struct my_thread *next;
- };
- int global_time;
- int time_q = -1;
- int io_dev = -1;
- int rc = 1, i;
- int init;
- unsigned long int ids[1000000];
- int count;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- struct my_thread *priority_queue;
- struct my_thread *default_thread;
- /*
- * add a new thread to priority_queue
- */
- void add_thread(struct my_thread *new_thread)
- {
- if (priority_queue == NULL) {
- priority_queue = new_thread;
- return;
- }
- // first element has max priority and min last_run
- struct my_thread *aux = priority_queue;
- if (new_thread->sort_rule > priority_queue->sort_rule) {
- new_thread->next = priority_queue;
- priority_queue = new_thread;
- } else {
- // Traverse the list and find a
- // position to insert new node
- 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;
- }
- }
- /*
- * return the element with max priority and min last_run
- */
- struct my_thread *get_thread()
- {
- struct my_thread *aux = priority_queue;
- if (aux == NULL)
- return default_thread;
- priority_queue = priority_queue->next;
- return aux;
- }
- /*
- * search a thread by it's id or default if it doesn't exists
- * in priority queue
- */
- struct my_thread *search_thread(tid_t id)
- {
- struct my_thread *aux;
- aux = priority_queue;
- while (aux != NULL) {
- if (aux->id == id)
- return aux;
- aux = aux->next;
- }
- return default_thread;
- }
- /*
- * 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_dev > 0)
- return -1;
- if (time_quantum <= 0)
- return -1;
- init++;
- if (init > 1)
- return -1;
- io_dev = io;
- time_q = time_quantum;
- priority_queue = NULL;
- default_thread = malloc(sizeof(struct my_thread));
- DIE(default_thread == NULL, "my_thread malloc\n");
- default_thread->priority = 0;
- default_thread->state = READY;
- sem_init(&default_thread->semaphore, 0, 0);
- default_thread->thread_time = RESET;
- default_thread->last_run = global_time;
- default_thread->blocking_event = -1;
- default_thread->sort_rule = 0;
- default_thread->next = NULL;
- default_thread->id = pthread_self();
- printf("id init = %lu\n", pthread_self());
- return 0;
- }
- void schedule(struct my_thread *current_thread)
- {
- global_time++;
- current_thread->thread_time++;
- if (current_thread->thread_time >= time_q) {
- printf("schedule: time quantum of %lu expired\n", current_thread->id);
- current_thread->thread_time = RESET;
- current_thread->last_run = global_time;
- current_thread->state = READY;
- add_thread(current_thread);
- }
- struct my_thread *to_exec = NULL;
- to_exec = get_thread();
- to_exec->state = RUNNING;
- printf("schedule: unlock %lu\n", to_exec->id);
- sem_post(&to_exec->semaphore);
- printf("schedule: current_thread->id = %lu\n", current_thread->id);
- printf("schedule: to_exec->id = %lu\n", to_exec->id);
- printf("schedule: current_thread->state = %d\n", current_thread->state);
- if (current_thread->state != TERMINATED) {
- printf("schedule: lock %lu\n", current_thread->id);
- sem_wait(¤t_thread->semaphore);
- printf("schedule: AM TRECUT DE WAIT!\n");
- }
- }
- void *start_thread(void *args)
- {
- struct my_thread *current_thread = ((struct my_thread *) args);
- so_handler *func = current_thread->func;
- unsigned int priority = current_thread->priority;
- printf("start-thread: lock %lu\n", current_thread->id);
- sem_wait(¤t_thread->semaphore);
- func(priority);
- printf("start-thread: unlock %lu\n", current_thread->id);
- current_thread->state = TERMINATED;
- schedule(current_thread);
- printf("start_thread: return NULL\n");
- 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 || priority > SO_MAX_PRIO || io_dev < 0)
- return INVALID_TID;
- struct my_thread *current_thread = malloc(sizeof(struct my_thread));
- DIE(current_thread == NULL, "my_thread malloc\n");
- current_thread->func = func;
- current_thread->priority = priority;
- current_thread->state = READY;
- sem_init(¤t_thread->semaphore, 0, 0);
- current_thread->thread_time = RESET;
- current_thread->last_run = global_time;
- current_thread->blocking_event = -1;
- current_thread->sort_rule =
- current_thread->priority * MAX_LAST +
- MAX_LAST - current_thread->last_run;
- current_thread->next = NULL;
- rc = pthread_create(¤t_thread->id,
- NULL,
- &start_thread,
- current_thread);
- DIE(rc != 0, "bad pthread_create\n");
- printf("fork: created thread %lu\n", current_thread->id);
- pthread_mutex_lock(&mutex);
- add_thread(current_thread);
- ids[count] = current_thread->id;
- count++;
- pthread_mutex_unlock(&mutex);
- printf("fork: added %lu to list\n", current_thread->id);
- so_exec();
- printf("fork: end\n");
- 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_dev < 0 || io >= io_dev)
- return -1;
- struct my_thread *device_thread =
- search_thread(pthread_self());
- device_thread->state = WAITING;
- device_thread->blocking_event = io;
- schedule(device_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_dev < 0 || io >= io_dev)
- return -1;
- int woke = 0;
- // iterez pq, daca elem->event == io && elem->state == WAITING
- // elem->state = READY
- struct my_thread *aux;
- aux = priority_queue;
- while (aux->next != NULL) {
- if (aux->state == WAITING && aux->blocking_event == io) {
- aux->state = READY;
- woke++;
- }
- 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 = NULL;
- exec_thread = search_thread(pthread_self());
- printf("start exec %lu\n", exec_thread->id);
- exec_thread->state = READY;
- schedule(exec_thread);
- printf("end exec %lu\n", exec_thread->id);
- }
- /*
- * destroys a scheduler
- */
- void so_end(void)
- {
- init = 0;
- // io_dev = -1;
- // time_q = -1;
- /*for (i = 0; i < count; i++) {
- printf("end: JOIN %lu\n", ids[i]);
- rc = pthread_join(ids[i], NULL);
- DIE(rc != 0, "pthread_join\n");
- }*/
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement