• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <pthread.h>
2 #include <string.h>
3 #include <errno.h>
4 #include "test.h"
5 
6 #define TEST(r, f, m) ( \
7 	((r) = (f)) == 0 || (t_error("%s failed: (pshared==%d, pi==%d) %s (" m ")\n", #f, pshared, pi, strerror(r)), 0) )
8 #define TESTX(r, f, x, m) ( \
9 	((r) = (f)) == (x) || (t_error("%s failed: (pshared==%d, pi==%d) got %d \"%s\" want %d \"%s\" (" m ")\n", #f, pshared, pi, r, strerror(r), x, strerror(x)), 0) )
10 
start_lock(void * arg)11 static void *start_lock(void *arg)
12 {
13 	pthread_mutex_lock(arg);
14 	return 0;
15 }
16 
start_wait(void * arg)17 static void *start_wait(void *arg)
18 {
19 	void **args = arg;
20 	pthread_mutex_lock(args[1]);
21 	pthread_barrier_wait(args[0]);
22 	nanosleep(&(struct timespec){ .tv_nsec = 10000000 }, 0);
23 	return 0;
24 }
25 
f(int pshared,int pi)26 void f(int pshared, int pi)
27 {
28 	pthread_t td;
29 	int r;
30 	void *res;
31 	pthread_barrier_t barrier2;
32 	pthread_mutexattr_t mtx_a;
33 	pthread_mutex_t mtx;
34 
35 	TEST(r, pthread_barrier_init(&barrier2, 0, 2), "creating barrier");
36 
37 	/* Robust mutexes */
38 	TEST(r, pthread_mutexattr_init(&mtx_a), "initializing mutex attr");
39 	TEST(r, pthread_mutexattr_setrobust(&mtx_a, PTHREAD_MUTEX_ROBUST), "setting robust attribute");
40 	if (pshared)
41 		TEST(r, pthread_mutexattr_setpshared(&mtx_a, PTHREAD_PROCESS_SHARED), "setting pshared attribute");
42 	if (pi)
43 		TEST(r, pthread_mutexattr_setprotocol(&mtx_a, PTHREAD_PRIO_INHERIT), "setting PI attribute");
44 	TEST(r, pthread_mutex_init(&mtx, &mtx_a), "initializing robust mutex");
45 	TEST(r, pthread_mutex_lock(&mtx), "locking robust mutex");
46 	TEST(r, pthread_mutex_unlock(&mtx), "unlocking robust mutex");
47 	TEST(r, pthread_create(&td, 0, start_lock, &mtx), "failed to create thread");
48 	TEST(r, pthread_join(td, &res), "joining thread");
49 	TESTX(r, pthread_mutex_lock(&mtx), EOWNERDEAD, "locking orphaned robust mutex");
50 	TEST(r, pthread_mutex_unlock(&mtx), "unlocking orphaned robust mutex");
51 	TESTX(r, pthread_mutex_lock(&mtx), ENOTRECOVERABLE, "re-locking orphaned robust mutex");
52 	TEST(r, pthread_mutex_destroy(&mtx), "destroying unrecoverable mutex");
53 
54 	TEST(r, pthread_mutex_init(&mtx, &mtx_a), "initializing robust mutex");
55 	TEST(r, pthread_create(&td, 0, start_lock, &mtx), "failed to create thread");
56 	TEST(r, pthread_join(td, &res), "joining thread");
57 	TESTX(r, pthread_mutex_lock(&mtx), EOWNERDEAD, "locking orphaned robust mutex");
58 	TEST(r, pthread_mutex_consistent(&mtx), "");
59 	TEST(r, pthread_mutex_unlock(&mtx), "unlocking orphaned robust mutex");
60 	TEST(r, pthread_mutex_lock(&mtx), "re-locking orphaned robust mutex");
61 	TEST(r, pthread_mutex_destroy(&mtx), "destroying mutex");
62 
63 	TEST(r, pthread_mutex_init(&mtx, &mtx_a), "");
64 	TEST(r, pthread_create(&td, 0, start_wait, (void *[]){ &barrier2, &mtx }), "");
65 	r = pthread_barrier_wait(&barrier2);
66 	if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
67 		t_error("pthread_barrier_wait failed: got %d \"%s\", wanted either 0 or %d\n",
68 			r, strerror(r), PTHREAD_BARRIER_SERIAL_THREAD);
69 	TEST(r, pthread_barrier_destroy(&barrier2), "");
70 	TESTX(r, pthread_mutex_lock(&mtx), EOWNERDEAD, "");
71 	TEST(r, pthread_join(td, &res), "");
72 	TEST(r, pthread_mutex_consistent(&mtx), "");
73 	TEST(r, pthread_mutex_unlock(&mtx), "");
74 	TEST(r, pthread_mutex_destroy(&mtx), "");
75 }
76 
main(void)77 int main(void)
78 {
79 	for (int pshared=0; pshared<=1; pshared++)
80 		for (int pi=0; pi<=1; pi++)
81 			f(pshared, pi);
82 	return t_status;
83 }
84