summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-06-01 09:01:07 +0000
committerpeter <peter@FreeBSD.org>1997-06-01 09:01:07 +0000
commite6f08b56a875b76720193c23108c342ac28ac9d6 (patch)
treed5e70bdab3c0b744699c031b5c890023166e6f69 /sys/kern/kern_time.c
parent350e8e813e694df48b5b5fad6ae3fbc651d15a58 (diff)
downloadFreeBSD-src-e6f08b56a875b76720193c23108c342ac28ac9d6.zip
FreeBSD-src-e6f08b56a875b76720193c23108c342ac28ac9d6.tar.gz
- implement signanosleep(2) by moving common code from nanosleep() into a
shared function. - use p->p_sleepend to try and get more accurate "time remaining" results when the time has been adjusted. - verify writeability of return address so that we can fail before sleeping if the address for the result is bogus.
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r--sys/kern/kern_time.c130
1 files changed, 102 insertions, 28 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 19cf8ee..a77df03 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)kern_time.c 8.1 (Berkeley) 6/10/93
- * $Id: kern_time.c,v 1.25 1997/05/10 06:02:29 brian Exp $
+ * $Id: kern_time.c,v 1.26 1997/05/10 12:00:03 peter Exp $
*/
#include <sys/param.h>
@@ -42,8 +42,12 @@
#include <sys/systm.h>
#include <sys/sysent.h>
#include <sys/proc.h>
+#include <sys/signal.h>
#include <sys/time.h>
#include <sys/vnode.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_extern.h>
struct timezone tz;
@@ -59,6 +63,8 @@ struct timezone tz;
static int settime __P((struct timeval *));
static void timevalfix __P((struct timeval *));
+static int nanosleep1 __P((struct proc *p, struct timespec *rqt,
+ struct timespec *rmt));
static int
settime(tv)
@@ -100,9 +106,12 @@ settime(tv)
timevalfix(&delta);
timevaladd(&boottime, &delta);
timevaladd(&runtime, &delta);
- for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
+ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
if (timerisset(&p->p_realtimer.it_value))
timevaladd(&p->p_realtimer.it_value, &delta);
+ if (p->p_sleepend)
+ timevaladd(p->p_sleepend, &delta);
+ }
#ifdef NFS
lease_updatetime(delta.tv_sec);
#endif
@@ -194,31 +203,19 @@ clock_getres(p, uap, retval)
return (error);
}
-#ifndef _SYS_SYSPROTO_H_
-struct nanosleep_args {
- struct timespec *rqtp;
- struct timespec *rmtp;
-};
-#endif
+static int nanowait;
-/* ARGSUSED */
-int
-nanosleep(p, uap, retval)
+static int
+nanosleep1(p, rqt, rmt)
struct proc *p;
- struct nanosleep_args *uap;
- register_t *retval;
+ struct timespec *rqt, *rmt;
{
- static int nanowait;
- struct timespec rmt, rqt;
struct timeval atv, utv;
- int error, error2, s, timo;
+ int error, s, timo;
- error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
- if (error)
- return (error);
- if (rqt.tv_nsec < 0 || rqt.tv_nsec >= 1000000000)
+ if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
return (EINVAL);
- TIMESPEC_TO_TIMEVAL(&atv, &rqt)
+ TIMESPEC_TO_TIMEVAL(&atv, rqt)
if (itimerfix(&atv))
return (EINVAL);
@@ -231,12 +228,15 @@ nanosleep(p, uap, retval)
timo = hzto(&atv);
splx(s);
- error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
+ p->p_sleepend = &atv;
+ error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
+ p->p_sleepend = NULL;
+
if (error == ERESTART)
error = EINTR;
if (error == EWOULDBLOCK)
error = 0;
- if (SCARG(uap, rmtp)) {
+ if (rmt != NULL) {
/*-
* XXX this is unnecessary and possibly wrong if the timeout
* expired. Then the remaining time should be zero. If the
@@ -244,6 +244,7 @@ nanosleep(p, uap, retval)
* (1) if settimeofday() was called, then the calculation is
* probably wrong, since `time' has probably become
* inconsistent with the ending time `atv'.
+ * XXX (1) should be fixed now with p->p_sleepend;
* (2) otherwise, our calculation of `timo' was wrong, perhaps
* due to `tick' being wrong when hzto() was called or
* changing afterwards (it can be wrong or change due to
@@ -259,18 +260,91 @@ nanosleep(p, uap, retval)
timevalsub(&atv, &utv);
if (atv.tv_sec < 0)
timerclear(&atv);
- TIMEVAL_TO_TIMESPEC(&atv, &rmt);
+ TIMEVAL_TO_TIMESPEC(&atv, rmt);
+ }
+ return (error);
+}
- /*
- * XXX should we test for addressibility before sleeping?
- */
+#ifndef _SYS_SYSPROTO_H_
+struct nanosleep_args {
+ struct timespec *rqtp;
+ struct timespec *rmtp;
+};
+#endif
+
+/* ARGSUSED */
+int
+nanosleep(p, uap, retval)
+ struct proc *p;
+ struct nanosleep_args *uap;
+ register_t *retval;
+{
+ struct timespec rmt, rqt;
+ int error, error2;
+
+ error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
+ if (error)
+ return (error);
+ if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
+ return (EFAULT);
+
+ error = nanosleep1(p, &rqt, &rmt);
+
+ if (SCARG(uap, rmtp)) {
error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
- if (error2)
+ if (error2) /* XXX shouldn't happen, did useracc() above */
return (error2);
}
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct signanosleep_args {
+ struct timespec *rqtp;
+ struct timespec *rmtp;
+ sigset_t *mask;
+};
+#endif
+
+/* ARGSUSED */
+int
+signanosleep(p, uap, retval)
+ struct proc *p;
+ struct signanosleep_args *uap;
+ register_t *retval;
+{
+ struct timespec rmt, rqt;
+ int error, error2;
+ struct sigacts *ps = p->p_sigacts;
+ sigset_t mask;
+
+ error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
+ if (error)
+ return (error);
+ if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
+ return (EFAULT);
+ error = copyin(SCARG(uap, mask), &mask, sizeof(mask));
+ if (error)
+ return (error);
+
+ /* See kern_sig.c:sigsuspend() for explanation */
+ ps->ps_oldmask = p->p_sigmask;
+ ps->ps_flags |= SAS_OLDMASK;
+ p->p_sigmask = mask &~ sigcantmask;
+
+ error = nanosleep1(p, &rqt, &rmt);
+
+ p->p_sigmask = ps->ps_oldmask; /* in case timeout rather than sig */
+ ps->ps_flags &= ~SAS_OLDMASK;
+
+ if (SCARG(uap, rmtp)) {
+ error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
+ if (error2) /* XXX shouldn't happen, did useracc() above */
+ return (error2);
+ }
+ return (error);
+
+}
#ifndef _SYS_SYSPROTO_H_
struct gettimeofday_args {
OpenPOWER on IntegriCloud