Subject: hzto [was Re: CVS commit: syssrc]
To: Jason R Thorpe <thorpej@zembu.com>
From: Konrad Schroder <perseant@hhhh.org>
List: tech-kern
Date: 07/14/2000 17:09:18
Okay.  After looking at the other places where timeradd/hzto is used, I
understand why it would be desirable to have a timeout of {0,0} be
distinct from a timeout of NULL (infinity).  I have two comments though:

1) By having a relative hzto_rel, doing the same thing as hzto but with a
relative offset instead of an abslute time, we could save a few cycles and
some time spent in splclock.  This would also never return zero unless it
was passed zero.  (Patch follows, comments welcome as always.)

2) "Avoid inadvertently sleeping forever"...On the one hand it is kind of
counter-intuitive that zero should mean forever; on the other hand that is
exactly what tsleep does, so it makes sense (from the backwards point of
view of a kernel programmer looking up at the applications) that
nanosleep, lfs_segwait, etc., should wait forever if passed zero as their
timeout.  Unfortunately application programmers (and standards
committees?) don't care about tsleep's calling conventions...they win.

						Konrad Schroder
						perseant@hhhh.org

Index: kern/kern_clock.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_clock.c,v
retrieving revision 1.60
diff -u -r1.60 kern_clock.c
--- kern_clock.c	2000/06/03 20:42:42	1.60
+++ kern_clock.c	2000/07/14 23:31:07
@@ -1141,6 +1141,26 @@
 }
 
 /*
+ * Compute number of hz until specified time has elapsed.
+ */
+int
+hzto_rel(tv)
+	struct timeval *tv;
+{
+	long ticks, sec;
+	int s;
+
+	sec = tv->tv_sec;
+	if (sec <= 0x7fffffff / 1000000 - 1)
+		ticks = (tv->tv_sec * 1000000 + tv->tv_usec) / tick;
+	else if (sec <= 0x7fffffff / hz)
+		ticks = sec * hz;
+	else
+		ticks = 0x7fffffff;
+	return (ticks);
+}
+
+/*
  * Start profiling on a process.
  *
  * Kernel profiling passes proc0 which never exits and hence
Index: kern/kern_time.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_time.c,v
retrieving revision 1.47
diff -u -r1.47 kern_time.c
--- kern_time.c	2000/05/31 05:02:34	1.47
+++ kern_time.c	2000/07/14 23:31:07
@@ -257,15 +257,12 @@
 	if (itimerfix(&atv))
 		return (EINVAL);
 
-	s = splclock();
-	timeradd(&atv,&time,&atv);
-	timo = hzto(&atv);
+	timo = hzto_rel(&atv);
 	/* 
 	 * Avoid inadvertantly sleeping forever
 	 */
 	if (timo == 0)
 		timo = 1;
-	splx(s);
 
 	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
 	if (error == ERESTART)
Index: kern/sys_generic.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/sys_generic.c,v
retrieving revision 1.48
diff -u -r1.48 sys_generic.c
--- sys_generic.c	2000/05/27 00:40:47	1.48
+++ sys_generic.c	2000/07/14 23:31:07
@@ -705,15 +705,12 @@
 			error = EINVAL;
 			goto done;
 		}
-		s = splclock();
-		timeradd(&atv, &time, &atv);
-		timo = hzto(&atv);
+		timo = hzto_rel(&atv);
 		/*
 		 * Avoid inadvertently sleeping forever.
 		 */
 		if (timo == 0)
 			timo = 1;
-		splx(s);
 	} else
 		timo = 0;
 retry:
@@ -843,15 +840,12 @@
 			error = EINVAL;
 			goto done;
 		}
-		s = splclock();
-		timeradd(&atv, &time, &atv);
-		timo = hzto(&atv);
+		timo = hzto_rel(&atv);
 		/*
 		 * Avoid inadvertently sleeping forever.
 		 */
 		if (timo == 0)
 			timo = 1;
-		splx(s);
 	} else
 		timo = 0;
 retry:
Index: sys/systm.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/systm.h,v
retrieving revision 1.111.2.1
diff -u -r1.111.2.1 systm.h
--- systm.h	2000/07/04 16:05:32	1.111.2.1
+++ systm.h	2000/07/14 23:31:18
@@ -230,6 +230,7 @@
 long	fuiword __P((const void *));
 
 int	hzto __P((struct timeval *tv));
+int	hzto_rel __P((struct timeval *tv));
 void	realitexpire __P((void *));
 
 void	hardclock __P((struct clockframe *frame));
Index: ufs/lfs/lfs_syscalls.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/lfs/lfs_syscalls.c,v
retrieving revision 1.41.4.2
diff -u -r1.41.4.2 lfs_syscalls.c
--- lfs_syscalls.c	2000/07/03 18:33:56	1.41.4.2
+++ lfs_syscalls.c	2000/07/15 00:03:40
@@ -819,12 +819,13 @@
  * sys_lfs_segwait:
  *
  * This will block until a segment in file system fsid is written.  A timeout
- * in milliseconds may be specified which will awake the cleaner automatically.
- * An fsid of -1 means any file system, and a timeout of 0 means forever.
+ * in seconds and microseconds may be specified which will awake the cleaner
+ * automatically.  An fsid of -1 means any file system, and a timeout of NULL
+ * means forever.
  *
  *  0 on success
  *  1 on timeout
- * -1/errno is return on error.
+ * -1/errno is returned on error.
  */
 int
 sys_lfs_segwait(p, v, retval)
@@ -860,10 +861,10 @@
 			return (error);
 		if (itimerfix(&atv))
 			return (EINVAL);
-		s = splclock();
-		timeradd(&atv, &time, &atv);
-		timeout = hzto(&atv);
-		splx(s);
+		timeout = hzto_rel(&atv);
+		/* Avoid inadvertently sleeping forever. */
+		if (timeout == 0)
+			timeout = 1;
 	} else
 		timeout = 0;