1 /* testing pthread mutex behaviour with various attributes */
2 #include <pthread.h>
3 #include <semaphore.h>
4 #include <stdio.h>
5 #include <errno.h>
6 #include <string.h>
7 #include "test.h"
8
9 #define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r))
10 #define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno))
11
relock(void * arg)12 static void *relock(void *arg)
13 {
14 void **a = arg;
15 int r;
16
17 T(pthread_mutex_lock(a[0]));
18 E(sem_post(a[1]));
19 *(int*)a[2] = pthread_mutex_lock(a[0]);
20 E(sem_post(a[1]));
21
22 T(pthread_mutex_unlock(a[0]));
23 if (*(int*)a[2] == 0)
24 T(pthread_mutex_unlock(a[0]));
25 return 0;
26 }
27
test_relock(int mtype)28 static int test_relock(int mtype)
29 {
30 struct timespec ts;
31 pthread_t t;
32 pthread_mutex_t m;
33 pthread_mutexattr_t ma;
34 sem_t s;
35 int i;
36 int r;
37 void *p;
38 void *a[] = {&m,&s,&i};
39
40 T(pthread_mutexattr_init(&ma));
41 T(pthread_mutexattr_settype(&ma, mtype));
42 T(pthread_mutex_init(a[0], &ma));
43 T(pthread_mutexattr_destroy(&ma));
44 E(sem_init(a[1], 0, 0));
45 T(pthread_create(&t, 0, relock, a));
46 E(sem_wait(a[1]));
47 E(clock_gettime(CLOCK_REALTIME, &ts));
48 ts.tv_nsec += 100*1000*1000;
49 if (ts.tv_nsec >= 1000*1000*1000) {
50 ts.tv_nsec -= 1000*1000*1000;
51 ts.tv_sec += 1;
52 }
53 r = sem_timedwait(a[1],&ts);
54 if (r == -1) {
55 if (errno != ETIMEDOUT)
56 t_error("sem_timedwait failed with unexpected error: %s\n", strerror(errno));
57 /* leave the deadlocked relock thread running */
58 return -1;
59 }
60 T(pthread_join(t, &p));
61 T(pthread_mutex_destroy(a[0]));
62 E(sem_destroy(a[1]));
63 return i;
64 }
65
unlock(void * arg)66 static void *unlock(void *arg)
67 {
68 void **a = arg;
69
70 *(int*)a[1] = pthread_mutex_unlock(a[0]);
71 return 0;
72 }
73
test_unlock(int mtype)74 static int test_unlock(int mtype)
75 {
76 pthread_t t;
77 pthread_mutex_t m;
78 pthread_mutexattr_t ma;
79 int i;
80 int r;
81 void *p;
82 void *a[] = {&m,&i};
83
84 T(pthread_mutexattr_init(&ma));
85 T(pthread_mutexattr_settype(&ma, mtype));
86 T(pthread_mutex_init(a[0], &ma));
87 T(pthread_mutexattr_destroy(&ma));
88 T(pthread_create(&t, 0, unlock, a));
89 T(pthread_join(t, &p));
90 T(pthread_mutex_destroy(a[0]));
91 return i;
92 }
93
test_unlock_other(int mtype)94 static int test_unlock_other(int mtype)
95 {
96 pthread_t t;
97 pthread_mutex_t m;
98 pthread_mutexattr_t ma;
99 int i;
100 int r;
101 void *p;
102 void *a[] = {&m,&i};
103
104 T(pthread_mutexattr_init(&ma));
105 T(pthread_mutexattr_settype(&ma, mtype));
106 T(pthread_mutex_init(a[0], &ma));
107 T(pthread_mutexattr_destroy(&ma));
108 T(pthread_mutex_lock(a[0]));
109 T(pthread_create(&t, 0, unlock, a));
110 T(pthread_join(t, &p));
111 T(pthread_mutex_unlock(a[0]));
112 T(pthread_mutex_destroy(a[0]));
113 return i;
114 }
115
test_mutexattr()116 static void test_mutexattr()
117 {
118 pthread_mutex_t m;
119 pthread_mutexattr_t a;
120 int r;
121 int i;
122
123 T(pthread_mutexattr_init(&a));
124 T(pthread_mutexattr_gettype(&a, &i));
125 if (i != PTHREAD_MUTEX_DEFAULT)
126 t_error("default mutex type is %d, wanted PTHREAD_MUTEX_DEFAULT (%d)\n", i, PTHREAD_MUTEX_DEFAULT);
127 T(pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK));
128 T(pthread_mutexattr_gettype(&a, &i));
129 if (i != PTHREAD_MUTEX_ERRORCHECK)
130 t_error("setting error check mutex type failed failed: got %d, wanted %d\n", i, PTHREAD_MUTEX_ERRORCHECK);
131 T(pthread_mutexattr_destroy(&a));
132 }
133
main(void)134 int main(void)
135 {
136 int i;
137
138 test_mutexattr();
139
140 i = test_relock(PTHREAD_MUTEX_NORMAL);
141 if (i != -1)
142 t_error("PTHREAD_MUTEX_NORMAL relock did not deadlock, got %s\n", strerror(i));
143 i = test_relock(PTHREAD_MUTEX_ERRORCHECK);
144 if (i != EDEADLK)
145 t_error("PTHREAD_MUTEX_ERRORCHECK relock did not return EDEADLK, got %s\n", i==-1?"deadlock":strerror(i));
146 i = test_relock(PTHREAD_MUTEX_RECURSIVE);
147 if (i != 0)
148 t_error("PTHREAD_MUTEX_RECURSIVE relock did not succed, got %s\n", i==-1?"deadlock":strerror(i));
149
150 i = test_unlock(PTHREAD_MUTEX_ERRORCHECK);
151 if (i != EPERM)
152 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i));
153 i = test_unlock(PTHREAD_MUTEX_RECURSIVE);
154 if (i != EPERM)
155 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i));
156
157 i = test_unlock_other(PTHREAD_MUTEX_ERRORCHECK);
158 if (i != EPERM)
159 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i));
160 i = test_unlock_other(PTHREAD_MUTEX_RECURSIVE);
161 if (i != EPERM)
162 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i));
163
164 return t_status;
165 }
166