add PI mutex tests
[libc-test] / src / functional / pthread_mutex_pi.c
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
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
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_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT));
43         T(pthread_mutex_init(a[0], &ma));
44         T(pthread_mutexattr_destroy(&ma));
45         E(sem_init(a[1], 0, 0));
46         T(pthread_create(&t, 0, relock, a));
47         E(sem_wait(a[1]));
48         E(clock_gettime(CLOCK_REALTIME, &ts));
49         ts.tv_nsec += 100*1000*1000;
50         if (ts.tv_nsec >= 1000*1000*1000) {
51                 ts.tv_nsec -= 1000*1000*1000;
52                 ts.tv_sec += 1;
53         }
54         r = sem_timedwait(a[1],&ts);
55         if (r == -1) {
56                 if (errno != ETIMEDOUT)
57                         t_error("sem_timedwait failed with unexpected error: %s\n", strerror(errno));
58                 /* leave the deadlocked relock thread running */
59                 return -1;
60         }
61         T(pthread_join(t, &p));
62         T(pthread_mutex_destroy(a[0]));
63         E(sem_destroy(a[1]));
64         return i;
65 }
66
67 static void *unlock(void *arg)
68 {
69         void **a = arg;
70
71         *(int*)a[1] = pthread_mutex_unlock(a[0]);
72         return 0;
73 }
74
75 static int test_unlock(int mtype)
76 {
77         pthread_t t;
78         pthread_mutex_t m;
79         pthread_mutexattr_t ma;
80         int i;
81         int r;
82         void *p;
83         void *a[] = {&m,&i};
84
85         T(pthread_mutexattr_init(&ma));
86         T(pthread_mutexattr_settype(&ma, mtype));
87         T(pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT));
88         T(pthread_mutex_init(a[0], &ma));
89         T(pthread_mutexattr_destroy(&ma));
90         T(pthread_create(&t, 0, unlock, a));
91         T(pthread_join(t, &p));
92         T(pthread_mutex_destroy(a[0]));
93         return i;
94 }
95
96 static int test_unlock_other(int mtype)
97 {
98         pthread_t t;
99         pthread_mutex_t m;
100         pthread_mutexattr_t ma;
101         int i;
102         int r;
103         void *p;
104         void *a[] = {&m,&i};
105
106         T(pthread_mutexattr_init(&ma));
107         T(pthread_mutexattr_settype(&ma, mtype));
108         T(pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT));
109         T(pthread_mutex_init(a[0], &ma));
110         T(pthread_mutexattr_destroy(&ma));
111         T(pthread_mutex_lock(a[0]));
112         T(pthread_create(&t, 0, unlock, a));
113         T(pthread_join(t, &p));
114         T(pthread_mutex_unlock(a[0]));
115         T(pthread_mutex_destroy(a[0]));
116         return i;
117 }
118
119 static void test_mutexattr()
120 {
121         pthread_mutex_t m;
122         pthread_mutexattr_t a;
123         int r;
124         int i;
125
126         T(pthread_mutexattr_init(&a));
127         T(pthread_mutexattr_gettype(&a, &i));
128         if (i != PTHREAD_MUTEX_DEFAULT)
129                 t_error("default mutex type is %d, wanted PTHREAD_MUTEX_DEFAULT (%d)\n", i, PTHREAD_MUTEX_DEFAULT);
130         T(pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK));
131         T(pthread_mutexattr_gettype(&a, &i));
132         if (i != PTHREAD_MUTEX_ERRORCHECK)
133                 t_error("setting error check mutex type failed failed: got %d, wanted %d\n", i, PTHREAD_MUTEX_ERRORCHECK);
134         T(pthread_mutexattr_destroy(&a));
135 }
136
137 int main(void)
138 {
139         int i;
140
141         test_mutexattr();
142
143         i = test_relock(PTHREAD_MUTEX_NORMAL);
144         if (i != -1)
145                 t_error("PTHREAD_MUTEX_NORMAL relock did not deadlock, got %s\n", strerror(i));
146         i = test_relock(PTHREAD_MUTEX_ERRORCHECK);
147         if (i != EDEADLK)
148                 t_error("PTHREAD_MUTEX_ERRORCHECK relock did not return EDEADLK, got %s\n", i==-1?"deadlock":strerror(i));
149         i = test_relock(PTHREAD_MUTEX_RECURSIVE);
150         if (i != 0)
151                 t_error("PTHREAD_MUTEX_RECURSIVE relock did not succed, got %s\n", i==-1?"deadlock":strerror(i));
152
153         i = test_unlock(PTHREAD_MUTEX_ERRORCHECK);
154         if (i != EPERM)
155                 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i));
156         i = test_unlock(PTHREAD_MUTEX_RECURSIVE);
157         if (i != EPERM)
158                 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i));
159
160         i = test_unlock_other(PTHREAD_MUTEX_ERRORCHECK);
161         if (i != EPERM)
162                 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i));
163         i = test_unlock_other(PTHREAD_MUTEX_RECURSIVE);
164         if (i != EPERM)
165                 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i));
166
167         return t_status;
168 }