1
/* ``The contents of this file are subject to the Erlang Public License,
2
* Version 1.1, (the "License"); you may not use this file except in
3
* compliance with the License. You should have received a copy of the
4
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
7
* Software distributed under the License is distributed on an "AS IS"
8
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
* the License for the specific language governing rights and limitations
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
19
#include "testcase_driver.h"
28
#define NO_OF_THREADS 2
34
static ErlDrvMutex *mtx;
35
static ErlDrvCond *cnd;
36
static int need_join[NO_OF_THREADS];
37
static ErlDrvTid tid[NO_OF_THREADS];
38
static ErlDrvThreadOpts *topts;
45
do_sleep(unsigned secs)
48
Sleep((DWORD) secs*1000);
54
static void *tf0(void *vta)
56
if (((thr_arg_t *) vta)->n == 0) {
58
erl_drv_mutex_lock(mtx);
60
erl_drv_cond_wait(cnd, mtx);
63
erl_drv_mutex_unlock(mtx);
69
erl_drv_cond_wait(cnd, mtx);
72
erl_drv_mutex_unlock(mtx);
78
erl_drv_mutex_unlock(mtx);
79
if (erl_drv_equal_tids(erl_drv_thread_self(), tid[0]))
83
return (void *) &res_tf0;
87
static void *tf1(void *vta)
90
if (((thr_arg_t *) vta)->n == 1) {
92
erl_drv_mutex_lock(mtx);
94
erl_drv_cond_wait(cnd, mtx);
97
erl_drv_mutex_unlock(mtx);
103
erl_drv_cond_wait(cnd, mtx);
106
erl_drv_mutex_unlock(mtx);
112
erl_drv_mutex_unlock(mtx);
114
if (erl_drv_equal_tids(erl_drv_thread_self(), tid[1]))
117
erl_drv_thread_exit((void *) &res_tf1);
125
testcase_run(TestCaseState_t *tcs)
133
driver_system_info(&sinfo, sizeof(ErlDrvSysInfo));
134
if (!sinfo.thread_support)
135
testcase_skipped(tcs, "No thread support; nothing to test");
137
testcase_printf(tcs, "Initializing\n");
141
my_tid = erl_drv_thread_self();
143
for (i = 0; i < NO_OF_THREADS; i++)
151
/* Create mutex and cond */
152
mtx = erl_drv_mutex_create("mutex");
154
cnd = erl_drv_cond_create("cond");
156
topts = erl_drv_thread_opts_create("thread opts");
158
topts->suggested_stack_size = 0; /* As small as possible */
160
testcase_printf(tcs, "Creating threads 0 & 1\n");
162
/* Create the threads */
164
r = erl_drv_thread_create("thread 0", &tid[0], tf0, (void *) &ta[0], topts);
169
r = erl_drv_thread_create("thread 1", &tid[1], tf1, (void *) &ta[1], NULL);
173
testcase_printf(tcs, "Testing tids\n");
175
ASSERT(tcs, !erl_drv_equal_tids(tid[0], my_tid));
176
ASSERT(tcs, !erl_drv_equal_tids(tid[1], my_tid));
177
ASSERT(tcs, !erl_drv_equal_tids(tid[0], tid[1]));
178
ASSERT(tcs, erl_drv_equal_tids(my_tid, erl_drv_thread_self()));
180
testcase_printf(tcs, "Testing mutex/cond\n");
182
/* Make sure the threads waits on cond wait */
185
erl_drv_mutex_lock(mtx);
187
ASSERT_CLNUP(tcs, cw_passed == 0, erl_drv_mutex_unlock(mtx));
189
/* Let one thread pass one cond wait */
190
erl_drv_cond_signal(cnd);
192
erl_drv_mutex_unlock(mtx);
196
erl_drv_mutex_lock(mtx);
198
ASSERT_CLNUP(tcs, cw_passed == 1, erl_drv_mutex_unlock(mtx));
201
/* Let both threads pass one cond wait */
202
erl_drv_cond_broadcast(cnd);
204
erl_drv_mutex_unlock(mtx);
208
erl_drv_mutex_lock(mtx);
210
ASSERT_CLNUP(tcs, cw_passed == 3, erl_drv_mutex_unlock(mtx));
213
/* Let the thread that only have passed one cond wait pass the other one */
214
erl_drv_cond_signal(cnd);
216
erl_drv_mutex_unlock(mtx);
220
erl_drv_mutex_lock(mtx);
222
ASSERT_CLNUP(tcs, cw_passed == 4, erl_drv_mutex_unlock(mtx));
225
testcase_printf(tcs, "Testing join\n");
227
/* Both threads should have passed both cond waits and exited;
228
join them and check returned values */
230
erl_drv_thread_join(tid[0], &tres[0]);
231
ASSERT_CLNUP(tcs, r == 0, erl_drv_mutex_unlock(mtx));
234
ASSERT_CLNUP(tcs, tres[0] == &res_tf0, erl_drv_mutex_unlock(mtx));
235
ASSERT_CLNUP(tcs, res_tf0 == 0, erl_drv_mutex_unlock(mtx));
237
r = erl_drv_thread_join(tid[1], &tres[1]);
238
ASSERT_CLNUP(tcs, r == 0, erl_drv_mutex_unlock(mtx));
241
ASSERT_CLNUP(tcs, tres[1] == &res_tf1, erl_drv_mutex_unlock(mtx));
242
ASSERT_CLNUP(tcs, res_tf1 == 1, erl_drv_mutex_unlock(mtx));
244
/* Test signaling when noone waits */
246
erl_drv_cond_signal(cnd);
248
/* Test broadcasting when noone waits */
250
erl_drv_cond_broadcast(cnd);
252
erl_drv_mutex_unlock(mtx);
254
erl_drv_mutex_destroy(mtx);
257
erl_drv_cond_destroy(cnd);
260
erl_drv_thread_opts_destroy(topts);
263
testcase_printf(tcs, "done\n");
273
testcase_cleanup(TestCaseState_t *tcs)
276
for (i = 0; i < NO_OF_THREADS; i++) {
278
erl_drv_mutex_lock(mtx);
280
erl_drv_cond_broadcast(cnd);
281
erl_drv_mutex_unlock(mtx);
282
erl_drv_thread_join(tid[i], NULL);
286
erl_drv_mutex_destroy(mtx);
288
erl_drv_cond_destroy(cnd);
290
erl_drv_thread_opts_destroy(topts);