aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c')
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c214
1 files changed, 214 insertions, 0 deletions
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 <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#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);
+}