01a13fb23fd918b969f9c325bcf160820ad93c11
[libc-test] / src / functional / pthread_mutex.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         return 0;
22 }
23
24 static int test_relock(int mtype)
25 {
26         struct timespec ts;
27         pthread_t t;
28         pthread_mutex_t m;
29         pthread_mutexattr_t ma;
30         sem_t s;
31         int i;
32         int r;
33         void *p;
34         void *a[] = {&m,&s,&i};
35
36         T(pthread_mutexattr_init(&ma));
37         T(pthread_mutexattr_settype(&ma, mtype));
38         T(pthread_mutex_init(a[0], &ma));
39         E(sem_init(a[1], 0, 0));
40         T(pthread_create(&t, 0, relock, a));
41         E(sem_wait(a[1]));
42         E(clock_gettime(CLOCK_REALTIME, &ts));
43         ts.tv_nsec += 100*1000*1000;
44         if (ts.tv_nsec >= 1000*1000*1000) {
45                 ts.tv_nsec -= 1000*1000*1000;
46                 ts.tv_sec += 1;
47         }
48         r = sem_timedwait(a[1],&ts);
49         if (r == -1) {
50                 if (errno != ETIMEDOUT)
51                         t_error("sem_timedwait failed with unexpected error: %s\n", strerror(errno));
52                 return -1;
53         }
54         T(pthread_join(t, &p));
55         T(pthread_mutex_destroy(a[0]));
56         T(pthread_mutexattr_destroy(&ma));
57         E(sem_destroy(a[1]));
58         return i;
59 }
60
61 static void *unlock(void *arg)
62 {
63         void **a = arg;
64
65         *(int*)a[1] = pthread_mutex_unlock(a[0]);
66         return 0;
67 }
68
69 static int test_unlock(int mtype)
70 {
71         pthread_t t;
72         pthread_mutex_t m;
73         pthread_mutexattr_t ma;
74         int i;
75         int r;
76         void *p;
77         void *a[] = {&m,&i};
78
79         T(pthread_mutexattr_init(&ma));
80         T(pthread_mutexattr_settype(&ma, mtype));
81         T(pthread_mutex_init(a[0], &ma));
82         T(pthread_create(&t, 0, unlock, a));
83         T(pthread_join(t, &p));
84         T(pthread_mutex_destroy(a[0]));
85         T(pthread_mutexattr_destroy(&ma));
86         return i;
87 }
88
89 static int test_unlock_other(int mtype)
90 {
91         pthread_t t;
92         pthread_mutex_t m;
93         pthread_mutexattr_t ma;
94         int i;
95         int r;
96         void *p;
97         void *a[] = {&m,&i};
98
99         T(pthread_mutexattr_init(&ma));
100         T(pthread_mutexattr_settype(&ma, mtype));
101         T(pthread_mutex_init(a[0], &ma));
102         T(pthread_mutex_lock(a[0]));
103         T(pthread_create(&t, 0, unlock, a));
104         T(pthread_join(t, &p));
105         T(pthread_mutex_destroy(a[0]));
106         T(pthread_mutexattr_destroy(&ma));
107         return i;
108 }
109
110 static void test_mutexattr()
111 {
112         pthread_mutex_t m;
113         pthread_mutexattr_t a;
114         int r;
115         int i;
116
117         T(pthread_mutexattr_init(&a));
118         T(pthread_mutexattr_gettype(&a, &i));
119         if (i != PTHREAD_MUTEX_DEFAULT)
120                 t_error("default mutex type is %d, wanted PTHREAD_MUTEX_DEFAULT (%d)\n", i, PTHREAD_MUTEX_DEFAULT);
121         T(pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK));
122         T(pthread_mutexattr_gettype(&a, &i));
123         if (i != PTHREAD_MUTEX_ERRORCHECK)
124                 t_error("setting error check mutex type failed failed: got %d, wanted %d\n", i, PTHREAD_MUTEX_ERRORCHECK);
125 }
126
127 int main(void)
128 {
129         int i;
130
131         test_mutexattr();
132
133         i = test_relock(PTHREAD_MUTEX_NORMAL);
134         if (i != -1)
135                 t_error("PTHREAD_MUTEX_NORMAL relock did not deadlock, got %s\n", strerror(i));
136         i = test_relock(PTHREAD_MUTEX_ERRORCHECK);
137         if (i != EDEADLK)
138                 t_error("PTHREAD_MUTEX_ERRORCHECK relock did not return EDEADLK, got %s\n", i==-1?"deadlock":strerror(i));
139         i = test_relock(PTHREAD_MUTEX_RECURSIVE);
140         if (i != 0)
141                 t_error("PTHREAD_MUTEX_RECURSIVE relock did not succed, got %s\n", i==-1?"deadlock":strerror(i));
142
143         i = test_unlock(PTHREAD_MUTEX_ERRORCHECK);
144         if (i != EPERM)
145                 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i));
146         i = test_unlock(PTHREAD_MUTEX_RECURSIVE);
147         if (i != EPERM)
148                 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i));
149
150         i = test_unlock_other(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_other(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         return t_status;
158 }