1 /* Copyright (c) 2016 Google, Inc.
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details. */
5 #include <utest/utest.h>
6 #include <parlib/uthread.h>
11 /* <--- Begin definition of test cases ---> */
17 unsigned int wait_sleep;
18 unsigned int sig_sleep;
21 #define PTH_TEST_TRUE (void*)1
23 bool test_signal_no_wait(void)
25 uth_cond_var_t cv = uth_cond_var_alloc();
27 uth_cond_var_broadcast(cv);
28 uth_cond_var_signal(cv);
30 uth_cond_var_free(cv);
34 void *__cv_signaller(void *arg)
36 struct common_args *args = (struct common_args*)arg;
38 uthread_usleep(args->sig_sleep);
39 uth_mutex_lock(args->mtx);
41 uth_mutex_unlock(args->mtx);
42 /* We can actually signal outside the mutex if we want. Remember the
43 * invariant: whenever the flag is set from FALSE to TRUE, all waiters that
44 * saw FALSE are on the CV's waitqueue. That's true even after we unlock
46 uth_cond_var_signal(args->cv);
50 void *__cv_broadcaster(void *arg)
52 struct common_args *args = (struct common_args*)arg;
54 uthread_usleep(args->sig_sleep);
55 uth_mutex_lock(args->mtx);
57 uth_mutex_unlock(args->mtx);
58 /* We can actually signal outside the mutex if we want. Remember the
59 * invariant: whenever the flag is set from FALSE to TRUE, all waiters that
60 * saw FALSE are on the CV's waitqueue. That's true even after we unlock
62 uth_cond_var_broadcast(args->cv);
66 void *__cv_waiter(void *arg)
68 struct common_args *args = (struct common_args*)arg;
70 uthread_usleep(args->wait_sleep);
71 uth_mutex_lock(args->mtx);
73 uth_cond_var_wait(args->cv, args->mtx);
74 UT_ASSERT(args->flag);
75 uth_mutex_unlock(args->mtx);
79 /* Basic one signaller, one receiver. We want to vary the amount of time the
80 * sender and receiver delays, starting with (1ms, 0ms) and ending with (0ms,
81 * 1ms). At each extreme, such as with the sender waiting 1ms, the
82 * receiver/waiter should hit the "check and wait" point well before the
83 * sender/signaller hits the "change state and signal" point. */
84 bool test_signal(void)
86 struct common_args local_a, *args = &local_a;
87 pthread_t signaller, waiter;
88 void *sig_join, *wait_join;
91 args->cv = uth_cond_var_alloc();
92 args->mtx = uth_mutex_alloc();
94 for (int i = 0; i < 1000; i += 10) {
97 args->sig_sleep = 1000 - i;
99 ret = pthread_create(&waiter, 0, __cv_waiter, args);
101 ret = pthread_create(&signaller, 0, __cv_signaller, args);
103 ret = pthread_join(waiter, &wait_join);
105 ret = pthread_join(signaller, &sig_join);
107 UT_ASSERT_M("Waiter Failed", wait_join == PTH_TEST_TRUE);
108 UT_ASSERT_M("Signaller Failed", sig_join == PTH_TEST_TRUE);
111 uth_cond_var_free(args->cv);
112 uth_mutex_free(args->mtx);
116 bool test_broadcast(void)
118 #define NR_WAITERS 20
119 struct common_args local_a, *args = &local_a;
120 pthread_t bcaster, waiters[NR_WAITERS];
121 void *bcast_join, *wait_joins[NR_WAITERS];
124 args->cv = uth_cond_var_alloc();
125 args->mtx = uth_mutex_alloc();
127 args->wait_sleep = 0;
128 args->sig_sleep = 1000;
130 for (int i = 0; i < NR_WAITERS; i++) {
131 ret = pthread_create(&waiters[i], 0, __cv_waiter, args);
134 ret = pthread_create(&bcaster, 0, __cv_broadcaster, args);
137 ret = pthread_join(bcaster, &bcast_join);
139 UT_ASSERT_M("Broadcaster Failed", bcast_join == PTH_TEST_TRUE);
140 for (int i = 0; i < NR_WAITERS; i++) {
141 ret = pthread_join(waiters[i], &wait_joins[i]);
143 UT_ASSERT_M("Waiter Failed", wait_joins[i] == PTH_TEST_TRUE);
146 uth_cond_var_free(args->cv);
147 uth_mutex_free(args->mtx);
150 /* <--- End definition of test cases ---> */
152 struct utest utests[] = {
153 UTEST_REG(signal_no_wait),
155 UTEST_REG(broadcast),
157 int num_utests = sizeof(utests) / sizeof(struct utest);
159 int main(int argc, char *argv[])
161 // Run test suite passing it all the args as whitelist of what tests to run.
162 char **whitelist = &argv[1];
163 int whitelist_len = argc - 1;
165 RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len);