2 * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved.
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 2.1 as
6 * published by the Free Software Foundation.
8 * This library 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 Lesser General Public
11 * License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17 * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
21 #include "semaphore.h"
26 * test that decrement waits properly
29 struct test_decr_wait_data {
31 gboolean increment_called;
35 test_decr_wait_thread(gpointer datap)
37 struct test_decr_wait_data *data = datap;
40 semaphore_decrement(data->sem, 20);
42 /* if increment hasn't been called yet, that's an error. */
43 if (!data->increment_called)
44 return GINT_TO_POINTER(0);
46 return GINT_TO_POINTER(1);
53 struct test_decr_wait_data data = { NULL, FALSE };
56 data.sem = semaphore_new_with_value(10),
58 /* die after 10 seconds (default signal disposition is to fail) */
61 th = g_thread_create(test_decr_wait_thread, (gpointer)&data, TRUE, NULL);
63 /* sleep to give semaphore_decrement() a chance to block (or not). */
64 g_usleep(G_USEC_PER_SEC / 4);
66 /* and then increment the semaphore enough that the decrement can succeed */
67 data.increment_called = TRUE;
68 semaphore_increment(data.sem, 10);
70 /* join the thread and see how it fared. */
71 rv = GPOINTER_TO_INT(g_thread_join(th));
73 semaphore_free(data.sem);
76 printf(" PASS: semaphore-test.test_decr_wait\n");
79 printf(" FAIL: semaphore-test.test_decr_wait\n");
86 * test that semaphore_wait_empty waits properly
90 test_wait_empty_thread(gpointer datap)
92 semaphore_t *sem = datap;
95 semaphore_decrement(sem, 20);
97 /* value should be 10 now (decremented from 30) */
99 return GINT_TO_POINTER(1);
101 /* sleep for a bit */
102 g_usleep(G_USEC_PER_SEC / 4);
104 /* decrement those last 10, which should trigger the zero */
105 semaphore_decrement(sem, 10);
107 return GINT_TO_POINTER(0);
111 test_wait_empty(void)
114 semaphore_t *sem = semaphore_new_with_value(10);
117 /* die after 10 seconds (default signal disposition is to fail) */
120 th = g_thread_create(test_wait_empty_thread, (gpointer)sem, TRUE, NULL);
122 /* sleep to give semaphore_decrement() a chance to block (or not). */
123 g_usleep(G_USEC_PER_SEC / 4);
125 /* add another 10, so decrement can hit zero next time it's called */
126 semaphore_increment(sem, 10);
128 /* and wait on the semaphore emptying */
129 semaphore_wait_empty(sem);
131 /* join the thread and see how it fared. */
132 rv = GPOINTER_TO_INT(g_thread_join(th));
137 printf(" PASS: semaphore-test.test_wait_empty\n");
140 printf(" FAIL: semaphore-test.test_wait_empty\n");
146 * test that semaphore_force_adjust correctly wakes both
147 * semaphore_decrement and semaphore_wait_empty.
151 test_force_adjust_thread(gpointer datap)
153 semaphore_t *sem = datap;
155 /* this should block */
156 semaphore_decrement(sem, 20);
158 /* and this should block, too - it's fun */
159 semaphore_wait_empty(sem);
165 test_force_adjust(void)
168 semaphore_t *sem = semaphore_new_with_value(10);
170 /* die after 10 seconds (default signal disposition is to fail) */
173 th = g_thread_create(test_force_adjust_thread, (gpointer)sem, TRUE, NULL);
175 /* sleep to give semaphore_decrement() a chance to block (or not). */
176 g_usleep(G_USEC_PER_SEC / 4);
178 /* add another 20, so decrement can proceed, but leave the value at 10 */
179 semaphore_force_adjust(sem, 20);
181 /* sleep to give semaphore_wait_empty() a chance to block (or not). */
182 g_usleep(G_USEC_PER_SEC / 4);
184 /* and empty out the semaphore */
185 semaphore_force_adjust(sem, -10);
191 /* it we didn't hang yet, it's all good */
192 printf(" PASS: semaphore-test.test_force_adjust\n");
197 * test that semaphore_force_set correctly wakes both
198 * semaphore_decrement and semaphore_wait_empty.
202 test_force_set_thread(gpointer datap)
204 semaphore_t *sem = datap;
206 /* this should block */
207 semaphore_decrement(sem, 20);
209 /* and this should block, too - it's fun */
210 semaphore_wait_empty(sem);
219 semaphore_t *sem = semaphore_new_with_value(10);
221 /* die after 10 seconds (default signal disposition is to fail) */
224 th = g_thread_create(test_force_set_thread, (gpointer)sem, TRUE, NULL);
226 /* sleep to give semaphore_decrement() a chance to block (or not). */
227 g_usleep(G_USEC_PER_SEC / 4);
229 /* set it to 30, so decrement can proceed, but leave the value at 10 */
230 semaphore_force_set(sem, 30);
232 /* sleep to give semaphore_wait_empty() a chance to block (or not). */
233 g_usleep(G_USEC_PER_SEC / 4);
235 /* and empty out the semaphore */
236 semaphore_force_set(sem, 0);
242 /* it we didn't hang yet, it's all good */
243 printf(" PASS: semaphore-test.test_force_set\n");
254 gboolean pass = TRUE;
256 #if defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)
257 amanda_thread_init();
259 pass = test_decr_wait() && pass;
260 pass = test_wait_empty() && pass;
261 pass = test_force_adjust() && pass;
262 pass = test_force_set() && pass;
266 printf("No thread support on this platform -- nothing to test\n");