From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- .../test/erl_drv_thread_SUITE_data/rwlock.c | 214 +++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c (limited to 'erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c') diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c b/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c new file mode 100644 index 0000000000..064f52c16b --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c @@ -0,0 +1,214 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" + +#ifdef __WIN32__ +#include +#else +#include +#endif +#include + +#define NO_OF_THREADS 17 + +struct { + int alive; + ErlDrvTid tid; +} test_thr[NO_OF_THREADS] = {0}; + + +static int die; +static int ready; +static int rlocked; +static int rwlocked; +static int do_rlock; +static int do_rwlock; +static ErlDrvMutex *mtx; +static ErlDrvCond *cnd; +static ErlDrvRWLock *rwlck; + +static void +do_sleep(unsigned secs) +{ +#ifdef __WIN32__ + Sleep((DWORD) secs*1000); +#else + sleep(secs); +#endif +} + +static void *tf(void *unused) +{ + + erl_drv_mutex_lock(mtx); + ready++; + if (ready == NO_OF_THREADS) + erl_drv_cond_broadcast(cnd); + while (!do_rlock) + erl_drv_cond_wait(cnd, mtx); + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_rlock(rwlck); + + /* make sure everyone rlocks at the same time */ + erl_drv_mutex_lock(mtx); + rlocked++; + if (rlocked == NO_OF_THREADS) + erl_drv_cond_broadcast(cnd); + while (rlocked != NO_OF_THREADS && !die) + erl_drv_cond_wait(cnd, mtx); + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_runlock(rwlck); + + erl_drv_mutex_lock(mtx); + while (!do_rwlock && !die) + erl_drv_cond_wait(cnd, mtx); + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_rwlock(rwlck); + rwlocked++; + erl_drv_rwlock_rwunlock(rwlck); + + return NULL; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i, r; + ErlDrvSysInfo sinfo; + + driver_system_info(&sinfo, sizeof(ErlDrvSysInfo)); + if (!sinfo.thread_support) + testcase_skipped(tcs, "No thread support; nothing to test"); + + testcase_printf(tcs, "Initializing\n"); + die = 0; + ready = 0; + rlocked = 0; + rwlocked = 0; + do_rlock = 0; + do_rwlock = 0; + + mtx = erl_drv_mutex_create("test mutex"); + cnd = erl_drv_cond_create("test cond"); + rwlck = erl_drv_rwlock_create("test rwlock"); + ASSERT(tcs, mtx && cnd && rwlck); + + testcase_printf(tcs, "Creating %d threads\n", NO_OF_THREADS); + /* Create the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + char name[100]; + sprintf(name, "thread %d", i); + r = erl_drv_thread_create(name, + &test_thr[i].tid, + tf, + NULL, + NULL); + ASSERT(tcs, r == 0); + test_thr[i].alive = 1; + } + + testcase_printf(tcs, "Testing\n"); + erl_drv_rwlock_rwlock(rwlck); + + erl_drv_mutex_lock(mtx); + while (ready != NO_OF_THREADS) + erl_drv_cond_wait(cnd, mtx); + do_rlock = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, + rlocked == 0, + do { + erl_drv_mutex_unlock(mtx); + erl_drv_rwlock_rwunlock(rwlck); + } while (0)); + + erl_drv_mutex_unlock(mtx); + erl_drv_rwlock_rwunlock(rwlck); + + do_sleep(2); + + erl_drv_mutex_lock(mtx); + ASSERT_CLNUP(tcs, rlocked == NO_OF_THREADS, erl_drv_mutex_unlock(mtx)); + do_rwlock = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + + testcase_printf(tcs, "Joining threads\n"); + /* Join the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + void *res; + r = erl_drv_thread_join(test_thr[i].tid, NULL); + test_thr[i].alive = 0; + ASSERT(tcs, r == 0); + } + + erl_drv_mutex_lock(mtx); + ASSERT_CLNUP(tcs, rwlocked == NO_OF_THREADS, erl_drv_mutex_unlock(mtx)); + erl_drv_mutex_unlock(mtx); + + erl_drv_mutex_destroy(mtx); + mtx = NULL; + erl_drv_cond_destroy(cnd); + cnd = NULL; + erl_drv_rwlock_destroy(rwlck); + rwlck = NULL; + + testcase_printf(tcs, "done\n"); +} + +char * +testcase_name(void) +{ + return "rwlock"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) { + if (test_thr[i].alive) { + erl_drv_mutex_lock(mtx); + die = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + erl_drv_thread_join(test_thr[i].tid, NULL); + } + } + + if (mtx) + erl_drv_mutex_destroy(mtx); + if (cnd) + erl_drv_cond_destroy(cnd); + if (rwlck) + erl_drv_rwlock_destroy(rwlck); +} -- cgit v1.2.3