2 * Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
23 #include "amsemaphore.h"
24 #include "testutils.h"
28 * test that decrement waits properly
31 struct test_decr_wait_data {
33 gboolean increment_called;
37 test_decr_wait_thread(gpointer datap)
39 struct test_decr_wait_data *data = datap;
42 amsemaphore_decrement(data->sem, 20);
44 /* if increment hasn't been called yet, that's an error. */
45 if (!data->increment_called)
46 return GINT_TO_POINTER(0);
48 return GINT_TO_POINTER(1);
55 struct test_decr_wait_data data = { NULL, FALSE };
58 data.sem = amsemaphore_new_with_value(10),
60 th = g_thread_create(test_decr_wait_thread, (gpointer)&data, TRUE, NULL);
62 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
63 g_usleep(G_USEC_PER_SEC / 4);
65 /* and then increment the semaphore enough that the decrement can succeed */
66 data.increment_called = TRUE;
67 amsemaphore_increment(data.sem, 10);
69 /* join the thread and see how it fared. */
70 rv = GPOINTER_TO_INT(g_thread_join(th));
72 amsemaphore_free(data.sem);
79 * test that amsemaphore_wait_empty waits properly
83 test_wait_empty_thread(gpointer datap)
85 amsemaphore_t *sem = datap;
88 amsemaphore_decrement(sem, 20);
90 /* value should be 10 now (decremented from 30) */
92 return GINT_TO_POINTER(1);
95 g_usleep(G_USEC_PER_SEC / 4);
97 /* decrement those last 10, which should trigger the zero */
98 amsemaphore_decrement(sem, 10);
100 return GINT_TO_POINTER(0);
104 test_wait_empty(void)
107 amsemaphore_t *sem = amsemaphore_new_with_value(10);
110 th = g_thread_create(test_wait_empty_thread, (gpointer)sem, TRUE, NULL);
112 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
113 g_usleep(G_USEC_PER_SEC / 4);
115 /* add another 10, so decrement can hit zero next time it's called */
116 amsemaphore_increment(sem, 10);
118 /* and wait on the semaphore emptying */
119 amsemaphore_wait_empty(sem);
121 /* join the thread and see how it fared. */
122 rv = GPOINTER_TO_INT(g_thread_join(th));
124 amsemaphore_free(sem);
130 * test that amsemaphore_force_adjust correctly wakes both
131 * amsemaphore_decrement and amsemaphore_wait_empty.
135 test_force_adjust_thread(gpointer datap)
137 amsemaphore_t *sem = datap;
139 /* this should block */
140 amsemaphore_decrement(sem, 20);
142 /* and this should block, too - it's fun */
143 amsemaphore_wait_empty(sem);
149 test_force_adjust(void)
152 amsemaphore_t *sem = amsemaphore_new_with_value(10);
154 th = g_thread_create(test_force_adjust_thread, (gpointer)sem, TRUE, NULL);
156 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
157 g_usleep(G_USEC_PER_SEC / 4);
159 /* add another 20, so decrement can proceed, but leave the value at 10 */
160 amsemaphore_force_adjust(sem, 20);
162 /* sleep to give amsemaphore_wait_empty() a chance to block (or not). */
163 g_usleep(G_USEC_PER_SEC / 4);
165 /* and empty out the semaphore */
166 amsemaphore_force_adjust(sem, -10);
170 amsemaphore_free(sem);
172 /* it we didn't hang yet, it's all good */
177 * test that amsemaphore_force_set correctly wakes both
178 * amsemaphore_decrement and amsemaphore_wait_empty.
182 test_force_set_thread(gpointer datap)
184 amsemaphore_t *sem = datap;
186 /* this should block */
187 amsemaphore_decrement(sem, 20);
189 /* and this should block, too - it's fun */
190 amsemaphore_wait_empty(sem);
199 amsemaphore_t *sem = amsemaphore_new_with_value(10);
201 th = g_thread_create(test_force_set_thread, (gpointer)sem, TRUE, NULL);
203 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
204 g_usleep(G_USEC_PER_SEC / 4);
206 /* set it to 30, so decrement can proceed, but leave the value at 10 */
207 amsemaphore_force_set(sem, 30);
209 /* sleep to give amsemaphore_wait_empty() a chance to block (or not). */
210 g_usleep(G_USEC_PER_SEC / 4);
212 /* and empty out the semaphore */
213 amsemaphore_force_set(sem, 0);
217 amsemaphore_free(sem);
219 /* it we didn't hang yet, it's all good */
228 main(int argc, char **argv)
230 #if defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)
231 static TestUtilsTest tests[] = {
232 TU_TEST(test_decr_wait, 90),
233 TU_TEST(test_wait_empty, 90),
234 TU_TEST(test_force_adjust, 90),
235 TU_TEST(test_force_set, 90),
241 return testutils_run_tests(argc, argv, tests);
243 g_fprintf(stderr, "No thread support on this platform -- nothing to test\n");