b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This file and its contents are supplied under the terms of the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You may only use this file in accordance with the terms of version
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * 1.0 of the CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * A full copy of the text of the CDDL should have accompanied this
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * source. A copy of the CDDL is also available via the Internet at
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * http://www.illumos.org/license/CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * condvar(9f)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* This is the API we're emulating */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/condvar.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/errno.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/debug.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/thread.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* avoiding synch.h */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _lwp_cond_signal(lwp_cond_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _lwp_cond_broadcast(lwp_cond_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossextern clock_t ddi_get_lbolt(void);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossextern void clock2ts(clock_t, timespec_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic int cv__wait(kcondvar_t *, kmutex_t *, int);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic clock_t cv__twait(kcondvar_t *, kmutex_t *, clock_t, int);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic const lwp_cond_t default_cv =
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross {{{0, 0, 0, 0}, USYNC_THREAD, _COND_MAGIC}, 0};
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* ARGSUSED */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_init(kcondvar_t *cv, char *name, kcv_type_t typ, void *arg)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *cv = default_cv;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* ARGSUSED */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_destroy(kcondvar_t *cv)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_signal(kcondvar_t *cv)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) _lwp_cond_signal(cv);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_broadcast(kcondvar_t *cv)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) _lwp_cond_broadcast(cv);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_wait(kcondvar_t *cv, kmutex_t *mp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) cv__wait(cv, mp, 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (cv__wait(cv, mp, 1));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv__wait(kcondvar_t *cv, kmutex_t *mp, int sigok)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int err;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosstop:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(mp->m_owner == _curthread());
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mp->m_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross err = _lwp_cond_wait(cv, &mp->m_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mp->m_owner = _curthread();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (err == 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (err == EINTR) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (sigok)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross goto top;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossclock_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross clock_t delta;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross delta = abstime - ddi_get_lbolt();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (cv__twait(cv, mp, delta, 0));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossclock_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_timedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross clock_t delta;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross delta = abstime - ddi_get_lbolt();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (cv__twait(cv, mp, delta, 1));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossclock_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_reltimedwait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, time_res_t res)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross _NOTE(ARGUNUSED(res))
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (cv__twait(cv, mp, delta, 0));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossclock_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv_reltimedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t delta,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross time_res_t res)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross _NOTE(ARGUNUSED(res))
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (cv__twait(cv, mp, delta, 1));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Factored out implementation of all the cv_*timedwait* functions.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Note that the delta passed in is relative to the (simulated)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * current time reported by ddi_get_lbolt(). Convert that to
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * timespec format and keep calling _lwp_cond_reltimedwait,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * which (NB!) decrements that delta in-place!
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic clock_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosscv__twait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, int sigok)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross timestruc_t ts;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int err;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (delta <= 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross clock2ts(delta, &ts);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosstop:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (ts.tv_sec == 0 && ts.tv_nsec == 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(mp->m_owner == _curthread());
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mp->m_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross err = _lwp_cond_reltimedwait(cv, &mp->m_lock, &ts);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mp->m_owner = _curthread();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross switch (err) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross case 0:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross case EINTR:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (sigok)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross goto top;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross default:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* FALLTHROUGH */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross case ETIME:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross break;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}