Advertisement
a2r

deadlock stack

a2r
Aug 3rd, 2013
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.44 KB | None | 0 0
  1. /*cflags = -Wall -Werror -ansi -pedantic -D_POSIX_C_SOURCE=200809L -pthread -lrt*/
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <pthread.h>
  7. #include <semaphore.h>
  8. #include <unistd.h>
  9. #include <signal.h>
  10.  
  11.  
  12. #define THREAD_A 0
  13. #define THREAD_B 1
  14.  
  15.  
  16. enum STATUS {LAZY, WAITING, USE};
  17.  
  18.  
  19. pthread_t threads[2];
  20. enum STATUS thread_status[2];
  21.  
  22.  
  23. sem_t resources;
  24. sem_t mutex;
  25.  
  26.  
  27. /*counter for detecting wether A or B was working more often*/
  28. int balance;
  29.  
  30. /*declaration*/
  31. void *thread_function(void *);
  32. void freetime(int, char);
  33. void deadlock_detection(void);
  34. void abortion(int sig);
  35. void resolve_deadlock();
  36.  
  37.  
  38.  
  39.  
  40. int main (void) {
  41.  
  42.  
  43.     int id_a = THREAD_A;
  44.     int id_b = THREAD_B;
  45.  
  46.  
  47.     /*registrating signal-handler*/
  48.     struct sigaction action;
  49.     action.sa_handler = &abortion;
  50.     action.sa_flags = 0;
  51.     sigemptyset(&action.sa_mask);
  52.  
  53.     if (sigaction(SIGINT, &action, NULL) == -1) {
  54.         perror("set actionhandler\n");
  55.         exit(EXIT_FAILURE);
  56.     }
  57.  
  58.  
  59.    
  60.     thread_status[THREAD_A] = LAZY;
  61.     thread_status[THREAD_B] = LAZY;
  62.  
  63.  
  64.     /*Initializing semaphores*/
  65.     if(sem_init(&resources, 0, 2) == -1)
  66.     {
  67.         perror("Init resources-Semaphore\n");
  68.         exit(EXIT_FAILURE);
  69.     }
  70.     if(sem_init(&mutex, 0, 1) == -1)
  71.     {
  72.         perror("Init mutex-Semaphore\n");
  73.         exit(EXIT_FAILURE);
  74.     }
  75.  
  76.  
  77.  
  78.     /*starting threads*/
  79.     if (pthread_create(&threads[THREAD_A], NULL, &thread_function, (void *) &id_a) != 0) {
  80.         perror("Create THREAD_A\n");
  81.         exit(EXIT_FAILURE);
  82.     }
  83.  
  84.     if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) {
  85.         perror("Create THREAD_B\n");
  86.         exit(EXIT_FAILURE);
  87.     }
  88.  
  89.  
  90.  
  91.     deadlock_detection();
  92.  
  93.  
  94.     return 0;
  95. }
  96.  
  97.  
  98.  
  99.  
  100.  
  101. void *thread_function(void *id) {
  102.  
  103.  
  104.     int thread = *((int *) id);
  105.     char c = (thread == THREAD_A) ? 'A' : 'B';
  106.  
  107.  
  108.     /*thread b starts a little later*/
  109.     if (thread == THREAD_B) {
  110.         sleep(4);
  111.     }
  112.  
  113.  
  114.     printf("Thread_%c: Started.\n", c);
  115.  
  116.  
  117.     while (1) {
  118.  
  119.         printf("Thread_%c: Let's see if a resource is available.\n", c);
  120.  
  121.         sem_wait(&resources);
  122.  
  123.         printf("Thread_%c: Now I have a resource.\n", c);
  124.  
  125.          sem_wait(&mutex);
  126.          if(thread == THREAD_A)
  127.          {
  128.             thread_status[THREAD_A] = WAITING;
  129.          }else if (thread == THREAD_B)
  130.          {
  131.             thread_status[THREAD_B] = WAITING;
  132.          }
  133.          sem_post(&mutex);
  134.  
  135.          /*thread a needs 1 second to get to the next resource, thread b needs a little longer*/
  136.          if(thread == THREAD_A)
  137.          {
  138.             sleep(1);
  139.          }else if (thread == THREAD_B)
  140.          {
  141.             sleep(3);
  142.          }
  143.  
  144.         printf("Thread_%c: Let's see if the second resource is also available.\n", c);
  145.  
  146.  
  147.         sem_wait(&resources);
  148.  
  149.         printf("Thread_%c: Now I have both resources and I can start working!\n", c);
  150.  
  151.         /*if a thread has both resources, he can start working*/
  152.          sem_wait(&mutex);
  153.          if(thread == THREAD_A)
  154.          {
  155.             thread_status[THREAD_A] = USE;
  156.             balance++;
  157.          }else if (thread == THREAD_B)
  158.          {
  159.             thread_status[THREAD_B] = USE;
  160.             balance--;
  161.          }
  162.          sem_post(&mutex);
  163.  
  164.          /*working needs 5 sec*/
  165.         sleep(5);
  166.  
  167.         printf("Thread_%c: My work is done, I will free my resources!\n", c);
  168.  
  169.         /*when work is done both resources can be freed*/
  170.         sem_post(&resources);
  171.         sem_post(&resources);
  172.  
  173.         /*and the thread who worked rests for a while*/
  174.          sem_wait(&mutex);
  175.          if(thread == THREAD_A)
  176.          {
  177.             thread_status[THREAD_A] = LAZY;
  178.          }else if (thread == THREAD_B)
  179.          {
  180.             thread_status[THREAD_B] = LAZY;
  181.          }
  182.          sem_post(&mutex);
  183.  
  184.  
  185.         freetime(thread, c);
  186.     }
  187.  
  188.    
  189.     pthread_exit(NULL);
  190. }
  191.  
  192.  
  193.  
  194. void freetime(int thread, char c) {
  195.     static int i = 0;
  196.  
  197.     if (thread == THREAD_A) {
  198.         printf("Thread_%c: I will now sleep for 5 seconds!\n", c);
  199.         sleep(5);
  200.     } else {
  201.         if ((5 - i) < 0) {
  202.             i = 0;
  203.         }
  204.         printf("Thread_%c: I will sleep now . I will be back in %d seconds !\n", c, 5 - i);
  205.         sleep(5 - i);
  206.         i += 3;
  207.   }
  208. }
  209.  
  210. /*the detection is executed every 8 seconds, when both threads are waiting a deadlock occured*/
  211. void deadlock_detection(void) {
  212.     while (1) {
  213.         sleep(8);
  214.  
  215.  
  216.         sem_wait(&mutex);
  217.         if(thread_status[THREAD_A] == WAITING && thread_status[THREAD_B] == WAITING)
  218.         {
  219.             printf("DEADLOCK: Both threads are waiting for a resource!\n");
  220.             resolve_deadlock();
  221.         }
  222.         sem_post(&mutex);
  223.  
  224.     }
  225. }
  226.  
  227. /*for resolving the deadlock, kill the thread who worked more often, and then restart it*/
  228. void resolve_deadlock()
  229. {  
  230.     void *pthread_exit_state;
  231.     int id_a = THREAD_A;
  232.     int id_b = THREAD_B;
  233.    
  234.     /*A worked more often*/
  235.     if(balance >= 0)
  236.     {
  237.         /*kill A*/
  238.          if(pthread_cancel(threads[THREAD_A]) != 0)
  239.         {
  240.             perror("Cancel THREAD_A-Thread\n");
  241.             exit(EXIT_FAILURE);
  242.         }
  243.    
  244.         if(pthread_join(threads[THREAD_A], &pthread_exit_state) != 0)
  245.         {
  246.             perror("Join THREAD_A-Thread\n");
  247.             exit(EXIT_FAILURE);
  248.         }
  249.        
  250.         if(pthread_exit_state == PTHREAD_CANCELED)
  251.         {
  252.             printf("THREAD_A-Thread canceled\n");
  253.         }else
  254.         {
  255.             printf("THREAD_A-Thread wasn't canceled\n");
  256.         }
  257.  
  258.         sem_post(&resources);
  259.        
  260.         /*restart A*/
  261.         if (pthread_create(&threads[THREAD_A], NULL, &thread_function, (void *) &id_a) != 0) {
  262.             perror("Create THREAD_A\n");
  263.             exit(EXIT_FAILURE);
  264.         }
  265.        
  266.     }else
  267.     {
  268.         /*same goes for B*/
  269.         if(pthread_cancel(threads[THREAD_B]) != 0)
  270.         {
  271.             perror("Cancel THREAD_B-Thread\n");
  272.             exit(EXIT_FAILURE);
  273.         }
  274.    
  275.         if(pthread_join(threads[THREAD_B], &pthread_exit_state) != 0)
  276.         {
  277.             perror("Join THREAD_B-Thread\n");
  278.             exit(EXIT_FAILURE);
  279.         }
  280.  
  281.         if(pthread_exit_state == PTHREAD_CANCELED)
  282.         {
  283.             printf("THREAD_B-Thread canceled\n");
  284.         }else
  285.         {
  286.             printf("THREAD_B-Thread wasn't canceled\n");
  287.         }
  288.  
  289.         sem_post(&resources);
  290.        
  291.         if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) {
  292.             perror("Create THREAD_B\n");
  293.             exit(EXIT_FAILURE);
  294.         }
  295.     }
  296. }
  297.  
  298.  
  299.  
  300. /*for CTRL+C - free all resources and exit*/
  301. void abortion(int sig) {
  302.  
  303.  
  304.     void *pthread_exit_state;
  305.    
  306.     printf(" ===> ABORT <===\n");
  307.    
  308.  
  309.     if(sem_destroy(&resources) == -1)
  310.     {
  311.         perror("Destroy resource-Semaphore\n");
  312.         exit(EXIT_FAILURE);    
  313.     }
  314.     if(sem_destroy(&mutex) == -1)
  315.     {
  316.         perror("Destroy mutex-Semaphore\n");
  317.         exit(EXIT_FAILURE);    
  318.     }
  319.    
  320.  
  321.     if(pthread_cancel(threads[THREAD_A]) != 0)
  322.     {
  323.         perror("Cancel THREAD_A-Thread\n");
  324.         exit(EXIT_FAILURE);
  325.     }
  326.    
  327.     if(pthread_join(threads[THREAD_A], &pthread_exit_state) != 0)
  328.     {
  329.         perror("Join THREAD_A-Thread\n");
  330.         exit(EXIT_FAILURE);
  331.     }
  332.  
  333.     if(pthread_exit_state == PTHREAD_CANCELED)
  334.     {
  335.         printf("THREAD_A-Thread canceled\n");
  336.     }else
  337.     {
  338.         printf("THREAD_A-Thread wasn't canceled\n");
  339.     }
  340.  
  341.    
  342.     if(pthread_cancel(threads[THREAD_B]) != 0)
  343.     {
  344.         perror("Cancel THREAD_B-Thread\n");
  345.         exit(EXIT_FAILURE);
  346.     }
  347.    
  348.     if(pthread_join(threads[THREAD_B], &pthread_exit_state) != 0)
  349.     {
  350.         perror("Join THREAD_B-Thread\n");
  351.         exit(EXIT_FAILURE);
  352.     }
  353.  
  354.     if(pthread_exit_state == PTHREAD_CANCELED)
  355.     {
  356.         printf("THREAD_B-Thread canceled\n");
  357.     }else
  358.     {
  359.         printf("THREAD_B-Thread wasn't canceled\n");
  360.     }
  361.    
  362.    
  363.     exit(0);
  364. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement