summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_clock.c52
-rw-r--r--sys/sys/systm.h3
2 files changed, 53 insertions, 2 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 0b7dfd3fe9e..6e6f0e3cca5 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_clock.c,v 1.31 2002/01/02 06:07:41 nordin Exp $ */
+/* $OpenBSD: kern_clock.c,v 1.32 2002/02/15 01:59:26 art Exp $ */
/* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */
/*-
@@ -764,6 +764,56 @@ hzto(tv)
}
/*
+ * Compute number of hz in the specified amount of time.
+ */
+int
+tvtohz(struct timeval *tv)
+{
+ unsigned long ticks;
+ long sec, usec;
+
+ /*
+ * If the number of usecs in the whole seconds part of the time
+ * difference fits in a long, then the total number of usecs will
+ * fit in an unsigned long. Compute the total and convert it to
+ * ticks, rounding up and adding 1 to allow for the current tick
+ * to expire. Rounding also depends on unsigned long arithmetic
+ * to avoid overflow.
+ *
+ * Otherwise, if the number of ticks in the whole seconds part of
+ * the time difference fits in a long, then convert the parts to
+ * ticks separately and add, using similar rounding methods and
+ * overflow avoidance. This method would work in the previous
+ * case but it is slightly slower and assumes that hz is integral.
+ *
+ * Otherwise, round the time difference down to the maximum
+ * representable value.
+ *
+ * If ints have 32 bits, then the maximum value for any timeout in
+ * 10ms ticks is 248 days.
+ */
+ sec = tv->tv_sec;
+ usec = tv->tv_usec;
+ if (usec < 0) {
+ sec--;
+ usec += 1000000;
+ }
+ if (sec < 0 || (sec == 0 && usec <= 0)) {
+ ticks = 0;
+ } else if (sec <= LONG_MAX / 1000000)
+ ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
+ / tick + 1;
+ else if (sec <= LONG_MAX / hz)
+ ticks = sec * hz
+ + ((unsigned long)usec + (tick - 1)) / tick + 1;
+ else
+ ticks = LONG_MAX;
+ if (ticks > INT_MAX)
+ ticks = INT_MAX;
+ return ((int)ticks);
+}
+
+/*
* Start profiling on a process.
*
* Kernel profiling passes proc0 which never exits and hence
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 62c097f3533..fe5ec2bf609 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systm.h,v 1.45 2002/02/04 19:38:20 miod Exp $ */
+/* $OpenBSD: systm.h,v 1.46 2002/02/15 01:59:26 art Exp $ */
/* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */
/*-
@@ -212,6 +212,7 @@ int suswintr __P((caddr_t, u_int));
struct timeval;
int hzto __P((struct timeval *));
+int tvtohz __P((struct timeval *));
void realitexpire __P((void *));
struct clockframe;