• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 
unlock(void * arg)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 
test_unlock(int mtype)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 
test_unlock_other(int mtype)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 
test_mutexattr()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 
main(void)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 }
169