• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <pthread.h>
2 #include <string.h>
3 #include "test.h"
4 
5 #define TEST(r, f, m) ( \
6 	((r) = (f)) == 0 || (t_error("%s failed: %s (" m ")\n", #f, strerror(r)), 0) )
7 
8 
start_signal(void * arg)9 static void *start_signal(void *arg)
10 {
11 	void **args = arg;
12 	pthread_mutex_lock(args[1]);
13 	pthread_cond_signal(args[0]);
14 	pthread_mutex_unlock(args[1]);
15 	return 0;
16 }
17 
start_wait(void * arg)18 static void *start_wait(void *arg)
19 {
20 	void **args = arg;
21 	pthread_mutex_t *m = args[1];
22 	pthread_cond_t *c = args[0];
23 	int *x = args[2];
24 
25 	pthread_mutex_lock(m);
26 	while (*x) pthread_cond_wait(c, m);
27 	pthread_mutex_unlock(m);
28 
29 	return 0;
30 }
31 
main(void)32 int main(void)
33 {
34 	pthread_t td, td1, td2, td3;
35 	int r;
36 	void *res;
37 	pthread_mutex_t mtx;
38 	pthread_cond_t cond;
39 	int foo[1];
40 
41 	/* Condition variables */
42 	TEST(r, pthread_mutex_init(&mtx, 0), "");
43 	TEST(r, pthread_cond_init(&cond, 0), "");
44 	TEST(r, pthread_mutex_lock(&mtx), "");
45 	TEST(r, pthread_create(&td, 0, start_signal, (void *[]){ &cond, &mtx }), "");
46 	TEST(r, pthread_cond_wait(&cond, &mtx), "");
47 	TEST(r, pthread_join(td, &res), "");
48 	TEST(r, pthread_mutex_unlock(&mtx), "");
49 	TEST(r, pthread_mutex_destroy(&mtx), "");
50 	TEST(r, pthread_cond_destroy(&cond), "");
51 
52 	/* Condition variables with multiple waiters */
53 	TEST(r, pthread_mutex_init(&mtx, 0), "");
54 	TEST(r, pthread_cond_init(&cond, 0), "");
55 	TEST(r, pthread_mutex_lock(&mtx), "");
56 	foo[0] = 1;
57 	TEST(r, pthread_create(&td1, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
58 	TEST(r, pthread_create(&td2, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
59 	TEST(r, pthread_create(&td3, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
60 	TEST(r, pthread_mutex_unlock(&mtx), "");
61 	nanosleep(&(struct timespec){.tv_nsec=1000000}, 0);
62 	foo[0] = 0;
63 	TEST(r, pthread_mutex_lock(&mtx), "");
64 	TEST(r, pthread_cond_signal(&cond), "");
65 	TEST(r, pthread_mutex_unlock(&mtx), "");
66 	TEST(r, pthread_mutex_lock(&mtx), "");
67 	TEST(r, pthread_cond_signal(&cond), "");
68 	TEST(r, pthread_mutex_unlock(&mtx), "");
69 	TEST(r, pthread_mutex_lock(&mtx), "");
70 	TEST(r, pthread_cond_signal(&cond), "");
71 	TEST(r, pthread_mutex_unlock(&mtx), "");
72 	TEST(r, pthread_join(td1, 0), "");
73 	TEST(r, pthread_join(td2, 0), "");
74 	TEST(r, pthread_join(td3, 0), "");
75 	TEST(r, pthread_mutex_destroy(&mtx), "");
76 	TEST(r, pthread_cond_destroy(&cond), "");
77 
78 	/* Condition variables with broadcast signals */
79 	TEST(r, pthread_mutex_init(&mtx, 0), "");
80 	TEST(r, pthread_cond_init(&cond, 0), "");
81 	TEST(r, pthread_mutex_lock(&mtx), "");
82 	foo[0] = 1;
83 	TEST(r, pthread_create(&td1, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
84 	TEST(r, pthread_create(&td2, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
85 	TEST(r, pthread_create(&td3, 0, start_wait, (void *[]){ &cond, &mtx, foo }), "");
86 	TEST(r, pthread_mutex_unlock(&mtx), "");
87 	nanosleep(&(struct timespec){.tv_nsec=1000000}, 0);
88 	TEST(r, pthread_mutex_lock(&mtx), "");
89 	foo[0] = 0;
90 	TEST(r, pthread_mutex_unlock(&mtx), "");
91 	TEST(r, pthread_cond_broadcast(&cond), "");
92 	TEST(r, pthread_join(td1, 0), "");
93 	TEST(r, pthread_join(td2, 0), "");
94 	TEST(r, pthread_join(td3, 0), "");
95 	TEST(r, pthread_mutex_destroy(&mtx), "");
96 	TEST(r, pthread_cond_destroy(&cond), "");
97 
98 	return t_status;
99 }
100