Advertisement
Guest User

Untitled

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