Add clock_nanosleep()

Add a clock_nanosleep() syscall, as specified by POSIX.
Make nanosleep() a wrapper around it.

Attach the clock_nanosleep test from NetBSD. Adjust it for the
FreeBSD behavior of updating rmtp only when interrupted by a signal.
I believe this to be POSIX-compliant, since POSIX mentions the rmtp
parameter only in the paragraph about EINTR. This is also what
Linux does. (NetBSD updates rmtp unconditionally.)

Copy the whole nanosleep.2 man page from NetBSD because it is complete
and closely resembles the POSIX description. Edit, polish, and reword it
a bit, being sure to keep any relevant text from the FreeBSD page.

Reviewed by:	kib, ngie, jilles
MFC after:	3 weeks
Relnotes:	yes
Sponsored by:	Dell EMC
Differential Revision:	https://reviews.freebsd.org/D10020
This commit is contained in:
Eric van Gyzen 2017-03-19 00:51:12 +00:00
parent a776eeafdc
commit 3f8455b090
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315526
19 changed files with 367 additions and 83 deletions

View file

@ -46,7 +46,11 @@ ATF_TC_BODY(clock_nanosleep_remain, tc)
rqtp.tv_sec = 0; rqtp.tv_nsec = 0;
rmtp.tv_sec = -1; rmtp.tv_nsec = -1;
ATF_REQUIRE(clock_nanosleep(CLOCK_REALTIME, 0, &rqtp, &rmtp) == 0);
#ifdef __FreeBSD__
ATF_CHECK(rmtp.tv_sec == -1 && rmtp.tv_nsec == -1);
#else
ATF_CHECK(rmtp.tv_sec == 0 && rmtp.tv_nsec == 0);
#endif
ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &rqtp) == 0);
rmtp.tv_sec = -1; rmtp.tv_nsec = -1;

View file

@ -169,12 +169,12 @@ void tzset(void);
int clock_getres(clockid_t, struct timespec *);
int clock_gettime(clockid_t, struct timespec *);
int clock_settime(clockid_t, const struct timespec *);
/* XXX missing: clock_nanosleep() */
int nanosleep(const struct timespec *, struct timespec *);
#endif /* __POSIX_VISIBLE >= 199309 */
#if __POSIX_VISIBLE >= 200112
int clock_getcpuclockid(pid_t, clockid_t *);
int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
#endif
#if __POSIX_VISIBLE >= 199506

View file

