Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*cflags = -Wall -Werror -ansi -pedantic -D_POSIX_C_SOURCE=200809L -pthread -lrt*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <unistd.h>
- #include <signal.h>
- #define THREAD_A 0
- #define THREAD_B 1
- enum STATUS {LAZY, WAITING, USE};
- pthread_t threads[2];
- enum STATUS thread_status[2];
- sem_t resources;
- sem_t mutex;
- /*counter for detecting wether A or B was working more often*/
- int balance;
- /*declaration*/
- void *thread_function(void *);
- void freetime(int, char);
- void deadlock_detection(void);
- void abortion(int sig);
- void resolve_deadlock();
- int main (void) {
- int id_a = THREAD_A;
- int id_b = THREAD_B;
- /*registrating signal-handler*/
- struct sigaction action;
- action.sa_handler = &abortion;
- action.sa_flags = 0;
- sigemptyset(&action.sa_mask);
- if (sigaction(SIGINT, &action, NULL) == -1) {
- perror("set actionhandler\n");
- exit(EXIT_FAILURE);
- }
- thread_status[THREAD_A] = LAZY;
- thread_status[THREAD_B] = LAZY;
- /*Initializing semaphores*/
- if(sem_init(&resources, 0, 2) == -1)
- {
- perror("Init resources-Semaphore\n");
- exit(EXIT_FAILURE);
- }
- if(sem_init(&mutex, 0, 1) == -1)
- {
- perror("Init mutex-Semaphore\n");
- exit(EXIT_FAILURE);
- }
- /*starting threads*/
- if (pthread_create(&threads[THREAD_A], NULL, &thread_function, (void *) &id_a) != 0) {
- perror("Create THREAD_A\n");
- exit(EXIT_FAILURE);
- }
- if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) {
- perror("Create THREAD_B\n");
- exit(EXIT_FAILURE);
- }
- deadlock_detection();
- return 0;
- }
- void *thread_function(void *id) {
- int thread = *((int *) id);
- char c = (thread == THREAD_A) ? 'A' : 'B';
- /*thread b starts a little later*/
- if (thread == THREAD_B) {
- sleep(4);
- }
- printf("Thread_%c: Started.\n", c);
- while (1) {
- printf("Thread_%c: Let's see if a resource is available.\n", c);
- sem_wait(&resources);
- printf("Thread_%c: Now I have a resource.\n", c);
- sem_wait(&mutex);
- if(thread == THREAD_A)
- {
- thread_status[THREAD_A] = WAITING;
- }else if (thread == THREAD_B)
- {
- thread_status[THREAD_B] = WAITING;
- }
- sem_post(&mutex);
- /*thread a needs 1 second to get to the next resource, thread b needs a little longer*/
- if(thread == THREAD_A)
- {
- sleep(1);
- }else if (thread == THREAD_B)
- {
- sleep(3);
- }
- printf("Thread_%c: Let's see if the second resource is also available.\n", c);
- sem_wait(&resources);
- printf("Thread_%c: Now I have both resources and I can start working!\n", c);
- /*if a thread has both resources, he can start working*/
- sem_wait(&mutex);
- if(thread == THREAD_A)
- {
- thread_status[THREAD_A] = USE;
- balance++;
- }else if (thread == THREAD_B)
- {
- thread_status[THREAD_B] = USE;
- balance--;
- }
- sem_post(&mutex);
- /*working needs 5 sec*/
- sleep(5);
- printf("Thread_%c: My work is done, I will free my resources!\n", c);
- /*when work is done both resources can be freed*/
- sem_post(&resources);
- sem_post(&resources);
- /*and the thread who worked rests for a while*/
- sem_wait(&mutex);
- if(thread == THREAD_A)
- {
- thread_status[THREAD_A] = LAZY;
- }else if (thread == THREAD_B)
- {
- thread_status[THREAD_B] = LAZY;
- }
- sem_post(&mutex);
- freetime(thread, c);
- }
- pthread_exit(NULL);
- }
- void freetime(int thread, char c) {
- static int i = 0;
- if (thread == THREAD_A) {
- printf("Thread_%c: I will now sleep for 5 seconds!\n", c);
- sleep(5);
- } else {
- if ((5 - i) < 0) {
- i = 0;
- }
- printf("Thread_%c: I will sleep now . I will be back in %d seconds !\n", c, 5 - i);
- sleep(5 - i);
- i += 3;
- }
- }
- /*the detection is executed every 8 seconds, when both threads are waiting a deadlock occured*/
- void deadlock_detection(void) {
- while (1) {
- sleep(8);
- sem_wait(&mutex);
- if(thread_status[THREAD_A] == WAITING && thread_status[THREAD_B] == WAITING)
- {
- printf("DEADLOCK: Both threads are waiting for a resource!\n");
- resolve_deadlock();
- }
- sem_post(&mutex);
- }
- }
- /*for resolving the deadlock, kill the thread who worked more often, and then restart it*/
- void resolve_deadlock()
- {
- void *pthread_exit_state;
- int id_a = THREAD_A;
- int id_b = THREAD_B;
- /*A worked more often*/
- if(balance >= 0)
- {
- /*kill A*/
- if(pthread_cancel(threads[THREAD_A]) != 0)
- {
- perror("Cancel THREAD_A-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_join(threads[THREAD_A], &pthread_exit_state) != 0)
- {
- perror("Join THREAD_A-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_exit_state == PTHREAD_CANCELED)
- {
- printf("THREAD_A-Thread canceled\n");
- }else
- {
- printf("THREAD_A-Thread wasn't canceled\n");
- }
- sem_post(&resources);
- /*restart A*/
- if (pthread_create(&threads[THREAD_A], NULL, &thread_function, (void *) &id_a) != 0) {
- perror("Create THREAD_A\n");
- exit(EXIT_FAILURE);
- }
- }else
- {
- /*same goes for B*/
- if(pthread_cancel(threads[THREAD_B]) != 0)
- {
- perror("Cancel THREAD_B-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_join(threads[THREAD_B], &pthread_exit_state) != 0)
- {
- perror("Join THREAD_B-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_exit_state == PTHREAD_CANCELED)
- {
- printf("THREAD_B-Thread canceled\n");
- }else
- {
- printf("THREAD_B-Thread wasn't canceled\n");
- }
- sem_post(&resources);
- if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) {
- perror("Create THREAD_B\n");
- exit(EXIT_FAILURE);
- }
- }
- }
- /*for CTRL+C - free all resources and exit*/
- void abortion(int sig) {
- void *pthread_exit_state;
- printf(" ===> ABORT <===\n");
- if(sem_destroy(&resources) == -1)
- {
- perror("Destroy resource-Semaphore\n");
- exit(EXIT_FAILURE);
- }
- if(sem_destroy(&mutex) == -1)
- {
- perror("Destroy mutex-Semaphore\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_cancel(threads[THREAD_A]) != 0)
- {
- perror("Cancel THREAD_A-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_join(threads[THREAD_A], &pthread_exit_state) != 0)
- {
- perror("Join THREAD_A-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_exit_state == PTHREAD_CANCELED)
- {
- printf("THREAD_A-Thread canceled\n");
- }else
- {
- printf("THREAD_A-Thread wasn't canceled\n");
- }
- if(pthread_cancel(threads[THREAD_B]) != 0)
- {
- perror("Cancel THREAD_B-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_join(threads[THREAD_B], &pthread_exit_state) != 0)
- {
- perror("Join THREAD_B-Thread\n");
- exit(EXIT_FAILURE);
- }
- if(pthread_exit_state == PTHREAD_CANCELED)
- {
- printf("THREAD_B-Thread canceled\n");
- }else
- {
- printf("THREAD_B-Thread wasn't canceled\n");
- }
- exit(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement