summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/timers.c')
-rw-r--r--usr/src/uts/common/os/timers.c28
1 files changed, 26 insertions, 2 deletions
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);
}