diff options
author | dm120769 <none@none> | 2007-04-27 07:12:39 -0700 |
---|---|---|
committer | dm120769 <none@none> | 2007-04-27 07:12:39 -0700 |
commit | 3348528f7ec68bf2f11d0cbd5c3b9932ea7f0d5c (patch) | |
tree | 855ea6b5ae3786966e656876cd1ac3992e072d51 /usr/src | |
parent | 85b65b39e9a6fea849facdcfc7d06f5ece340e36 (diff) | |
download | illumos-gate-3348528f7ec68bf2f11d0cbd5c3b9932ea7f0d5c.tar.gz |
backout 6265036/6531693: causes 6544953
Diffstat (limited to 'usr/src')
22 files changed, 174 insertions, 243 deletions
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_futex.c b/usr/src/uts/common/brand/lx/syscall/lx_futex.c index dd514c95f4..ceb6f330aa 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_futex.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_futex.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -212,7 +212,7 @@ futex_wait(memid_t *memid, caddr_t addr, int val, timespec_t *timeout) err = 0; while ((fw.fw_woken == 0) && (err == 0)) { ret = cv_waituntil_sig(&fw.fw_cv, &futex_hash_lock[index], - timeout); + timeout, timechanged); if (ret < 0) err = set_errno(ETIMEDOUT); else if (ret == 0) diff --git a/usr/src/uts/common/fs/portfs/port.c b/usr/src/uts/common/fs/portfs/port.c index a331eaea5b..a2d6b95170 100644 --- a/usr/src/uts/common/fs/portfs/port.c +++ b/usr/src/uts/common/fs/portfs/port.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1141,6 +1141,7 @@ port_getn(port_t *pp, port_event_t *uevp, uint_t max, uint_t *nget, uint_t tnent; int rval; int blocking = -1; + int timecheck; int flag; timespec_t rqtime; timespec_t *rqtp = NULL; @@ -1227,6 +1228,7 @@ port_getn(port_t *pp, port_event_t *uevp, uint_t max, uint_t *nget, goto portnowait; } rqtp = pgt->pgt_rqtp; + timecheck = pgt->pgt_timecheck; pgt->pgt_flags |= PORTGET_WAIT_EVENTS; } else { /* check if enough events are available ... */ @@ -1250,6 +1252,7 @@ port_getn(port_t *pp, port_event_t *uevp, uint_t max, uint_t *nget, if (rqtp != NULL) { timespec_t now; + timecheck = timechanged; gethrestime(&now); timespecadd(rqtp, &now); } @@ -1291,7 +1294,7 @@ port_getn(port_t *pp, port_event_t *uevp, uint_t max, uint_t *nget, } rval = cv_waituntil_sig(&pgetp->portget_cv, &portq->portq_mutex, - rqtp); + rqtp, timecheck); if (rval <= 0) { error = (rval == 0) ? EINTR : ETIME; @@ -1506,6 +1509,7 @@ portnowait: } if (rqtp != NULL) { timespec_t now; + pgt->pgt_timecheck = timechanged; gethrestime(&now); timespecadd(&pgt->pgt_rqtime, &now); } @@ -1514,6 +1518,7 @@ portnowait: /* timeout already checked -> remember values */ pgt->pgt_rqtp = rqtp; if (rqtp != NULL) { + pgt->pgt_timecheck = timecheck; pgt->pgt_rqtime = *rqtp; } } diff --git a/usr/src/uts/common/fs/proc/prcontrol.c b/usr/src/uts/common/fs/proc/prcontrol.c index 97ba369083..19e5f4b604 100644 --- a/usr/src/uts/common/fs/proc/prcontrol.c +++ b/usr/src/uts/common/fs/proc/prcontrol.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1084,6 +1084,7 @@ pr_wait_stop(prnode_t *pnp, time_t timeo) proc_t *p = pcp->prc_proc; timestruc_t rqtime; timestruc_t *rqtp = NULL; + int timecheck = 0; kthread_t *t; int error; @@ -1093,6 +1094,7 @@ pr_wait_stop(prnode_t *pnp, time_t timeo) */ timestruc_t now; + timecheck = timechanged; gethrestime(&now); rqtp = &rqtime; rqtp->tv_sec = timeo / MILLISEC; @@ -1108,7 +1110,7 @@ pr_wait_stop(prnode_t *pnp, time_t timeo) thread_unlock(t); mutex_enter(&pcp->prc_mutex); prunlock(pnp); - error = pr_wait(pcp, rqtp); + error = pr_wait(pcp, rqtp, timecheck); if (error) /* -1 is timeout */ return (error); if ((error = prlock(pnp, ZNO)) != 0) @@ -1127,7 +1129,7 @@ pr_wait_stop(prnode_t *pnp, time_t timeo) thread_unlock(t); mutex_enter(&pcp->prc_mutex); prunlock(pnp); - error = pr_wait(pcp, rqtp); + error = pr_wait(pcp, rqtp, timecheck); if (error) /* -1 is timeout */ return (error); if ((error = prlock(pnp, ZNO)) != 0) @@ -1285,12 +1287,13 @@ pr_setrun(prnode_t *pnp, ulong_t flags) */ int pr_wait(prcommon_t *pcp, /* prcommon referring to process/lwp */ - timestruc_t *ts) /* absolute time of timeout, if any */ + timestruc_t *ts, /* absolute time of timeout, if any */ + int timecheck) { int rval; ASSERT(MUTEX_HELD(&pcp->prc_mutex)); - rval = cv_waituntil_sig(&pcp->prc_wait, &pcp->prc_mutex, ts); + rval = cv_waituntil_sig(&pcp->prc_wait, &pcp->prc_mutex, ts, timecheck); mutex_exit(&pcp->prc_mutex); switch (rval) { case 0: @@ -2043,7 +2046,7 @@ retry: * Wait for the agent to stop and notify us. * If we've been interrupted, return that information. */ - error = pr_wait(pcp, NULL); + error = pr_wait(pcp, NULL, 0); if (error == EINTR) { error = 0; break; diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h index 0c3ee857cb..1294421f9f 100644 --- a/usr/src/uts/common/fs/proc/prdata.h +++ b/usr/src/uts/common/fs/proc/prdata.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -332,7 +332,7 @@ extern kthread_t *pr_thread(prnode_t *); extern void pr_stop(prnode_t *); extern int pr_wait_stop(prnode_t *, time_t); extern int pr_setrun(prnode_t *, ulong_t); -extern int pr_wait(prcommon_t *, timestruc_t *); +extern int pr_wait(prcommon_t *, timestruc_t *, int); extern void pr_wait_die(prnode_t *); extern int pr_setsig(prnode_t *, siginfo_t *); extern int pr_kill(prnode_t *, int, cred_t *); diff --git a/usr/src/uts/common/io/devpoll.c b/usr/src/uts/common/io/devpoll.c index 274737a147..965df2a9a1 100644 --- a/usr/src/uts/common/io/devpoll.c +++ b/usr/src/uts/common/io/devpoll.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -688,6 +688,7 @@ dpioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) timestruc_t now; timestruc_t rqtime; timestruc_t *rqtp = NULL; + int timecheck = 0; minor_t minor; dp_entry_t *dpep; pollcache_t *pcp; @@ -696,6 +697,7 @@ dpioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) if (cmd == DP_POLL) { /* do this now, before we sleep on DP_WRITER_PRESENT below */ + timecheck = timechanged; gethrestime(&now); } minor = getminor(dev); @@ -758,7 +760,7 @@ dpioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) return (0); mutex_enter(&curthread->t_delay_lock); while ((rval = cv_waituntil_sig(&curthread->t_delay_cv, - &curthread->t_delay_lock, rqtp)) > 0) + &curthread->t_delay_lock, rqtp, timecheck)) > 0) continue; mutex_exit(&curthread->t_delay_lock); return ((rval == 0)? EINTR : 0); @@ -813,7 +815,7 @@ dpioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) if (time_out == 0) /* immediate timeout */ break; rval = cv_waituntil_sig(&pcp->pc_cv, &pcp->pc_lock, - rqtp); + rqtp, timecheck); /* * If we were awakened by a signal or timeout * then break the loop, else poll again. diff --git a/usr/src/uts/common/os/aio.c b/usr/src/uts/common/os/aio.c index 631fb7b0e5..7dc72c0d2a 100644 --- a/usr/src/uts/common/os/aio.c +++ b/usr/src/uts/common/os/aio.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -529,6 +529,7 @@ aiowait( aio_req_t *reqp; clock_t status; int blocking; + int timecheck; timestruc_t rqtime; timestruc_t *rqtp; @@ -544,6 +545,7 @@ aiowait( return (error); if (rqtp) { timestruc_t now; + timecheck = timechanged; gethrestime(&now); timespecadd(rqtp, &now); } @@ -573,7 +575,7 @@ aiowait( } if (blocking) { status = cv_waituntil_sig(&aiop->aio_waitcv, - &aiop->aio_mutex, rqtp); + &aiop->aio_mutex, rqtp, timecheck); if (status > 0) /* check done queue again */ continue; @@ -617,6 +619,7 @@ aiowaitn(void *uiocb, uint_t nent, uint_t *nwait, timespec_t *timout) int iocb_index = 0; model_t model = get_udatamodel(); int blocking = 1; + int timecheck; timestruc_t rqtime; timestruc_t *rqtp; @@ -687,6 +690,7 @@ aiowaitn(void *uiocb, uint_t nent, uint_t *nwait, timespec_t *timout) */ if (rqtp) { timestruc_t now; + timecheck = timechanged; gethrestime(&now); timespecadd(rqtp, &now); } @@ -748,7 +752,7 @@ aiowaitn(void *uiocb, uint_t nent, uint_t *nwait, timespec_t *timout) if ((cnt < waitcnt) && blocking) { int rval = cv_waituntil_sig(&aiop->aio_waitcv, - &aiop->aio_mutex, rqtp); + &aiop->aio_mutex, rqtp, timecheck); if (rval > 0) continue; if (rval < 0) { @@ -916,6 +920,7 @@ aiosuspend( size_t ssize; model_t model = get_udatamodel(); int blocking; + int timecheck; timestruc_t rqtime; timestruc_t *rqtp; @@ -931,6 +936,7 @@ aiosuspend( return (error); if (rqtp) { timestruc_t now; + timecheck = timechanged; gethrestime(&now); timespecadd(rqtp, &now); } @@ -1050,7 +1056,7 @@ aiosuspend( */ mutex_exit(&aiop->aio_cleanupq_mutex); rv = cv_waituntil_sig(&aiop->aio_waitcv, - &aiop->aio_mutex, rqtp); + &aiop->aio_mutex, rqtp, timecheck); /* * we have to drop aio_mutex and * grab it in the right order. diff --git a/usr/src/uts/common/os/callout.c b/usr/src/uts/common/os/callout.c index e477155b76..1d13f7d179 100644 --- a/usr/src/uts/common/os/callout.c +++ b/usr/src/uts/common/os/callout.c @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -78,49 +79,6 @@ static callout_table_t *callout_table[CALLOUT_TABLES]; CALLOUT_HASH_##INSDEL(ct->ct_lbhash[CALLOUT_LBHASH(runtime)], \ cp, c_lbnext, c_lbprev) -#define CALLOUT_HRES_INSERT(ct, cp, cnext, cprev, hresms) \ -{ \ - callout_t *nextp = ct->ct_hresq; \ - callout_t *prevp; \ - \ - if (nextp == NULL || hresms <= nextp->c_hresms) { \ - cp->cnext = ct->ct_hresq; \ - ct->ct_hresq = cp; \ - cp->cprev = NULL; \ - if (cp->cnext != NULL) \ - cp->cnext->cprev = cp; \ - } else { \ - do { \ - prevp = nextp; \ - nextp = nextp->cnext; \ - } while (nextp != NULL && hresms > nextp->c_hresms); \ - prevp->cnext = cp; \ - cp->cprev = prevp; \ - cp->cnext = nextp; \ - if (nextp != NULL) \ - nextp->cprev = cp; \ - } \ -} - -#define CALLOUT_HRES_DELETE(ct, cp, cnext, cprev, hresms) \ -{ \ - if (cp == ct->ct_hresq) { \ - ct->ct_hresq = cp->cnext; \ - if (cp->cnext != NULL) \ - cp->cnext->cprev = NULL; \ - } else { \ - cp->cprev->cnext = cp->cnext; \ - if (cp->cnext != NULL) \ - cp->cnext->cprev = cp->cprev; \ - } \ -} - -#define CALLOUT_HRES_UPDATE(INSDEL, ct, cp, id, hresms) \ - ASSERT(MUTEX_HELD(&ct->ct_lock)); \ - ASSERT(cp->c_xid == id); \ - CALLOUT_HRES_##INSDEL(ct, cp, c_hrnext, \ - c_hrprev, hresms) - /* * Allocate a callout structure. We try quite hard because we * can't sleep, and if we can't do the allocation, we're toast. @@ -148,13 +106,9 @@ static timeout_id_t timeout_common(void (*func)(void *), void *arg, clock_t delta, callout_table_t *ct) { - callout_t *cp; - callout_id_t id; - clock_t runtime; - timestruc_t now; - int64_t hresms; - - gethrestime(&now); + callout_t *cp; + callout_id_t id; + clock_t runtime; mutex_enter(&ct->ct_lock); @@ -174,16 +128,6 @@ timeout_common(void (*func)(void *), void *arg, clock_t delta, cp->c_runtime = runtime = lbolt + delta; /* - * Calculate the future time in millisecond. - * We must cast tv_sec and delta to 64-bit integers - * to avoid integer overflow on 32-platforms. - */ - hresms = (int64_t)now.tv_sec * MILLISEC + now.tv_nsec / MICROSEC + - TICK_TO_MSEC((int64_t)delta); - - cp->c_hresms = hresms; - - /* * Assign an ID to this callout */ if (delta > CALLOUT_LONGTERM_TICKS) @@ -196,7 +140,6 @@ timeout_common(void (*func)(void *), void *arg, clock_t delta, cp->c_xid = id; CALLOUT_HASH_UPDATE(INSERT, ct, cp, id, runtime); - CALLOUT_HRES_UPDATE(INSERT, ct, cp, id, hresms); mutex_exit(&ct->ct_lock); @@ -241,7 +184,6 @@ untimeout(timeout_id_t id_arg) clock_t time_left = runtime - lbolt; CALLOUT_HASH_UPDATE(DELETE, ct, cp, id, runtime); - CALLOUT_HRES_UPDATE(DELETE, ct, cp, id, 0); cp->c_idnext = ct->ct_freelist; ct->ct_freelist = cp; mutex_exit(&ct->ct_lock); @@ -303,11 +245,9 @@ untimeout(timeout_id_t id_arg) static void callout_execute(callout_table_t *ct) { - callout_t *cp; - callout_id_t xid; - clock_t runtime; - timestruc_t now; - int64_t hresms; + callout_t *cp; + callout_id_t xid; + clock_t runtime; mutex_enter(&ct->ct_lock); @@ -327,16 +267,14 @@ callout_execute(callout_table_t *ct) mutex_enter(&ct->ct_lock); /* - * Delete callout from both the hash tables and the - * hres queue, return it to freelist, and tell anyone - * who cares that we're done. + * Delete callout from hash tables, return to freelist, + * and tell anyone who cares that we're done. * Even though we dropped and reacquired ct->ct_lock, * it's OK to pick up where we left off because only * newly-created timeouts can precede cp on ct_lbhash, * and those timeouts cannot be due on this tick. */ CALLOUT_HASH_UPDATE(DELETE, ct, cp, xid, runtime); - CALLOUT_HRES_UPDATE(DELETE, ct, cp, xid, hresms); cp->c_idnext = ct->ct_freelist; ct->ct_freelist = cp; cp->c_xid = 0; /* Indicate completion for c_done */ @@ -351,48 +289,6 @@ callout_execute(callout_table_t *ct) if (ct->ct_runtime == runtime) ct->ct_runtime = runtime + 1; } - - gethrestime(&now); - - /* - * Calculate the future time in millisecond. - * We must cast tv_sec to 64-bit integer - * to avoid integer overflow on 32-platforms. - */ - hresms = (int64_t)now.tv_sec * MILLISEC + now.tv_nsec / MICROSEC; - - cp = ct->ct_hresq; - while (cp != NULL && hresms >= cp->c_hresms) { - xid = cp->c_xid; - if (xid & CALLOUT_EXECUTING) { - cp = cp->c_hrnext; - continue; - } - cp->c_executor = curthread; - cp->c_xid = xid |= CALLOUT_EXECUTING; - runtime = cp->c_runtime; - mutex_exit(&ct->ct_lock); - DTRACE_PROBE1(callout__start, callout_t *, cp); - (*cp->c_func)(cp->c_arg); - DTRACE_PROBE1(callout__end, callout_t *, cp); - mutex_enter(&ct->ct_lock); - - /* - * See comments above. - */ - CALLOUT_HASH_UPDATE(DELETE, ct, cp, xid, runtime); - CALLOUT_HRES_UPDATE(DELETE, ct, cp, xid, hresms); - cp->c_idnext = ct->ct_freelist; - ct->ct_freelist = cp; - cp->c_xid = 0; /* Indicate completion for c_done */ - cv_broadcast(&cp->c_done); - - /* - * Start over from the head of the list, see if - * any timeout bearing an earlier hres time. - */ - cp = ct->ct_hresq; - } mutex_exit(&ct->ct_lock); } @@ -402,10 +298,8 @@ callout_execute(callout_table_t *ct) static void callout_schedule_1(callout_table_t *ct) { - callout_t *cp; - clock_t curtime, runtime; - timestruc_t now; - int64_t hresms; + callout_t *cp; + clock_t curtime, runtime; mutex_enter(&ct->ct_lock); ct->ct_curtime = curtime = lbolt; @@ -426,30 +320,6 @@ callout_schedule_1(callout_table_t *ct) } ct->ct_runtime++; } - - gethrestime(&now); - - /* - * Calculate the future time in millisecond. - * We must cast tv_sec to 64-bit integer - * to avoid integer overflow on 32-platforms. - */ - hresms = (int64_t)now.tv_sec * MILLISEC + now.tv_nsec / MICROSEC; - - cp = ct->ct_hresq; - while (cp != NULL && hresms >= cp->c_hresms) { - if (cp->c_xid & CALLOUT_EXECUTING) { - cp = cp->c_hrnext; - continue; - } - mutex_exit(&ct->ct_lock); - if (ct->ct_taskq == NULL) - softcall((void (*)(void *))callout_execute, ct); - else - (void) taskq_dispatch(ct->ct_taskq, - (task_func_t *)callout_execute, ct, KM_NOSLEEP); - return; - } mutex_exit(&ct->ct_lock); } diff --git a/usr/src/uts/common/os/clock.c b/usr/src/uts/common/os/clock.c index e465c864ef..ec72927e87 100644 --- a/usr/src/uts/common/os/clock.c +++ b/usr/src/uts/common/os/clock.c @@ -842,7 +842,7 @@ clock(void) hrestime = tod; membar_enter(); /* hrestime visible */ timedelta = 0; - hrestime_isvalid = 1; + timechanged++; tod_needsync = 0; hr_clock_unlock(s); } @@ -1773,20 +1773,16 @@ clkset(time_t approx) mutex_exit(&tod_lock); } -int hrestime_isvalid = 0; +int timechanged; /* for testing if the system time has been reset */ void set_hrestime(timestruc_t *ts) { int spl = hr_clock_lock(); hrestime = *ts; - /* - * hrestime must be visible before hrestime_isvalid - * is set to 1 - */ - membar_enter(); + membar_enter(); /* hrestime must be visible before timechanged++ */ timedelta = 0; - hrestime_isvalid = 1; + timechanged++; hr_clock_unlock(spl); } diff --git a/usr/src/uts/common/os/condvar.c b/usr/src/uts/common/os/condvar.c index 4ac03cbddb..fcc9d8aee7 100644 --- a/usr/src/uts/common/os/condvar.c +++ b/usr/src/uts/common/os/condvar.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -615,13 +615,19 @@ cv_wait_stop(kcondvar_t *cvp, kmutex_t *mp, int wakeup_time) * >0 if awakened via cv_signal() or cv_broadcast() * or by a spurious wakeup. * (might return time remaining) + * As a special test, if someone abruptly resets the system time + * (but not through adjtime(2); drifting of the clock is allowed and + * expected [see timespectohz_adj()]), then we force a return of -1 + * so the caller can return a premature timeout to the calling process + * so it can reevaluate the situation in light of the new system time. + * (The system clock has been reset if timecheck != timechanged.) */ int -cv_waituntil_sig(kcondvar_t *cvp, kmutex_t *mp, timestruc_t *when) +cv_waituntil_sig(kcondvar_t *cvp, kmutex_t *mp, + timestruc_t *when, int timecheck) { timestruc_t now; timestruc_t delta; - clock_t ticks; int rval; if (when == NULL) @@ -638,20 +644,29 @@ cv_waituntil_sig(kcondvar_t *cvp, kmutex_t *mp, timestruc_t *when) */ rval = cv_timedwait_sig(cvp, mp, lbolt); } else { - ticks = lbolt + timespectohz(when, now); - rval = cv_timedwait_sig(cvp, mp, ticks); - - gethrestime(&now); - delta = *when; - timespecsub(&delta, &now); - - /* - * timeout is premature iff - * ticks >= lbolt and when > now - */ - if (rval == -1 && ticks >= lbolt && (delta.tv_sec > 0 || - (delta.tv_sec == 0 && delta.tv_nsec > 0))) + if (timecheck == timechanged) { + rval = cv_timedwait_sig(cvp, mp, + lbolt + timespectohz_adj(when, now)); + } else { + /* + * Someone reset the system time; + * just force an immediate timeout. + */ + rval = -1; + } + if (rval == -1 && timecheck == timechanged) { + /* + * Even though cv_timedwait_sig() returned showing a + * timeout, the future time may not have passed yet. + * If not, change rval to indicate a normal wakeup. + */ + gethrestime(&now); + delta = *when; + timespecsub(&delta, &now); + if (delta.tv_sec > 0 || (delta.tv_sec == 0 && + delta.tv_nsec > 0)) rval = 1; + } } return (rval); } diff --git a/usr/src/uts/common/os/logsubr.c b/usr/src/uts/common/os/logsubr.c index 465a019869..729db9a130 100644 --- a/usr/src/uts/common/os/logsubr.c +++ b/usr/src/uts/common/os/logsubr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -327,7 +327,7 @@ log_conswitch(log_t *src, log_t *dst) lc->flags |= SL_LOGONLY; /* - * The ttime is written with 0 in log_sendmsg() only when + * The ttime is written with 0 in log_sensmsg() only when * good gethrestime_sec() data is not available to store in * the log_ctl_t in the early boot phase. */ @@ -605,12 +605,16 @@ log_sendmsg(mblk_t *mp, zoneid_t zoneid) log_enter(); /* - * If we are still in the early boot phase and the hrestime is invalid, - * we set ttime to 0 so that log_conswitch() can determine the correct - * ttime with a log_ctl_t structure which contains a valid ttime stamp. + * In the early boot phase hrestime is invalid, then timechanged is 0. + * If hrestime is not valid, the ttime is set to 0 here and the correct + * ttime is calculated in log_conswitch() later. The log_conswitch() + * calculation to determine the correct ttime does not use ttime data + * from these log_ctl_t structures; it only uses ttime from log_ctl_t's + * that contain good data. + * */ lc->ltime = lbolt; - if (hrestime_isvalid) { + if (timechanged) { lc->ttime = gethrestime_sec(); } else { lc->ttime = 0; diff --git a/usr/src/uts/common/os/timers.c b/usr/src/uts/common/os/timers.c index e656a17088..38881be61e 100644 --- a/usr/src/uts/common/os/timers.c +++ b/usr/src/uts/common/os/timers.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -850,6 +850,28 @@ timespectohz(timespec_t *tv, timespec_t now) } /* + * Same as timespectohz() except that we adjust the clock ticks down a bit. + * If we will be waiting for a long time, we may encounter skewing problems + * due to adjtime() system calls. Since we can skew up to 1/16 lbolt rate + * if adjtime is going crazy, we reduce the time delta since timeout() takes + * clock ticks rather than wallclock elapsed time. This may cause the caller + * (who calls timeout()) to return with a timeout prematurely and callers + * must accommodate this. See lwp_timeout(), queue_lwptimer() and + * cv_waituntil_sig(), currently the only callers of this function. + */ +clock_t +timespectohz_adj(timespec_t *tv, timespec_t now) +{ + timespec_t wait_time = *tv; + + timespecsub(&wait_time, &now); + wait_time.tv_sec -= wait_time.tv_sec >> 4; + wait_time.tv_nsec -= wait_time.tv_nsec >> 4; + timespecadd(&wait_time, &now); + return (timespectohz(&wait_time, now)); +} + +/* * hrt2ts(): convert from hrtime_t to timestruc_t. * * All this routine really does is: @@ -1162,6 +1184,7 @@ nanosleep(timespec_t *rqtp, timespec_t *rmtp) timespec_t rqtime; timespec_t rmtime; timespec_t now; + int timecheck; int ret = 1; model_t datamodel = get_udatamodel(); @@ -1181,11 +1204,12 @@ nanosleep(timespec_t *rqtp, timespec_t *rmtp) return (set_errno(EINVAL)); if (timerspecisset(&rqtime)) { + timecheck = timechanged; gethrestime(&now); timespecadd(&rqtime, &now); mutex_enter(&curthread->t_delay_lock); while ((ret = cv_waituntil_sig(&curthread->t_delay_cv, - &curthread->t_delay_lock, &rqtime)) > 0) + &curthread->t_delay_lock, &rqtime, timecheck)) > 0) continue; mutex_exit(&curthread->t_delay_lock); } diff --git a/usr/src/uts/common/sys/callo.h b/usr/src/uts/common/sys/callo.h index d4328e3e02..b48d41e3b9 100644 --- a/usr/src/uts/common/sys/callo.h +++ b/usr/src/uts/common/sys/callo.h @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -23,8 +24,8 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1997-1998 by Sun Microsystems, Inc. + * All rights reserved. */ #ifndef _SYS_CALLO_H @@ -50,11 +51,8 @@ typedef struct callout { struct callout *c_idprev; /* prev in ID hash */ struct callout *c_lbnext; /* next in lbolt hash */ struct callout *c_lbprev; /* prev in lbolt hash */ - struct callout *c_hrnext; /* next in hres queue */ - struct callout *c_hrprev; /* prev in hres queue */ callout_id_t c_xid; /* extended callout ID; see below */ clock_t c_runtime; /* absolute run time */ - int64_t c_hresms; /* hres in milli-second */ void (*c_func)(void *); /* function to call */ void *c_arg; /* argument to function */ kthread_id_t c_executor; /* thread executing callout */ @@ -127,7 +125,6 @@ typedef struct callout_table { callout_id_t ct_long_id; /* most recently issued long-term ID */ callout_t *ct_idhash[CALLOUT_BUCKETS]; /* ID hash chains */ callout_t *ct_lbhash[CALLOUT_BUCKETS]; /* lbolt hash chains */ - callout_t *ct_hresq; /* hres sorted queue */ } callout_table_t; #ifdef _KERNEL diff --git a/usr/src/uts/common/sys/condvar.h b/usr/src/uts/common/sys/condvar.h index a07e35aba8..5d618e6284 100644 --- a/usr/src/uts/common/sys/condvar.h +++ b/usr/src/uts/common/sys/condvar.h @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -81,7 +82,7 @@ extern int cv_wait_sig_swap(kcondvar_t *, kmutex_t *); extern int cv_wait_sig_swap_core(kcondvar_t *, kmutex_t *, int *); extern void cv_signal(kcondvar_t *); extern void cv_broadcast(kcondvar_t *); -extern int cv_waituntil_sig(kcondvar_t *, kmutex_t *, timestruc_t *); +extern int cv_waituntil_sig(kcondvar_t *, kmutex_t *, timestruc_t *, int); #endif /* defined(_KERNEL) */ diff --git a/usr/src/uts/common/sys/lwp_timer_impl.h b/usr/src/uts/common/sys/lwp_timer_impl.h index 7c3cbc75e6..fbbafde863 100644 --- a/usr/src/uts/common/sys/lwp_timer_impl.h +++ b/usr/src/uts/common/sys/lwp_timer_impl.h @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +42,7 @@ typedef struct { kthread_t *lwpt_thread; timespec_t *lwpt_tsp; timespec_t lwpt_rqtime; - clock_t lwpt_lbolt; + int lwpt_timecheck; int lwpt_imm_timeout; int lwpt_time_error; timeout_id_t lwpt_id; diff --git a/usr/src/uts/common/sys/port_impl.h b/usr/src/uts/common/sys/port_impl.h index 3b12a20873..a80e7afc84 100644 --- a/usr/src/uts/common/sys/port_impl.h +++ b/usr/src/uts/common/sys/port_impl.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -182,6 +182,7 @@ extern uint_t port_max_list; typedef struct port_gettimer { ushort_t pgt_flags; ushort_t pgt_loop; + int pgt_timecheck; timespec_t pgt_rqtime; timespec_t *pgt_rqtp; struct timespec *pgt_timeout; diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h index 80a966fc5f..ffc2c7dcfb 100644 --- a/usr/src/uts/common/sys/time.h +++ b/usr/src/uts/common/sys/time.h @@ -272,7 +272,7 @@ typedef struct todinfo { } todinfo_t; extern int64_t timedelta; -extern int hrestime_isvalid; +extern int timechanged; extern int tod_needsync; extern kmutex_t tod_lock; extern timestruc_t hrestime; diff --git a/usr/src/uts/common/sys/timer.h b/usr/src/uts/common/sys/timer.h index 37614f5e96..dcf076ebcb 100644 --- a/usr/src/uts/common/sys/timer.h +++ b/usr/src/uts/common/sys/timer.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -99,6 +99,7 @@ extern void timer_exit(void); extern void timer_lwpexit(void); extern clock_t hzto(struct timeval *); extern clock_t timespectohz(timespec_t *, timespec_t); +extern clock_t timespectohz_adj(timespec_t *, timespec_t); extern int itimerspecfix(timespec_t *); extern void timespecadd(timespec_t *, timespec_t *); extern void timespecsub(timespec_t *, timespec_t *); diff --git a/usr/src/uts/common/syscall/lwp_timer.c b/usr/src/uts/common/syscall/lwp_timer.c index df5a3a6198..7c1d862bea 100644 --- a/usr/src/uts/common/syscall/lwp_timer.c +++ b/usr/src/uts/common/syscall/lwp_timer.c @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,17 +59,16 @@ lwp_timer_timeout(void *arg) mutex_enter(&t->t_delay_lock); gethrestime(&now); - /* - * timeout is premature iff - * lwpt_lbolt >= lbolt and when > now + * Requeue the timeout if no one has reset the system time + * and if the absolute future time has not been reached. */ - if (lwptp->lwpt_lbolt >= lbolt && + if (lwptp->lwpt_timecheck == timechanged && (lwptp->lwpt_rqtime.tv_sec > now.tv_sec || (lwptp->lwpt_rqtime.tv_sec == now.tv_sec && lwptp->lwpt_rqtime.tv_nsec > now.tv_nsec))) { lwptp->lwpt_id = realtime_timeout(lwp_timer_timeout, lwptp, - timespectohz(&lwptp->lwpt_rqtime, now)); + timespectohz_adj(&lwptp->lwpt_rqtime, now)); } else { /* * Set the thread running only if it is asleep on @@ -93,6 +93,7 @@ lwp_timer_copyin(lwp_timer_t *lwptp, timespec_t *tsp) if (tsp == NULL) /* not really an error, just need to bzero() */ goto err; + lwptp->lwpt_timecheck = timechanged; /* do this before gethrestime() */ gethrestime(&now); /* do this before copyin() */ if (curproc->p_model == DATAMODEL_NATIVE) { if (copyin(tsp, &lwptp->lwpt_rqtime, sizeof (timespec_t))) { @@ -127,8 +128,6 @@ lwp_timer_copyin(lwp_timer_t *lwptp, timespec_t *tsp) lwptp->lwpt_id = 0; lwptp->lwpt_imm_timeout = 0; timespecadd(&lwptp->lwpt_rqtime, &now); - lwptp->lwpt_lbolt = lbolt + - timespectohz(&lwptp->lwpt_rqtime, now); } return (0); err: @@ -145,12 +144,7 @@ lwp_timer_enqueue(lwp_timer_t *lwptp) ASSERT(lwptp->lwpt_thread == curthread); ASSERT(MUTEX_HELD(&curthread->t_delay_lock)); gethrestime(&now); - - /* - * timeout is premature iff - * lwpt_lbolt >= lbolt and when > now - */ - if (lwptp->lwpt_lbolt >= lbolt && + if (lwptp->lwpt_timecheck == timechanged && (lwptp->lwpt_rqtime.tv_sec > now.tv_sec || (lwptp->lwpt_rqtime.tv_sec == now.tv_sec && lwptp->lwpt_rqtime.tv_nsec > now.tv_nsec))) { @@ -158,7 +152,7 @@ lwp_timer_enqueue(lwp_timer_t *lwptp) * Queue the timeout. */ lwptp->lwpt_id = realtime_timeout(lwp_timer_timeout, lwptp, - timespectohz(&lwptp->lwpt_rqtime, now)); + timespectohz_adj(&lwptp->lwpt_rqtime, now)); return (0); } diff --git a/usr/src/uts/common/syscall/lwpsys.c b/usr/src/uts/common/syscall/lwpsys.c index cab8263d0d..8868468a44 100644 --- a/usr/src/uts/common/syscall/lwpsys.c +++ b/usr/src/uts/common/syscall/lwpsys.c @@ -2,8 +2,9 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -402,6 +403,7 @@ lwp_park(timespec_t *timeoutp, id_t lwpid) timespec_t now; timespec_t *rqtp = NULL; kthread_t *t = curthread; + int timecheck = 0; int error = 0; model_t datamodel = ttoproc(t)->p_model; @@ -409,6 +411,7 @@ lwp_park(timespec_t *timeoutp, id_t lwpid) (void) lwp_unpark(lwpid); if (timeoutp) { + timecheck = timechanged; gethrestime(&now); if (datamodel == DATAMODEL_NATIVE) { if (copyin(timeoutp, &rqtime, sizeof (timespec_t))) { @@ -443,7 +446,7 @@ lwp_park(timespec_t *timeoutp, id_t lwpid) error = EINTR; while (error == 0 && t->t_unpark == 0) { switch (cv_waituntil_sig(&t->t_delay_cv, - &t->t_delay_lock, rqtp)) { + &t->t_delay_lock, rqtp, timecheck)) { case 0: error = EINTR; break; diff --git a/usr/src/uts/common/syscall/poll.c b/usr/src/uts/common/syscall/poll.c index ab62954123..c5ab2b83e4 100644 --- a/usr/src/uts/common/syscall/poll.c +++ b/usr/src/uts/common/syscall/poll.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -290,6 +290,7 @@ poll_common(pollfd_t *fds, nfds_t nfds, timespec_t *tsp, k_sigset_t *ksetp) int rval; int i; timespec_t *rqtp = NULL; + int timecheck = 0; int imm_timeout = 0; pollfd_t *pollfdp; pollstate_t *ps; @@ -306,6 +307,7 @@ poll_common(pollfd_t *fds, nfds_t nfds, timespec_t *tsp, k_sigset_t *ksetp) imm_timeout = 1; else { timespec_t now; + timecheck = timechanged; gethrestime(&now); rqtp = tsp; timespecadd(rqtp, &now); @@ -346,7 +348,7 @@ poll_common(pollfd_t *fds, nfds_t nfds, timespec_t *tsp, k_sigset_t *ksetp) if (!imm_timeout) { mutex_enter(&t->t_delay_lock); while ((rval = cv_waituntil_sig(&t->t_delay_cv, - &t->t_delay_lock, rqtp)) > 0) + &t->t_delay_lock, rqtp, timecheck)) > 0) continue; mutex_exit(&t->t_delay_lock); if (rval == 0) @@ -544,7 +546,7 @@ poll_common(pollfd_t *fds, nfds_t nfds, timespec_t *tsp, k_sigset_t *ksetp) rval = -1; else rval = cv_waituntil_sig(&pcp->pc_cv, &pcp->pc_lock, - rqtp); + rqtp, timecheck); mutex_exit(&pcp->pc_lock); /* * If we have received a signal or timed out diff --git a/usr/src/uts/common/syscall/sem.c b/usr/src/uts/common/syscall/sem.c index 95d1825dc9..d1bde2ff2d 100644 --- a/usr/src/uts/common/syscall/sem.c +++ b/usr/src/uts/common/syscall/sem.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -874,6 +874,7 @@ semop(int semid, struct sembuf *sops, size_t nsops, timespec_t *timeout) struct sembuf *uops; /* ptr to copy of user ops */ struct sembuf x_sem; /* avoid kmem_alloc's */ timespec_t now, ts, *tsp = NULL; + int timecheck = 0; int cvres, needundo, mode; struct sem_undo *undo; proc_t *pp = curproc; @@ -897,6 +898,7 @@ semop(int semid, struct sembuf *sops, size_t nsops, timespec_t *timeout) * we can legally not validate 'timeout' if it is unused. */ if (timeout != NULL) { + timecheck = timechanged; gethrestime(&now); if (error = compute_timeout(&tsp, &ts, &now, timeout)) return (set_errno(error)); @@ -1087,7 +1089,8 @@ check: ipc_hold(sem_svc, (kipc_perm_t *)sp); } semp->semncnt++; - cvres = cv_waituntil_sig(&semp->semncnt_cv, lock, tsp); + cvres = cv_waituntil_sig(&semp->semncnt_cv, lock, + tsp, timecheck); lock = ipc_relock(sem_svc, sp->sem_perm.ipc_id, lock); if (!IPC_FREE(&sp->sem_perm)) { @@ -1123,7 +1126,8 @@ check: ipc_hold(sem_svc, (kipc_perm_t *)sp); } semp->semzcnt++; - cvres = cv_waituntil_sig(&semp->semzcnt_cv, lock, tsp); + cvres = cv_waituntil_sig(&semp->semzcnt_cv, lock, + tsp, timecheck); lock = ipc_relock(sem_svc, sp->sem_perm.ipc_id, lock); /* diff --git a/usr/src/uts/common/syscall/sigtimedwait.c b/usr/src/uts/common/syscall/sigtimedwait.c index 56ca042498..ad4d79b763 100644 --- a/usr/src/uts/common/syscall/sigtimedwait.c +++ b/usr/src/uts/common/syscall/sigtimedwait.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -102,6 +102,7 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp) proc_t *p = ttoproc(t); timespec_t sig_timeout; timespec_t *rqtp = NULL; + int timecheck = 0; int ret; int error = 0; k_siginfo_t info, *infop; @@ -110,6 +111,7 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp) if (timeoutp) { timespec_t now; + timecheck = timechanged; gethrestime(&now); if (datamodel == DATAMODEL_NATIVE) { if (copyin(timeoutp, &sig_timeout, @@ -151,7 +153,7 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp) * the absolute future time is passed. */ while ((ret = cv_waituntil_sig(&t->t_delay_cv, &p->p_lock, - rqtp)) > 0) + rqtp, timecheck)) > 0) continue; if (ret == -1) error = EAGAIN; |