2 * Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
22 #include "amsemaphore.h"
23 #include "testutils.h"
27 * test that decrement waits properly
30 struct test_decr_wait_data {
32 gboolean increment_called;
36 test_decr_wait_thread(gpointer datap)
38 struct test_decr_wait_data *data = datap;
41 amsemaphore_decrement(data->sem, 20);
43 /* if increment hasn't been called yet, that's an error. */
44 if (!data->increment_called)
45 return GINT_TO_POINTER(0);
47 return GINT_TO_POINTER(1);
54 struct test_decr_wait_data data = { NULL, FALSE };
57 data.sem = amsemaphore_new_with_value(10),
59 th = g_thread_create(test_decr_wait_thread, (gpointer)&data, TRUE, NULL);
61 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
62 g_usleep(G_USEC_PER_SEC / 4);
64 /* and then increment the semaphore enough that the decrement can succeed */
65 data.increment_called = TRUE;
66 amsemaphore_increment(data.sem, 10);
68 /* join the thread and see how it fared. */
69 rv = GPOINTER_TO_INT(g_thread_join(th));
71 amsemaphore_free(data.sem);
78 * test that amsemaphore_wait_empty waits properly
82 test_wait_empty_thread(gpointer datap)
84 amsemaphore_t *sem = datap;
87 amsemaphore_decrement(sem, 20);
89 /* value should be 10 now (decremented from 30) */
91 return GINT_TO_POINTER(1);
94 g_usleep(G_USEC_PER_SEC / 4);
96 /* decrement those last 10, which should trigger the zero */
97 amsemaphore_decrement(sem, 10);
99 return GINT_TO_POINTER(0);
103 test_wait_empty(void)
106 amsemaphore_t *sem = amsemaphore_new_with_value(10);
109 th = g_thread_create(test_wait_empty_thread, (gpointer)sem, TRUE, NULL);
111 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
112 g_usleep(G_USEC_PER_SEC / 4);
114 /* add another 10, so decrement can hit zero next time it's called */
115 amsemaphore_increment(sem, 10);
117 /* and wait on the semaphore emptying */
118 amsemaphore_wait_empty(sem);
120 /* join the thread and see how it fared. */
121 rv = GPOINTER_TO_INT(g_thread_join(th));
123 amsemaphore_free(sem);
129 * test that amsemaphore_force_adjust correctly wakes both
130 * amsemaphore_decrement and amsemaphore_wait_empty.
134 test_force_adjust_thread(gpointer datap)
136 amsemaphore_t *sem = datap;
138 /* this should block */
139 amsemaphore_decrement(sem, 20);
141 /* and this should block, too - it's fun */
142 amsemaphore_wait_empty(sem);
148 test_force_adjust(void)
151 amsemaphore_t *sem = amsemaphore_new_with_value(10);
153 th = g_thread_create(test_force_adjust_thread, (gpointer)sem, TRUE, NULL);
155 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
156 g_usleep(G_USEC_PER_SEC / 4);
158 /* add another 20, so decrement can proceed, but leave the value at 10 */
159 amsemaphore_force_adjust(sem, 20);
161 /* sleep to give amsemaphore_wait_empty() a chance to block (or not). */
162 g_usleep(G_USEC_PER_SEC / 4);
164 /* and empty out the semaphore */
165 amsemaphore_force_adjust(sem, -10);
169 amsemaphore_free(sem);
171 /* it we didn't hang yet, it's all good */
176 * test that amsemaphore_force_set correctly wakes both
177 * amsemaphore_decrement and amsemaphore_wait_empty.
181 test_force_set_thread(gpointer datap)
183 amsemaphore_t *sem = datap;
185 /* this should block */
186 amsemaphore_decrement(sem, 20);
188 /* and this should block, too - it's fun */
189 amsemaphore_wait_empty(sem);
198 amsemaphore_t *sem = amsemaphore_new_with_value(10);
200 th = g_thread_create(test_force_set_thread, (gpointer)sem, TRUE, NULL);
202 /* sleep to give amsemaphore_decrement() a chance to block (or not). */
203 g_usleep(G_USEC_PER_SEC / 4);
205 /* set it to 30, so decrement can proceed, but leave the value at 10 */
206 amsemaphore_force_set(sem, 30);
208 /* sleep to give amsemaphore_wait_empty() a chance to block (or not). */
209 g_usleep(G_USEC_PER_SEC / 4);
211 /* and empty out the semaphore */
212 amsemaphore_force_set(sem, 0);
216 amsemaphore_free(sem);
218 /* it we didn't hang yet, it's all good */
227 main(int argc, char **argv)
229 #if defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)
230 static TestUtilsTest tests[] = {
231 TU_TEST(test_decr_wait, 90),
232 TU_TEST(test_wait_empty, 90),
233 TU_TEST(test_force_adjust, 90),
234 TU_TEST(test_force_set, 90),
240 return testutils_run_tests(argc, argv, tests);
242 g_fprintf(stderr, "No thread support on this platform -- nothing to test\n");