aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/obsolete_SUITE_data/erl_threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/obsolete_SUITE_data/erl_threads.c')
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/erl_threads.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c
new file mode 100644
index 0000000000..27a5163121
--- /dev/null
+++ b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c
@@ -0,0 +1,302 @@
+/* ``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"
+
+#ifndef __WIN32__
+
+#define NO_OF_THREADS 2
+
+#include <unistd.h>
+#include <errno.h>
+
+static int die;
+static int cw_passed;
+static int res_tf0;
+static int res_tf1;
+static erl_mutex_t mtx;
+static erl_cond_t cnd;
+static erl_thread_t tid[NO_OF_THREADS];
+static int need_join[NO_OF_THREADS];
+
+typedef struct {
+ int n;
+} thr_arg_t;
+
+
+static void *tf0(void *vta)
+{
+ int r;
+
+ if (((thr_arg_t *) vta)->n != 0)
+ goto fail;
+
+ r = erts_mutex_lock(mtx);
+ if (r != 0) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ r = erts_cond_wait(cnd, mtx);
+ if (r != 0 || die) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ cw_passed++;
+
+ r = erts_cond_wait(cnd, mtx);
+ if (r != 0 || die) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ cw_passed++;
+
+ r = erts_mutex_unlock(mtx);
+ if (r != 0)
+ goto fail;
+
+ res_tf0 = 0;
+
+ return (void *) &res_tf0;
+
+ fail:
+ return NULL;
+}
+
+
+static void *tf1(void *vta)
+{
+ int r;
+
+ if (((thr_arg_t *) vta)->n != 1)
+ goto fail;
+
+ r = erts_mutex_lock(mtx);
+ if (r != 0) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ r = erts_cond_wait(cnd, mtx);
+ if (r != 0 || die) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ cw_passed++;
+
+ r = erts_cond_wait(cnd, mtx);
+ if (r != 0 || die) {
+ erts_mutex_unlock(mtx);
+ goto fail;
+ }
+
+ cw_passed++;
+
+ r = erts_mutex_unlock(mtx);
+ if (r != 0)
+ goto fail;
+
+ res_tf1 = 1;
+
+ erts_thread_exit((void *) &res_tf1);
+
+ res_tf1 = 4711;
+
+ fail:
+ return NULL;
+}
+
+#endif /* #ifndef __WIN32__ */
+
+void
+testcase_run(TestCaseState_t *tcs)
+{
+#ifdef __WIN32__
+ testcase_skipped(tcs, "Nothing to test; not supported on windows.");
+#else
+ int i, r;
+ void *tres[NO_OF_THREADS];
+ thr_arg_t ta[NO_OF_THREADS];
+ erl_thread_t t1;
+
+ die = 0;
+ cw_passed = 0;
+
+ for (i = 0; i < NO_OF_THREADS; i++)
+ need_join[i] = 0;
+
+ res_tf0 = 17;
+ res_tf1 = 17;
+
+ cnd = mtx = NULL;
+
+ /* Create mutex and cond */
+ mtx = erts_mutex_create();
+ ASSERT(tcs, mtx);
+ cnd = erts_cond_create();
+ ASSERT(tcs, cnd);
+
+ /* Create the threads */
+ ta[0].n = 0;
+ r = erts_thread_create(&tid[0], tf0, (void *) &ta[0], 0);
+ ASSERT(tcs, r == 0);
+ need_join[0] = 1;
+
+ ta[1].n = 1;
+ r = erts_thread_create(&tid[1], tf1, (void *) &ta[1], 0);
+ ASSERT(tcs, r == 0);
+ need_join[1] = 1;
+
+ /* Make sure the threads waits on cond wait */
+ sleep(1);
+
+ r = erts_mutex_lock(mtx);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ ASSERT_CLNUP(tcs, cw_passed == 0, (void) erts_mutex_unlock(mtx));
+
+
+ /* Let one thread pass one cond wait */
+ r = erts_cond_signal(cnd);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ r = erts_mutex_unlock(mtx);
+ ASSERT(tcs, r == 0);
+
+ sleep(1);
+
+ r = erts_mutex_lock(mtx);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ ASSERT_CLNUP(tcs, cw_passed == 1, (void) erts_mutex_unlock(mtx));
+
+
+ /* Let both threads pass one cond wait */
+ r = erts_cond_broadcast(cnd);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ r = erts_mutex_unlock(mtx);
+ ASSERT(tcs, r == 0);
+
+ sleep(1);
+
+ r = erts_mutex_lock(mtx);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ ASSERT_CLNUP(tcs, cw_passed == 3, (void) erts_mutex_unlock(mtx));
+
+
+ /* Let the thread that only have passed one cond wait pass the other one */
+ r = erts_cond_signal(cnd);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ r = erts_mutex_unlock(mtx);
+ ASSERT(tcs, r == 0);
+
+ sleep(1);
+
+ r = erts_mutex_lock(mtx);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ ASSERT_CLNUP(tcs, cw_passed == 4, (void) erts_mutex_unlock(mtx));
+
+ /* Both threads should have passed both cond waits and exited;
+ join them and check returned values */
+
+ r = erts_thread_join(tid[0], &tres[0]);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+ need_join[0] = 0;
+
+ ASSERT_CLNUP(tcs, tres[0] == &res_tf0, (void) erts_mutex_unlock(mtx));
+ ASSERT_CLNUP(tcs, res_tf0 == 0, (void) erts_mutex_unlock(mtx));
+
+ r = erts_thread_join(tid[1], &tres[1]);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+ need_join[1] = 0;
+
+ ASSERT_CLNUP(tcs, tres[1] == &res_tf1, (void) erts_mutex_unlock(mtx));
+ ASSERT_CLNUP(tcs, res_tf1 == 1, (void) erts_mutex_unlock(mtx));
+
+ /* Test signaling when noone waits */
+
+ r = erts_cond_signal(cnd);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ /* Test broadcasting when noone waits */
+
+ r = erts_cond_broadcast(cnd);
+ ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx));
+
+ /* erts_cond_timedwait() not supported anymore */
+ r = erts_cond_timedwait(cnd, mtx, 1000);
+ ASSERT_CLNUP(tcs, r != 0, (void) erts_mutex_unlock(mtx));
+ ASSERT_CLNUP(tcs,
+ strcmp(erl_errno_id(r), "enotsup") == 0,
+ (void) erts_mutex_unlock(mtx));
+
+ r = erts_mutex_unlock(mtx);
+ ASSERT(tcs, r == 0);
+
+ r = erts_mutex_destroy(mtx);
+ ASSERT(tcs, r == 0);
+ mtx = NULL;
+
+ r = erts_cond_destroy(cnd);
+ ASSERT(tcs, r == 0);
+ cnd = NULL;
+
+ /* ... */
+ t1 = erts_thread_self();
+
+ if (cw_passed == 4711) {
+ /* We don't want to execute this just check that the
+ symbol/symbols is/are defined */
+ erts_thread_kill(t1);
+ }
+
+#endif /* #ifndef __WIN32__ */
+}
+
+char *
+testcase_name(void)
+{
+ return "erl_threads";
+}
+
+void
+testcase_cleanup(TestCaseState_t *tcs)
+{
+ int i;
+ for (i = 0; i < NO_OF_THREADS; i++) {
+ if (need_join[i]) {
+ erts_mutex_lock(mtx);
+ die = 1;
+ erts_cond_broadcast(cnd);
+ erts_mutex_unlock(mtx);
+ erts_thread_join(tid[1], NULL);
+ }
+ }
+ if (mtx)
+ erts_mutex_destroy(mtx);
+ if (cnd)
+ erts_cond_destroy(cnd);
+}
+