@ -229,6 +229,7 @@ enum {
INTERPOS_ppoll,
INTERPOS_map_stacks_exec,
INTERPOS_fdatasync,
INTERPOS_clock_nanosleep,
INTERPOS_MAX
};
@ -318,6 +319,8 @@ int __sys_aio_suspend(const struct aiocb * const[], int,
int __sys_accept(int, struct sockaddr *, __socklen_t *);
int __sys_accept4(int, struct sockaddr *, __socklen_t *, int);
int __sys_clock_gettime(__clockid_t, struct timespec *ts);
int __sys_clock_nanosleep(__clockid_t, int,
const struct timespec *, struct timespec *);
int __sys_close(int);
int __sys_connect(int, const struct sockaddr *, __socklen_t);
int __sys_fcntl(int, int, ...);

View file

@ -56,6 +56,7 @@
#define bind _bind
#define __cap_get_fd ___cap_get_fd
#define __cap_set_fd ___cap_set_fd
#define clock_nanosleep _clock_nanosleep
#define close _close
#define connect _connect
#define dup _dup

View file

@ -37,6 +37,7 @@
#undef bind
#undef __cap_get_fd
#undef __cap_set_fd
#undef clock_nanosleep
#undef close
#undef connect
#undef dup

View file

@ -45,6 +45,7 @@ INTERPOSED = \
accept \
accept4 \
aio_suspend \
clock_nanosleep \
close \
connect \
fcntl \
@ -360,6 +361,7 @@ MLINKS+=chown.2 fchown.2 \
chown.2 lchown.2
MLINKS+=clock_gettime.2 clock_getres.2 \
clock_gettime.2 clock_settime.2
MLINKS+=nanosleep.2 clock_nanosleep.2
MLINKS+=cpuset.2 cpuset_getid.2 \
cpuset.2 cpuset_setid.2
MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2

View file

@ -399,6 +399,7 @@ FBSD_1.4 {
};
FBSD_1.5 {
clock_nanosleep;
fdatasync;
};
@ -511,6 +512,7 @@ FBSDprivate_1.0 {
__sys_clock_getres;
_clock_gettime;
__sys_clock_gettime;
__sys_clock_nanosleep;
_clock_settime;
__sys_clock_settime;
_close;

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2017 Eric van Gyzen
* Copyright (c) 2014 The FreeBSD Foundation.
* All rights reserved.
*
* Portions of this software were developed by Konstantin Belousov
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice(s), this list of conditions and the following disclaimer as
* the first lines of this file unmodified other than the possible
* addition of one or more copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
* notice(s), this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <time.h>
#include "libc_private.h"
__weak_reference(__sys_clock_nanosleep, __clock_nanosleep);
#pragma weak clock_nanosleep
int
clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
struct timespec *rmtp)
{
return (((int (*)(clockid_t, int, const struct timespec *,
struct timespec *))
__libc_interposing[INTERPOS_clock_nanosleep])(clock_id, flags,
rqtp, rmtp));
}

View file

@ -80,6 +80,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = {
SLOT(ppoll, __sys_ppoll),
SLOT(map_stacks_exec, __libc_map_stacks_exec),
SLOT(fdatasync, __sys_fdatasync),
SLOT(clock_nanosleep, __sys_clock_nanosleep),
};
#undef SLOT

View file

@ -1,5 +1,4 @@
.\" $OpenBSD: nanosleep.2,v 1.1 1997/04/20 20:56:20 tholo Exp $
.\" $NetBSD: nanosleep.2,v 1.1 1997/04/17 18:12:02 jtc Exp $
.\" $NetBSD: nanosleep.2,v 1.23 2016/11/14 10:40:59 wiz Exp $
.\"
.\" Copyright (c) 1986, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,51 +30,136 @@
.\" @(#)sleep.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd April 17, 1997
.Dd March 17, 2017
.Dt NANOSLEEP 2
.Os
.Sh NAME
.Nm nanosleep
.Nd suspend process execution for an interval measured in nanoseconds
.Nd high resolution sleep
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In time.h
.Ft int
.Fn nanosleep "const struct timespec *rqtp" "struct timespec *rmtp"
.Fo clock_nanosleep
.Fa "clockid_t clock_id"
.Fa "int flags"
.Fa "const struct timespec *rqtp"
.Fa "struct timespec *rmtp"
.Fc
.Ft int
.Fo nanosleep
.Fa "const struct timespec *rqtp"
.Fa "struct timespec *rmtp"
.Fc
.Sh DESCRIPTION
The
.Fn nanosleep
system call
causes the calling thread to sleep until the time interval specified by
.Fa rqtp
has elapsed.
An unmasked signal will
cause it to terminate the sleep early, regardless of the
.Dv SA_RESTART
value on the interrupting signal.
.Sh RETURN VALUES
If the
.Fn nanosleep
system call returns because the requested time has elapsed, the value
returned will be zero.
.Dv TIMER_ABSTIME
flag is not set in the
.Fa flags
argument, then
.Fn clock_nanosleep
suspends execution of the calling thread until either the
time interval specified by the
.Fa rqtp
argument has elapsed,
or a signal is delivered to the calling process and its
action is to invoke a signal-catching function or to terminate the
process.
The clock used to measure the time is specified by the
.Fa clock_id
argument.
.Pp
If the
.Dv TIMER_ABSTIME
flag is set in the
.Fa flags
argument, then
.Fn clock_nanosleep
suspends execution of the calling thread until either the value
of the clock specified by the
.Fa clock_id
argument reaches the absolute time specified by the
.Fa rqtp
argument,
or a signal is delivered to the calling process and its
action is to invoke a signal-catching function or to terminate the
process.
If, at the time of the call, the time value specified by
.Fa rqtp
is less than or equal to the time value of the specified clock, then
.Fn clock_nanosleep
returns immediately and the calling thread is not suspended.
.Pp
The suspension time may be longer than requested due to the
scheduling of other activity by the system.
An unmasked signal will terminate the sleep early, regardless of the
.Dv SA_RESTART
value on the interrupting signal.
The
.Fa rqtp
and
.Fa rmtp
arguments can point to the same object.
.Pp
The following
.Fa clock_id
values are supported:
.Pp
.Bl -item -compact -offset indent
.It
CLOCK_MONOTONIC
.It
CLOCK_MONOTONIC_FAST
.It
CLOCK_MONOTONIC_PRECISE
.It
CLOCK_REALTIME
.It
CLOCK_REALTIME_FAST
.It
CLOCK_REALTIME_PRECISE
.It
CLOCK_SECOND
.It
CLOCK_UPTIME
.It
CLOCK_UPTIME_FAST
.It
CLOCK_UPTIME_PRECISE
.El
.Pp
The
.Fn nanosleep
system call returns due to the delivery of a signal, the value returned
will be -1, and the global variable
function behaves like
.Fn clock_nanosleep
with a
.Fa clock_id
argument of
.Dv CLOCK_REALTIME
and without the
.Dv TIMER_ABSTIME
flag in the
.Fa flags
argument.
.Sh RETURN VALUES
These functions return zero when the requested time has elapsed.
.Pp
If these functions return for any other reason, then
.Fn clock_nanosleep
will directly return the error number, and
.Fn nanosleep
will return \-1 with the global variable
.Va errno
will be set to indicate the interruption.
If
set to indicate the error.
If a relative sleep is interrupted by a signal and
.Fa rmtp
is
.No non- Ns Dv NULL ,
.Pf non- Dv NULL ,
the timespec structure it references is updated to contain the
unslept amount (the request time minus the time actually slept).
.Sh ERRORS
The
.Fn nanosleep
system call fails if:
These functions can fail with the following errors.
.Bl -tag -width Er
.It Bq Er EFAULT
Either
@ -85,27 +169,32 @@ or
points to memory that is not a valid part of the process
address space.
.It Bq Er EINTR
The
.Fn nanosleep
system call
was interrupted by the delivery of a signal.
The function was interrupted by the delivery of a signal.
.It Bq Er EINVAL
The
.Fa rqtp
argument
specified a nanosecond value less than zero
argument specified a nanosecond value less than zero
or greater than or equal to 1000 million.
.It Bq Er ENOSYS
.It Bq Er EINVAL
The
.Fn nanosleep
system call
is not supported by this implementation.
.Fa flags
argument contained an invalid flag.
.It Bq Er EINVAL
The
.Fa clock_id
argument was
.Dv CLOCK_THREAD_CPUTIME_ID
or an unrecognized value.
.It Bq Er ENOTSUP
The
.Fa clock_id
argument was valid but not supported by this implementation of
.Fn clock_nanosleep .
.El
.Sh SEE ALSO
.Xr sigsuspend 2 ,
.Xr clock_gettime 2 ,
.Xr sigaction 2 ,
.Xr sleep 3
.Sh STANDARDS
The
.Fn nanosleep
system call conforms to
.St -p1003.1b-93 .
These functions conform to
.St -p1003.1-2008 .

View file

@ -12,6 +12,7 @@ NETBSD_ATF_TESTS_C+= access_test
NETBSD_ATF_TESTS_C+= bind_test
NETBSD_ATF_TESTS_C+= chroot_test
NETBSD_ATF_TESTS_C+= clock_gettime_test
NETBSD_ATF_TESTS_C+= clock_nanosleep_test
NETBSD_ATF_TESTS_C+= connect_test
NETBSD_ATF_TESTS_C+= dup_test
NETBSD_ATF_TESTS_C+= fsync_test

View file

@ -865,6 +865,8 @@ int __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info);
/* #include <time.h> */
#ifdef _TIME_H_
int __sys_clock_nanosleep(clockid_t, int, const struct timespec *,
struct timespec *);
int __sys_nanosleep(const struct timespec *, struct timespec *);
#endif

