Advertisement
candale

DOS - Threads And Sync

Nov 18th, 2013
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.94 KB | None | 0 0
  1. /*
  2. Implement a program that satisfies the requirements below.
  3.  
  4. 1. Reads from the console a number E of elements and a number W of
  5.    threads (we will call them workers). (1p) DONE
  6.  
  7. 2. Generates a linked list using the structure below containing E
  8.    elements and populates the "value" fields with random numbers. (2p) DONE
  9.  
  10. 3. Populates the "worker" fields with values between 0 and W-1, so that
  11.    the difference between the number of elements of each worker is at
  12.    most 1, basically trying to distribute the work evenly among
  13.    workers) (1p) DONE
  14.  
  15. 4. Creates W worker threads, each given its creation order number. Each
  16.    worker will continuously parse the linked list and for the elements
  17.    belonging to it (match the worker's order number with the elem
  18.    "worker" field) will replace the value with its square root. (2p)
  19.  
  20. 5. The main thread of the program will be signaled to wake up from
  21.    waiting whenever 5 elements or all the elements left in the list
  22.    (if less than 5) have their value less than 2. Upon waking up, the
  23.    main thread eliminates the elements with values less than 2. The
  24.    program stops when the list is empty. (2p)
  25.  
  26. 6. No more than 3 workers can access the linked list at the same
  27.    time. (2p)
  28.  
  29. struct elem {
  30.     int value;
  31.     int worker;
  32.     struct elem* next;
  33. };
  34. */
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <pthread.h>
  39. #include <fcntl.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <string.h>
  43. #include <semaphore.h>
  44. #include <math.h>
  45.  
  46. struct elem {
  47.     int value;
  48.     int worker;
  49.     struct elem* next;
  50. };
  51.  
  52. struct elem* root;
  53. pthread_mutex_t flg_mtx;
  54. pthread_mutex_t main_mtx;
  55. pthread_cond_t cond;
  56. pthread_rwlock_t rwl;
  57. sem_t sem;
  58. int fiveFlg;
  59. int doneFlg;
  60.  
  61. void printList(struct elem* root) {
  62.     while(root != NULL) {
  63.         printf("W %d V %d --> ", root->worker, root->value);
  64.         root = root->next;
  65.     }
  66.     printf("\n");
  67. }
  68.  
  69. struct elem* createList(int numE, int numW) {
  70.     int i;
  71.     struct elem* aux = NULL;
  72.     for(i = 0; i < numE; i++) {
  73.         struct elem* e = (struct elem*)malloc(sizeof(struct elem));
  74.         e->value  = rand() % 200;
  75.         e->worker = i % numW;
  76.         e->next = aux;
  77.         aux = e;
  78.     }
  79.  
  80.     return aux;
  81. }
  82.  
  83. void deleteNodes() {
  84.     struct elem * e = NULL;
  85.     struct elem * ee = NULL;
  86.     struct elem * aux = NULL;
  87.     e = root;
  88.     while(e != NULL) {
  89.         if(e->value < 2) {
  90.             if(ee != NULL) {
  91.                 ee->next = e->next;
  92.                 aux = e;
  93.                 e = e->next;
  94.                 free(aux);
  95.             } else {
  96.                 aux = e;
  97.                 e = e->next;
  98.                 root = root->next;
  99.                 free(aux);
  100.             }
  101.         } else {
  102.             ee =  e;
  103.             e  = e->next;
  104.         }
  105.     }
  106. }
  107.  
  108. void * worker(void * wNum) {
  109.     int self = *(int *)wNum;
  110.     struct elem* aux;
  111.     int ok = 1;
  112.    
  113.     printf("!!!Started thread number: %d\n", self);
  114.    
  115.     while(ok == 1) {
  116.         ok  = 0;
  117.         aux = root;
  118.                
  119.         sem_wait(&sem);
  120.         while(aux != NULL) {
  121.                 if(aux->worker == self && aux->value >= 2) {
  122.                     ok = 1;
  123.  
  124.                     aux->value = (int)sqrt(aux->value);
  125.                     //printf("Worker number: %d changed node value to: %d\n", self, aux->value);
  126.                
  127.                     if(aux->value < 2) {
  128.                         printf("!!!Trying to get mutex for worker %d...\n", self);
  129.                         pthread_mutex_lock(&flg_mtx);
  130.                         printf("Thread %d: changed value to: %d (incrementing flag...)\n", self, aux->value);
  131.                         fiveFlg ++;        
  132.                        
  133.                         if(fiveFlg == 5) {
  134.                             printf("!!!Signaled Main!!!\n");
  135.                             pthread_mutex_unlock(&flg_mtx);
  136.                             pthread_cond_signal(&cond);
  137.                             break;
  138.                         } else {
  139.                             pthread_mutex_unlock(&flg_mtx);
  140.                         }
  141.                     }
  142.                 }
  143.                 aux = aux->next;
  144.         }
  145.  
  146.         sem_post(&sem);
  147.     }
  148.    
  149.  
  150.     aux = root;
  151.     ok = 1;
  152.     if(aux != NULL){
  153.         while(aux != NULL) {
  154.             if(aux->value >= 2) {
  155.                 ok = 0;
  156.             }
  157.             aux = aux->next;
  158.         }
  159.    
  160.    
  161.         if(ok == 1) {
  162.             printf("!!!Sent last signal to main\n");
  163.             fiveFlg = 5;
  164.             pthread_cond_signal(&cond);
  165.         }
  166.     }
  167.    
  168.     return NULL;
  169. }
  170.  
  171. void initialiseSync() {
  172.     if(0 > sem_init(&sem, 0, 3)) {
  173.         printf("Failed to create semaphre\n");
  174.         exit(1);
  175.     }
  176.     if(pthread_mutex_init(&flg_mtx, NULL) != 0) {
  177.         printf("Failed to initialise the flag mutex\n");
  178.         exit(1);
  179.     }
  180.     if(pthread_rwlock_init(&rwl, NULL) != 0) {
  181.         printf("Failed to initialise rwlock\n");
  182.         exit(1);
  183.     }
  184.     if(pthread_cond_init(&cond, NULL) != 0) {
  185.         printf("Failed to initialise conditional variable\n");
  186.         exit(1);
  187.     }
  188.  
  189. }
  190.  
  191. void destroySync() {
  192.     sem_destroy(&sem); 
  193.     pthread_mutex_destroy(&flg_mtx);
  194.     pthread_cond_destroy(&cond);
  195. }
  196.  
  197. int main(int argc, char * argv[]) {
  198.  
  199.     if(argc != 3) {
  200.         printf("Two parameters must be supplied!\n");
  201.         exit(1);
  202.     }
  203.    
  204.     int numE, numW;
  205.     int i;
  206.     numE = atoi(argv[1]);
  207.     numW = atoi(argv[2]);
  208.     int wrkNums[numW];
  209.     pthread_t threads[numW];
  210.     root = NULL;
  211.     fiveFlg = 0;
  212.     doneFlg = 0;
  213.  
  214.     printf("!!!Number of elements: %d  Number of threads: %d\n\n", numE, numW);
  215.     srand(time(NULL));
  216.    
  217.     initialiseSync();
  218.  
  219.    
  220.     root = createList(numE, numW);
  221.     printList(root);
  222.    
  223.     printf("!!!Creating threads...\n");
  224.     for(i = 0; i < numW && i < numE; i++) {
  225.         wrkNums[i] = i;
  226.         pthread_create(&threads[i], NULL, worker, &wrkNums[i]);
  227.     }
  228.     printf("!!!Threads created successfully\n");
  229.    
  230.     printf("!!!Trying to get the mutex in MAIN...\n");
  231.     pthread_mutex_lock(&flg_mtx);
  232.     while(root != NULL) {
  233.         printf("!!!Main is waiting for flag\n");       
  234.         pthread_cond_wait(&cond, &flg_mtx);
  235.  
  236.         printf("!!!Main got flag. Deleting nodes...\n");
  237.         printList(root);
  238.        
  239.         deleteNodes();
  240.        
  241.         fiveFlg = 0;
  242.         pthread_mutex_unlock(&flg_mtx);
  243.         printf("!!!Done deleting nodes\n");
  244.         printList(root);
  245.     }  
  246.  
  247.     printf("!!!Waiting for threads...\n");
  248.     for(i = 0; i < numW && i < numE; i++) {
  249.         pthread_join(threads[i], NULL);
  250.     }
  251.     printf("!!!Done waiting. Terminating...\n");
  252.     printList(root);
  253.    
  254.     destroySync();
  255.  
  256.     return 0;
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement