summaryrefslogtreecommitdiff
path: root/usr/src/lib/libfakekernel/common/cond.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libfakekernel/common/cond.c')
-rw-r--r--usr/src/lib/libfakekernel/common/cond.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/usr/src/lib/libfakekernel/common/cond.c b/usr/src/lib/libfakekernel/common/cond.c
new file mode 100644
index 0000000000..0ed2ea7b73
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/cond.c
@@ -0,0 +1,180 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * condvar(9f)
+ */
+
+/* This is the API we're emulating */
+#include <sys/condvar.h>
+
+#include <sys/errno.h>
+#include <sys/debug.h>
+#include <sys/thread.h>
+
+/* avoiding synch.h */
+int _lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *);
+int _lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
+int _lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
+int _lwp_cond_signal(lwp_cond_t *);
+int _lwp_cond_broadcast(lwp_cond_t *);
+
+
+extern clock_t ddi_get_lbolt(void);
+extern void clock2ts(clock_t, timespec_t *);
+
+static int cv__wait(kcondvar_t *, kmutex_t *, int);
+static clock_t cv__twait(kcondvar_t *, kmutex_t *, clock_t, int);
+
+static const lwp_cond_t default_cv =
+ {{{0, 0, 0, 0}, USYNC_THREAD, _COND_MAGIC}, 0};
+
+
+/* ARGSUSED */
+void
+cv_init(kcondvar_t *cv, char *name, kcv_type_t typ, void *arg)
+{
+ *cv = default_cv;
+}
+
+/* ARGSUSED */
+void
+cv_destroy(kcondvar_t *cv)
+{
+}
+
+void
+cv_signal(kcondvar_t *cv)
+{
+ (void) _lwp_cond_signal(cv);
+}
+
+void
+cv_broadcast(kcondvar_t *cv)
+{
+ (void) _lwp_cond_broadcast(cv);
+}
+
+void
+cv_wait(kcondvar_t *cv, kmutex_t *mp)
+{
+ (void) cv__wait(cv, mp, 0);
+}
+
+int
+cv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
+{
+ return (cv__wait(cv, mp, 1));
+}
+
+int
+cv__wait(kcondvar_t *cv, kmutex_t *mp, int sigok)
+{
+ int err;
+
+top:
+ ASSERT(mp->m_owner == _curthread());
+ mp->m_owner = _KTHREAD_INVALID;
+ err = _lwp_cond_wait(cv, &mp->m_lock);
+ mp->m_owner = _curthread();
+
+ if (err == 0)
+ return (1);
+ if (err == EINTR) {
+ if (sigok)
+ return (0);
+ goto top;
+ }
+ return (-1);
+}
+
+clock_t
+cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
+{
+ clock_t delta;
+
+ delta = abstime - ddi_get_lbolt();
+ return (cv__twait(cv, mp, delta, 0));
+}
+
+clock_t
+cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
+{
+ clock_t delta;
+
+ delta = abstime - ddi_get_lbolt();
+ return (cv__twait(cv, mp, delta, 1));
+}
+
+clock_t
+cv_reltimedwait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, time_res_t res)
+{
+ _NOTE(ARGUNUSED(res))
+
+ return (cv__twait(cv, mp, delta, 0));
+}
+
+clock_t
+cv_reltimedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t delta,
+ time_res_t res)
+{
+ _NOTE(ARGUNUSED(res))
+
+ return (cv__twait(cv, mp, delta, 1));
+}
+
+/*
+ * Factored out implementation of all the cv_*timedwait* functions.
+ * Note that the delta passed in is relative to the (simulated)
+ * current time reported by ddi_get_lbolt(). Convert that to
+ * timespec format and keep calling _lwp_cond_reltimedwait,
+ * which (NB!) decrements that delta in-place!
+ */
+static clock_t
+cv__twait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, int sigok)
+{
+ timestruc_t ts;
+ int err;
+
+ if (delta <= 0)
+ return (-1);
+
+ clock2ts(delta, &ts);
+
+top:
+ if (ts.tv_sec == 0 && ts.tv_nsec == 0)
+ return (-1);
+
+ ASSERT(mp->m_owner == _curthread());
+ mp->m_owner = _KTHREAD_INVALID;
+ err = _lwp_cond_reltimedwait(cv, &mp->m_lock, &ts);
+ mp->m_owner = _curthread();
+
+ switch (err) {
+ case 0:
+ return (1);
+ case EINTR:
+ if (sigok)
+ return (0);
+ goto top;
+ default:
+ ASSERT(0);
+ /* FALLTHROUGH */
+ case ETIME:
+ break;
+ }
+
+ return (-1);
+}