View file

@ -259,6 +259,22 @@ __thr_msync(void *addr, size_t len, int flags)
return (ret);
}
static int
__thr_clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *time_to_sleep, struct timespec *time_remaining)
{
struct pthread *curthread;
int ret;
curthread = _get_curthread();
_thr_cancel_enter(curthread);
ret = __sys_clock_nanosleep(clock_id, flags, time_to_sleep,
time_remaining);
_thr_cancel_leave(curthread, 1);
return (ret);
}
static int
__thr_nanosleep(const struct timespec *time_to_sleep,
struct timespec *time_remaining)
@ -668,6 +684,7 @@ __thr_interpose_libc(void)
SLOT(ppoll);
SLOT(map_stacks_exec);
SLOT(fdatasync);
SLOT(clock_nanosleep);
#undef SLOT
*(__libc_interposing_slot(
INTERPOS__pthread_mutex_init_calloc_cb)) =

View file

@ -1,5 +1,5 @@
.\" $FreeBSD$
.Dd February 17, 2017
.Dd March 18, 2017
.Dt PTHREAD_TESTCANCEL 3
.Os
.Sh NAME
@ -105,6 +105,7 @@ functions:
.It Fn accept4
.It Fn aio_suspend
.It Fn connect
.It Fn clock_nanosleep
.It Fn close
.It Fn creat
.It Fn fcntl

View file

