Advertisement
Guest User

Untitled

a guest
May 20th, 2018
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.58 KB | None | 0 0
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <semaphore.h>
  5. #include "so_scheduler.h"
  6.  
  7. #define DIE(assertion, call_description)                \
  8.     do {                                \
  9.         if (assertion) {                    \
  10.             fprintf(stderr, "(%s, %d): ",           \
  11.                     __FILE__, __LINE__);        \
  12.             perror(call_description);           \
  13.             exit(EXIT_FAILURE);             \
  14.         }                           \
  15.     } while (0)
  16.  
  17. #define READY 0
  18. #define RUNNING 1
  19. #define WAITING 2
  20. #define TERMINATED 3
  21.  
  22. #define MAX_LEN 1000000
  23.  
  24. struct my_thread {
  25.     so_handler *func;
  26.     unsigned int priority;
  27.     unsigned int state;
  28.     tid_t id;
  29.     sem_t semaphore;
  30.     unsigned int time_thread;
  31.     unsigned int last_run;
  32.     unsigned int blocking_event;
  33.     unsigned int sort_rule;
  34.     struct my_thread *next;
  35. };
  36.  
  37. int init, global_time;
  38. unsigned int quantum, io_devices;
  39. struct my_thread *queue, *default_thread;
  40.  
  41. void add_thread(struct my_thread *new_thread)
  42. {
  43.     if (queue == NULL) {
  44.         queue = new_thread;
  45.         return;
  46.     }
  47.     /*
  48.      * first element has max priority and min last_run
  49.      */
  50.     struct my_thread *aux = queue;
  51.  
  52.     if (new_thread->sort_rule > queue->sort_rule) {
  53.         new_thread->next = queue;
  54.         queue = new_thread;
  55.     } else {
  56.         /*
  57.          * traverse the list and find a
  58.          * position to insert new my_thread
  59.          */
  60.         while (aux->next != NULL &&
  61.             aux->next->sort_rule >= new_thread->sort_rule) {
  62.             aux = aux->next;
  63.         }
  64.  
  65.         /*
  66.          * either at the ends of the list
  67.          * or at required position
  68.          */
  69.         new_thread->next = aux->next;
  70.         aux->next = new_thread;
  71.     }
  72. }
  73.  
  74. /*
  75.  * get the element from pq with maximum priority
  76.  * but minimum last_run
  77.  */
  78. struct my_thread *get_thread()
  79. {
  80.     struct my_thread *ret = default_thread, *aux = NULL;
  81.     int flag = 0, min_run = global_time + 1;
  82.    
  83.     aux = queue;
  84.     while (aux != NULL) {
  85.         if (aux->state == READY) {
  86.             flag = 1;
  87.             if (min_run > aux->last_run) {
  88.                 min_run = aux->last_run;
  89.                 ret = aux;
  90.             }
  91.         }
  92.         if (aux->next != NULL) {
  93.             if (aux->priority > aux->next->priority && flag == 1)
  94.                 break;
  95.         }
  96.         aux = aux->next;
  97.     }
  98.     return ret;
  99. }
  100.  
  101. /*
  102.  * returns a thread with specified id
  103.  */
  104. struct my_thread *search_thread(tid_t id)
  105. {
  106.     struct my_thread *aux = NULL, *found = default_thread;
  107.     int flag = 0;
  108.  
  109.     aux = queue;
  110.     while (aux != NULL) {
  111.         if (aux->id == id) {
  112.             flag = 1;
  113.             found = aux;
  114.         }
  115.         if (aux->next != NULL) {
  116.             if (aux->priority > aux->next->priority && flag == 1)
  117.                 return found;
  118.         }
  119.         aux = aux->next;
  120.     }
  121.  
  122.     return found;
  123. }
  124. /*
  125.  * Round Robin Algorithm
  126.  */
  127. void schedule(struct my_thread *thread)
  128. {
  129.     global_time++;
  130.     thread->time_thread++;
  131.  
  132.     /*
  133.      * if current overlayed it's time quantum
  134.      * then change it's values
  135.      */
  136.     if (thread->time_thread >= quantum) {
  137.         thread->last_run = global_time;
  138.         thread->time_thread = 0;
  139.         thread->sort_rule =
  140.                 thread->priority * MAX_LEN +
  141.                 MAX_LEN - thread->last_run;
  142.     }
  143.  
  144.     struct my_thread *to_execute = get_thread();
  145.  
  146.     to_execute->state = RUNNING;
  147.     sem_post(&to_execute->semaphore);
  148.  
  149.     if (thread->state != TERMINATED)
  150.         sem_wait(&thread->semaphore);
  151. }
  152.  
  153. /*
  154.  * creates and initializes scheduler
  155.  * + time quantum for each thread
  156.  * + number of IO devices supported
  157.  * returns: 0 on success or negative on error
  158.  */
  159. int so_init(unsigned int time_quantum, unsigned int io)
  160. {
  161.     if (io < 0 || io > SO_MAX_NUM_EVENTS)
  162.         return -1;
  163.     if (io_devices > 0)
  164.         return -1;
  165.     if (time_quantum <= 0)
  166.         return -1;
  167.  
  168.     init++;
  169.     if (init > 1)
  170.         return -1;
  171.  
  172.     quantum = time_quantum;
  173.     io_devices = io;
  174.     queue = NULL;
  175.  
  176.     default_thread = malloc(sizeof(struct my_thread));
  177.     DIE(default_thread == NULL, "malloc\n");
  178.  
  179.     default_thread->priority = 0;
  180.     default_thread->state = READY;
  181.     default_thread->id = pthread_self();
  182.     sem_init(&default_thread->semaphore, 0, 0);
  183.     default_thread->time_thread = 0;
  184.     default_thread->last_run = global_time;
  185.     default_thread->blocking_event = -1;
  186.     default_thread->sort_rule = 0;
  187.     default_thread->next = NULL;
  188.  
  189.     return 0;
  190. }
  191.  
  192. void *start_thread(void *arg)
  193. {
  194.     struct my_thread *aux = (struct my_thread *) arg;
  195.  
  196.     so_handler *func = aux->func;
  197.     unsigned int priority = aux->priority;
  198.  
  199.     sem_wait(&aux->semaphore);
  200.     func(priority);
  201.     aux->state = TERMINATED;
  202.     schedule(aux);
  203.     return NULL;
  204. }
  205.  
  206. /*
  207.  * creates a new so_task_t and runs it according to the scheduler
  208.  * + handler function
  209.  * + priority
  210.  * returns: tid of the new task if successful or INVALID_TID
  211.  */
  212. tid_t so_fork(so_handler *func, unsigned int priority)
  213. {
  214.     if (func == NULL)
  215.         return INVALID_TID;
  216.  
  217.     if (priority > SO_MAX_PRIO)
  218.         return INVALID_TID;
  219.  
  220.     if (io_devices < 0)
  221.         return INVALID_TID;
  222.  
  223.     int rc;
  224.     struct my_thread *current_thread = NULL;
  225.  
  226.     current_thread = malloc(sizeof(struct my_thread));
  227.     DIE(current_thread == NULL, "malloc\n");
  228.  
  229.     current_thread->func = func;
  230.     current_thread->priority = priority;
  231.     current_thread->state = READY;
  232.     sem_init(&current_thread->semaphore, 0, 0);
  233.     current_thread->time_thread = 0;
  234.     current_thread->last_run = global_time;
  235.     current_thread->blocking_event = -1;
  236.     current_thread->sort_rule =
  237.                 current_thread->priority * MAX_LEN +
  238.                 MAX_LEN - current_thread->last_run;
  239.     current_thread->next = NULL;
  240.  
  241.     rc = pthread_create(&current_thread->id, NULL,
  242.         start_thread, current_thread);
  243.     DIE(rc != 0, "pthread_create");
  244.  
  245.     add_thread(current_thread);
  246.     so_exec();
  247.     return current_thread->id;
  248. }
  249.  
  250. /*
  251.  * waits for an IO device
  252.  * + device index
  253.  * returns: -1 if the device does not exist or 0 on success
  254.  */
  255. int so_wait(unsigned int io)
  256. {
  257.     if (io_devices < 0 || io >= io_devices)
  258.         return -1;
  259.  
  260.     struct my_thread *wait_thread = default_thread;
  261.  
  262.     wait_thread = search_thread(pthread_self());
  263.  
  264.     wait_thread->state = WAITING;
  265.     wait_thread->blocking_event = io;
  266.     schedule(wait_thread);
  267.  
  268.     return 0;
  269. }
  270.  
  271. /*
  272.  * signals an IO device
  273.  * + device index
  274.  * return the number of tasks woke or -1 on error
  275.  */
  276. int so_signal(unsigned int io)
  277. {
  278.     if (io_devices < 0 || io >= io_devices)
  279.         return -1;
  280.  
  281.     int woke = 0;
  282.  
  283.     for (struct my_thread *aux = queue; aux != NULL; aux = aux->next) {
  284.         if (aux->state == WAITING
  285.             && aux->blocking_event == io) {
  286.             aux->state = READY;
  287.             woke++;
  288.         }
  289.     }
  290.  
  291.     so_exec();
  292.     return woke;
  293. }
  294.  
  295. /*
  296.  * does whatever operation
  297.  */
  298. void so_exec(void)
  299. {
  300.     struct my_thread *exec_thread
  301.         = search_thread(pthread_self());
  302.     exec_thread->state = READY;
  303.     schedule(exec_thread);
  304. }
  305.  
  306. /*
  307.  * destroys a scheduler
  308.  */
  309. void so_end(void)
  310. {
  311.     int rc;
  312.     struct my_thread *q = queue;
  313.  
  314.     init = 0;
  315.     sem_destroy(&default_thread->semaphore);
  316.     while (q != NULL) {
  317.         rc = pthread_join(q->id, NULL);
  318.         DIE(rc == -1, "pthread_join");
  319.         sem_destroy(&q->semaphore);
  320.         q = q->next;
  321.     }
  322. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement