Commit | Line | Data |
---|---|---|
3aac2619 | 1 | #include <pthread_extra.h> |
735a6b43 TM |
2 | #include <time.h> |
3 | #include <stdio.h> | |
4 | #include <stdbool.h> | |
5 | ||
735a6b43 TM |
6 | /* |
7 | //This is first prototype for two mutexes only, it is useful in order to understand how this all works | |
8 | //Currently it was replaced by macro with the same name | |
9 | int pthread_mutex_timedlock_two(pthread_mutex_t *a, pthread_mutex_t *b, const struct timespec *restrict abs_timeout) { | |
10 | int ret; | |
11 | ||
12 | while(1) { | |
13 | //Wait for the first mutex | |
14 | ret = (abs_timeout==NULL ? pthread_mutex_lock(a) : pthread_mutex_timedlock(a, abs_timeout)); | |
15 | if(ret) return ret; //Something is fishy about this mutex. Abort! | |
16 | ||
17 | //Try to lock the second mutex | |
18 | ret = pthread_mutex_trylock(b); | |
19 | if(!ret) return ret; //Locked BOTH Hooray! | |
20 | ||
21 | //Unlock first if second failed to prevent deadlocks | |
22 | pthread_mutex_unlock(a); | |
23 | ||
24 | //Swap mutexes, so we will try to block on the second mutex next time: | |
25 | pthread_mutex_swap(a, b); | |
26 | //printf("Retry!\n"); | |
27 | } | |
28 | } | |
29 | */ | |
30 | ||
31 | int pthread_mutex_timedlock_multi_generic(pthread_mutex_t **lck, int cnt, bool block, const struct timespec *restrict abs_timeout) { | |
32 | int ret, locked; | |
33 | ||
34 | while(1) { | |
35 | //Try to lock all mutexes | |
36 | for(int i = 0; i<cnt; i++) { | |
37 | //Block only on the first one | |
38 | if(block && i==0) { | |
39 | ret = (abs_timeout==NULL ? pthread_mutex_lock(lck[i]) : pthread_mutex_timedlock(lck[i], abs_timeout)); | |
40 | if(ret) return ret; //Something went wrong | |
41 | continue; | |
42 | } | |
43 | //Then try if we can lock the rest | |
44 | ret = pthread_mutex_trylock(lck[i]); | |
45 | if(ret) { | |
46 | //Cannot lock this one | |
47 | locked = i; | |
48 | printf("Cannot lock #%d!\n", i); | |
49 | break; | |
50 | } | |
51 | locked = i; | |
52 | } | |
53 | ||
54 | //Check if we managed to lock all locks | |
55 | if(locked == cnt) return 0; | |
56 | ||
57 | //Unlock all mutexes that we managed to lock so far | |
58 | for(int i = 0;i<locked;i++) { | |
59 | printf("Unlocking #%d\n", i); | |
60 | pthread_mutex_unlock(lck[i]); | |
61 | } | |
62 | if(!block) return ret; //We do not want to block, just trying | |
63 | ||
64 | //Try to block on locked mutex in next round | |
65 | pthread_mutex_swap(lck[0],lck[locked]); | |
66 | } | |
67 | } |