@ -129,6 +129,8 @@ CTASSERT(sizeof(struct sigaction32) == 24);
static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
static int freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,
int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp);
void
freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)
@ -2225,29 +2227,49 @@ ofreebsd32_sigstack(struct thread *td,
int
freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
{
return (freebsd32_user_clock_nanosleep(td, CLOCK_REALTIME,
TIMER_RELTIME, uap->rqtp, uap->rmtp));
}
int
freebsd32_clock_nanosleep(struct thread *td,
struct freebsd32_clock_nanosleep_args *uap)
{
int error;
error = freebsd32_user_clock_nanosleep(td, uap->clock_id, uap->flags,
uap->rqtp, uap->rmtp);
return (kern_posix_error(td, error));
}
static int
freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,
int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp)
{
struct timespec32 rmt32, rqt32;
struct timespec rmt, rqt;
int error;
error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
error = copyin(ua_rqtp, &rqt32, sizeof(rqt32));
if (error)
return (error);
CP(rqt32, rqt, tv_sec);
CP(rqt32, rqt, tv_nsec);
if (uap->rmtp &&
!useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
if (ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0 &&
!useracc(ua_rmtp, sizeof(rmt32), VM_PROT_WRITE))
return (EFAULT);
error = kern_nanosleep(td, &rqt, &rmt);
if (error == EINTR && uap->rmtp) {
error = kern_clock_nanosleep(td, clock_id, flags, &rqt, &rmt);
if (error == EINTR && ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0) {
int error2;
CP(rmt, rmt32, tv_sec);
CP(rmt, rmt32, tv_nsec);
error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
error2 = copyout(&rmt32, ua_rmtp, sizeof(rmt32));
if (error2)
error = error2;
}

View file

@ -462,7 +462,10 @@
struct ffclock_estimate *cest); }
243 AUE_NULL NOPROTO { int ffclock_getestimate( \
struct ffclock_estimate *cest); }
244 AUE_NULL UNIMPL nosys
244 AUE_NULL STD { int freebsd32_clock_nanosleep( \
clockid_t clock_id, int flags, \
const struct timespec32 *rqtp, \
struct timespec32 *rmtp); }
245 AUE_NULL UNIMPL nosys
246 AUE_NULL UNIMPL nosys
247 AUE_NULL STD { int freebsd32_clock_getcpuclockid2(\

View file

@ -86,6 +86,9 @@ static uma_zone_t itimer_zone = NULL;
static int settime(struct thread *, struct timeval *);
static void timevalfix(struct timeval *);
static int user_clock_nanosleep(struct thread *td, clockid_t clock_id,
int flags, const struct timespec *ua_rqtp,
struct timespec *ua_rmtp);
static void itimer_start(void);
static int itimer_init(void *, int, int);
@ -481,47 +484,95 @@ kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts)
return (0);
}
static uint8_t nanowait[MAXCPU];
int
kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt)
{
struct timespec ts;
return (kern_clock_nanosleep(td, CLOCK_REALTIME, TIMER_RELTIME, rqt,
rmt));
}
static uint8_t nanowait[MAXCPU];
int
kern_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags,
const struct timespec *rqt, struct timespec *rmt)
{
struct timespec ts, now;
sbintime_t sbt, sbtt, prec, tmp;
time_t over;
int error;
bool is_abs_real;
if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
return (EINVAL);
if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
return (0);
ts = *rqt;
if (ts.tv_sec > INT32_MAX / 2) {
over = ts.tv_sec - INT32_MAX / 2;
ts.tv_sec -= over;
} else
over = 0;
tmp = tstosbt(ts);
prec = tmp;
prec >>= tc_precexp;
if (TIMESEL(&sbt, tmp))
sbt += tc_tick_sbt;
sbt += tmp;
error = tsleep_sbt(&nanowait[curcpu], PWAIT | PCATCH, "nanslp",
sbt, prec, C_ABSOLUTE);
if ((flags & ~TIMER_ABSTIME) != 0)
return (EINVAL);
switch (clock_id) {
case CLOCK_REALTIME:
case CLOCK_REALTIME_PRECISE:
case CLOCK_REALTIME_FAST:
case CLOCK_SECOND:
is_abs_real = (flags & TIMER_ABSTIME) != 0;
break;
case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_PRECISE:
case CLOCK_MONOTONIC_FAST:
case CLOCK_UPTIME:
case CLOCK_UPTIME_PRECISE:
case CLOCK_UPTIME_FAST:
is_abs_real = false;
break;
case CLOCK_VIRTUAL:
case CLOCK_PROF:
case CLOCK_PROCESS_CPUTIME_ID:
return (ENOTSUP);
case CLOCK_THREAD_CPUTIME_ID:
default:
return (EINVAL);
}
do {
ts = *rqt;
if ((flags & TIMER_ABSTIME) != 0) {
if (is_abs_real)
td->td_rtcgen =
atomic_load_acq_int(&rtc_generation);
error = kern_clock_gettime(td, clock_id, &now);
KASSERT(error == 0, ("kern_clock_gettime: %d", error));
timespecsub(&ts, &now);
}
if (ts.tv_sec < 0 || (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
error = EWOULDBLOCK;
break;
}
if (ts.tv_sec > INT32_MAX / 2) {
over = ts.tv_sec - INT32_MAX / 2;
ts.tv_sec -= over;
} else
over = 0;
tmp = tstosbt(ts);
prec = tmp;
prec >>= tc_precexp;
if (TIMESEL(&sbt, tmp))
sbt += tc_tick_sbt;
sbt += tmp;
error = tsleep_sbt(&nanowait[curcpu], PWAIT | PCATCH, "nanslp",
sbt, prec, C_ABSOLUTE);
} while (error == 0 && is_abs_real && td->td_rtcgen == 0);
td->td_rtcgen = 0;
if (error != EWOULDBLOCK) {
TIMESEL(&sbtt, tmp);
if (sbtt >= sbt)
return (0);
if (error == ERESTART)
error = EINTR;
TIMESEL(&sbtt, tmp);
if (rmt != NULL) {
if ((flags & TIMER_ABSTIME) == 0 && rmt != NULL) {
ts = sbttots(sbt - sbtt);
ts.tv_sec += over;
if (ts.tv_sec < 0)
timespecclear(&ts);
*rmt = ts;
}
if (sbtt >= sbt)
return (0);
return (error);
}
return (0);
@ -536,22 +587,49 @@ struct nanosleep_args {
/* ARGSUSED */
int
sys_nanosleep(struct thread *td, struct nanosleep_args *uap)
{
return (user_clock_nanosleep(td, CLOCK_REALTIME, TIMER_RELTIME,
uap->rqtp, uap->rmtp));
}
#ifndef _SYS_SYSPROTO_H_
struct clock_nanosleep_args {
clockid_t clock_id;
int flags;
struct timespec *rqtp;
struct timespec *rmtp;
};
#endif
/* ARGSUSED */
int
sys_clock_nanosleep(struct thread *td, struct clock_nanosleep_args *uap)
{
int error;
error = user_clock_nanosleep(td, uap->clock_id, uap->flags, uap->rqtp,
uap->rmtp);
return (kern_posix_error(td, error));
}
static int
user_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags,
const struct timespec *ua_rqtp, struct timespec *ua_rmtp)
{
struct timespec rmt, rqt;
int error;
error = copyin(uap->rqtp, &rqt, sizeof(rqt));
error = copyin(ua_rqtp, &rqt, sizeof(rqt));
if (error)
return (error);
if (uap->rmtp &&
!useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
return (EFAULT);
error = kern_nanosleep(td, &rqt, &rmt);
if (error == EINTR && uap->rmtp) {
if (ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0 &&
!useracc(ua_rmtp, sizeof(rmt), VM_PROT_WRITE))
return (EFAULT);
error = kern_clock_nanosleep(td, clock_id, flags, &rqt, &rmt);
if (error == EINTR && ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0) {
int error2;
error2 = copyout(&rmt, uap->rmtp, sizeof(rmt));
error2 = copyout(&rmt, ua_rmtp, sizeof(rmt));
if (error2)
error = error2;
}

View file

@ -461,7 +461,9 @@
struct ffclock_estimate *cest); }
243 AUE_NULL STD { int ffclock_getestimate( \
struct ffclock_estimate *cest); }
244 AUE_NULL UNIMPL nosys
244 AUE_NULL STD { int clock_nanosleep(clockid_t clock_id, \
int flags, const struct timespec *rqtp, \
struct timespec *rmtp); }
245 AUE_NULL UNIMPL nosys
246 AUE_NULL UNIMPL nosys
247 AUE_NULL STD { int clock_getcpuclockid2(id_t id,\

View file

@ -82,6 +82,8 @@ int kern_clock_getres(struct thread *td, clockid_t clock_id,
struct timespec *ts);
int kern_clock_gettime(struct thread *td, clockid_t clock_id,
struct timespec *ats);
int kern_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags,
const struct timespec *rqtp, struct timespec *rmtp);
int kern_clock_settime(struct thread *td, clockid_t clock_id,
struct timespec *ats);
int kern_close(struct thread *td, int fd);