diff options
30 files changed, 455 insertions, 84 deletions
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c b/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c index 8c1fd03..7437778 100644 --- a/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c +++ b/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c @@ -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; diff --git a/include/time.h b/include/time.h index c172538..54c7e49 100644 --- a/include/time.h +++ b/include/time.h @@ -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 diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index e484d20..384f61f 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -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, ...); diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 52e9b25..f15edee 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -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 diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index e40e6fd..7df4961 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -37,6 +37,7 @@ #undef bind #undef __cap_get_fd #undef __cap_set_fd +#undef clock_nanosleep #undef close #undef connect #undef dup diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index ac1bb11..8ecfbbc 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -34,6 +34,7 @@ INTERPOSED = \ accept \ accept4 \ aio_suspend \ + clock_nanosleep \ close \ connect \ fcntl \ @@ -349,6 +350,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 diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 489635e..83d1af9 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -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; diff --git a/lib/libc/sys/clock_nanosleep.c b/lib/libc/sys/clock_nanosleep.c new file mode 100644 index 0000000..65e1548 --- /dev/null +++ b/lib/libc/sys/clock_nanosleep.c @@ -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)); +} diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c index 1447e42..faf1e6c 100644 --- a/lib/libc/sys/interposing_table.c +++ b/lib/libc/sys/interposing_table.c @@ -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 diff --git a/lib/libc/sys/nanosleep.2 b/lib/libc/sys/nanosleep.2 index f50544b..29277f3 100644 --- a/lib/libc/sys/nanosleep.2 +++ b/lib/libc/sys/nanosleep.2 @@ -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 +If the +.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 -has elapsed. -An unmasked signal will -cause it to terminate the sleep early, regardless of the +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. -.Sh RETURN VALUES -If the +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 because the requested time has elapsed, the value -returned will be zero. +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 the +If these functions return for any other reason, then +.Fn clock_nanosleep +will directly return the error number, and .Fn nanosleep -system call returns due to the delivery of a signal, the value returned -will be -1, and the global variable +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 . diff --git a/lib/libc/tests/sys/Makefile b/lib/libc/tests/sys/Makefile index 64b20a8..10d2c2c 100644 --- a/lib/libc/tests/sys/Makefile +++ b/lib/libc/tests/sys/Makefile @@ -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 diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 9bea65f..56ecdb4 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -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 diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 362826c..92d0c99 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -260,6 +260,22 @@ __thr_msync(void *addr, size_t len, int flags) } 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)) = diff --git a/share/man/man3/pthread_testcancel.3 b/share/man/man3/pthread_testcancel.3 index 8d0204d..5d0efcb 100644 --- a/share/man/man3/pthread_testcancel.3 +++ b/share/man/man3/pthread_testcancel.3 @@ -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 diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 86b1399..08a072f 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -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) @@ -2226,28 +2228,48 @@ 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; } diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 2ef4bbe..1d341f6 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -236,6 +236,12 @@ struct freebsd32_nanosleep_args { char rqtp_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * rqtp; char rqtp_r_[PADR_(const struct timespec32 *)]; char rmtp_l_[PADL_(struct timespec32 *)]; struct timespec32 * rmtp; char rmtp_r_[PADR_(struct timespec32 *)]; }; +struct freebsd32_clock_nanosleep_args { + char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; + char rqtp_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * rqtp; char rqtp_r_[PADR_(const struct timespec32 *)]; + char rmtp_l_[PADL_(struct timespec32 *)]; struct timespec32 * rmtp; char rmtp_r_[PADR_(struct timespec32 *)]; +}; struct freebsd32_clock_getcpuclockid2_args { char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)]; char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)]; @@ -728,6 +734,7 @@ int freebsd32_ktimer_create(struct thread *, struct freebsd32_ktimer_create_args int freebsd32_ktimer_settime(struct thread *, struct freebsd32_ktimer_settime_args *); int freebsd32_ktimer_gettime(struct thread *, struct freebsd32_ktimer_gettime_args *); int freebsd32_nanosleep(struct thread *, struct freebsd32_nanosleep_args *); +int freebsd32_clock_nanosleep(struct thread *, struct freebsd32_clock_nanosleep_args *); int freebsd32_clock_getcpuclockid2(struct thread *, struct freebsd32_clock_getcpuclockid2_args *); int freebsd32_aio_read(struct thread *, struct freebsd32_aio_read_args *); int freebsd32_aio_write(struct thread *, struct freebsd32_aio_write_args *); @@ -1186,6 +1193,7 @@ int freebsd10_freebsd32_pipe(struct thread *, struct freebsd10_freebsd32_pipe_ar #define FREEBSD32_SYS_AUE_freebsd32_ktimer_settime AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_ktimer_gettime AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_nanosleep AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_clock_nanosleep AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_clock_getcpuclockid2 AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_aio_read AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_aio_write AUE_NULL diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index a80e1e4..9cf249d 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -215,6 +215,7 @@ #define FREEBSD32_SYS_ffclock_getcounter 241 #define FREEBSD32_SYS_ffclock_setestimate 242 #define FREEBSD32_SYS_ffclock_getestimate 243 +#define FREEBSD32_SYS_freebsd32_clock_nanosleep 244 #define FREEBSD32_SYS_freebsd32_clock_getcpuclockid2 247 #define FREEBSD32_SYS_minherit 250 #define FREEBSD32_SYS_rfork 251 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 6b3b4a0..5ef6c83 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -254,7 +254,7 @@ const char *freebsd32_syscallnames[] = { "ffclock_getcounter", /* 241 = ffclock_getcounter */ "ffclock_setestimate", /* 242 = ffclock_setestimate */ "ffclock_getestimate", /* 243 = ffclock_getestimate */ - "#244", /* 244 = nosys */ + "freebsd32_clock_nanosleep", /* 244 = freebsd32_clock_nanosleep */ "#245", /* 245 = nosys */ "#246", /* 246 = nosys */ "freebsd32_clock_getcpuclockid2", /* 247 = freebsd32_clock_getcpuclockid2 */ diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 9a5547f..b709679 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -297,7 +297,7 @@ struct sysent freebsd32_sysent[] = { { AS(ffclock_getcounter_args), (sy_call_t *)sys_ffclock_getcounter, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = ffclock_getcounter */ { AS(ffclock_setestimate_args), (sy_call_t *)sys_ffclock_setestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = ffclock_setestimate */ { AS(ffclock_getestimate_args), (sy_call_t *)sys_ffclock_getestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = ffclock_getestimate */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 244 = nosys */ + { AS(freebsd32_clock_nanosleep_args), (sy_call_t *)freebsd32_clock_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 244 = freebsd32_clock_nanosleep */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 245 = nosys */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 246 = nosys */ { AS(freebsd32_clock_getcpuclockid2_args), (sy_call_t *)freebsd32_clock_getcpuclockid2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 247 = freebsd32_clock_getcpuclockid2 */ diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index ed4722a..002d4a2 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -1260,6 +1260,16 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 1; break; } + /* freebsd32_clock_nanosleep */ + case 244: { + struct freebsd32_clock_nanosleep_args *p = params; + iarg[0] = p->clock_id; /* clockid_t */ + iarg[1] = p->flags; /* int */ + uarg[2] = (intptr_t) p->rqtp; /* const struct timespec32 * */ + uarg[3] = (intptr_t) p->rmtp; /* struct timespec32 * */ + *n_args = 4; + break; + } /* freebsd32_clock_getcpuclockid2 */ case 247: { struct freebsd32_clock_getcpuclockid2_args *p = params; @@ -5312,6 +5322,25 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* freebsd32_clock_nanosleep */ + case 244: + switch(ndx) { + case 0: + p = "clockid_t"; + break; + case 1: + p = "int"; + break; + case 2: + p = "const struct timespec32 *"; + break; + case 3: + p = "struct timespec32 *"; + break; + default: + break; + }; + break; /* freebsd32_clock_getcpuclockid2 */ case 247: switch(ndx) { @@ -9651,6 +9680,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* freebsd32_clock_nanosleep */ + case 244: + if (ndx == 0 || ndx == 1) + p = "int"; + break; /* freebsd32_clock_getcpuclockid2 */ case 247: if (ndx == 0 || ndx == 1) diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 276d79c..d9afd24 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -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(\ diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index e5421b9..d0c1dec 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -290,7 +290,7 @@ struct sysent sysent[] = { { AS(ffclock_getcounter_args), (sy_call_t *)sys_ffclock_getcounter, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = ffclock_getcounter */ { AS(ffclock_setestimate_args), (sy_call_t *)sys_ffclock_setestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = ffclock_setestimate */ { AS(ffclock_getestimate_args), (sy_call_t *)sys_ffclock_getestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = ffclock_getestimate */ - { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 244 = nosys */ + { AS(clock_nanosleep_args), (sy_call_t *)sys_clock_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 244 = clock_nanosleep */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 245 = nosys */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 246 = nosys */ { AS(clock_getcpuclockid2_args), (sy_call_t *)sys_clock_getcpuclockid2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 247 = clock_getcpuclockid2 */ diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 6255d2d..41b086e 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -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); @@ -474,47 +477,95 @@ kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts) return (0); } +int +kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) +{ + + return (kern_clock_nanosleep(td, CLOCK_REALTIME, TIMER_RELTIME, rqt, + rmt)); +} + static uint8_t nanowait[MAXCPU]; int -kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) +kern_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags, + const struct timespec *rqt, struct timespec *rmt) { - struct timespec ts; + 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); @@ -530,21 +581,48 @@ struct nanosleep_args { 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; } diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index b0d782e..21145a6 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -251,7 +251,7 @@ const char *syscallnames[] = { "ffclock_getcounter", /* 241 = ffclock_getcounter */ "ffclock_setestimate", /* 242 = ffclock_setestimate */ "ffclock_getestimate", /* 243 = ffclock_getestimate */ - "#244", /* 244 = nosys */ + "clock_nanosleep", /* 244 = clock_nanosleep */ "#245", /* 245 = nosys */ "#246", /* 246 = nosys */ "clock_getcpuclockid2", /* 247 = clock_getcpuclockid2 */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 36380bd..632e05e 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -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,\ diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index ab98c5a..29a8aa1 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -1290,6 +1290,16 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 1; break; } + /* clock_nanosleep */ + case 244: { + struct clock_nanosleep_args *p = params; + iarg[0] = p->clock_id; /* clockid_t */ + iarg[1] = p->flags; /* int */ + uarg[2] = (intptr_t) p->rqtp; /* const struct timespec * */ + uarg[3] = (intptr_t) p->rmtp; /* struct timespec * */ + *n_args = 4; + break; + } /* clock_getcpuclockid2 */ case 247: { struct clock_getcpuclockid2_args *p = params; @@ -5374,6 +5384,25 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* clock_nanosleep */ + case 244: + switch(ndx) { + case 0: + p = "clockid_t"; + break; + case 1: + p = "int"; + break; + case 2: + p = "const struct timespec *"; + break; + case 3: + p = "struct timespec *"; + break; + default: + break; + }; + break; /* clock_getcpuclockid2 */ case 247: switch(ndx) { @@ -9628,6 +9657,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* clock_nanosleep */ + case 244: + if (ndx == 0 || ndx == 1) + p = "int"; + break; /* clock_getcpuclockid2 */ case 247: if (ndx == 0 || ndx == 1) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index a39a9f2..806a549 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -219,6 +219,7 @@ #define SYS_ffclock_getcounter 241 #define SYS_ffclock_setestimate 242 #define SYS_ffclock_getestimate 243 +#define SYS_clock_nanosleep 244 #define SYS_clock_getcpuclockid2 247 #define SYS_ntp_gettime 248 #define SYS_minherit 250 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 1a073ef..113572d 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -159,6 +159,7 @@ MIASM = \ ffclock_getcounter.o \ ffclock_setestimate.o \ ffclock_getestimate.o \ + clock_nanosleep.o \ clock_getcpuclockid2.o \ ntp_gettime.o \ minherit.o \ diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index ff2a110..16af617 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -83,6 +83,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); diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index df6e8fa..9843ad5 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -698,6 +698,12 @@ struct ffclock_setestimate_args { struct ffclock_getestimate_args { char cest_l_[PADL_(struct ffclock_estimate *)]; struct ffclock_estimate * cest; char cest_r_[PADR_(struct ffclock_estimate *)]; }; +struct clock_nanosleep_args { + char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; + char rqtp_l_[PADL_(const struct timespec *)]; const struct timespec * rqtp; char rqtp_r_[PADR_(const struct timespec *)]; + char rmtp_l_[PADL_(struct timespec *)]; struct timespec * rmtp; char rmtp_r_[PADR_(struct timespec *)]; +}; struct clock_getcpuclockid2_args { char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; @@ -1942,6 +1948,7 @@ int sys_nanosleep(struct thread *, struct nanosleep_args *); int sys_ffclock_getcounter(struct thread *, struct ffclock_getcounter_args *); int sys_ffclock_setestimate(struct thread *, struct ffclock_setestimate_args *); int sys_ffclock_getestimate(struct thread *, struct ffclock_getestimate_args *); +int sys_clock_nanosleep(struct thread *, struct clock_nanosleep_args *); int sys_clock_getcpuclockid2(struct thread *, struct clock_getcpuclockid2_args *); int sys_ntp_gettime(struct thread *, struct ntp_gettime_args *); int sys_minherit(struct thread *, struct minherit_args *); @@ -2713,6 +2720,7 @@ int freebsd10_pipe(struct thread *, struct freebsd10_pipe_args *); #define SYS_AUE_ffclock_getcounter AUE_NULL #define SYS_AUE_ffclock_setestimate AUE_NULL #define SYS_AUE_ffclock_getestimate AUE_NULL +#define SYS_AUE_clock_nanosleep AUE_NULL #define SYS_AUE_clock_getcpuclockid2 AUE_NULL #define SYS_AUE_ntp_gettime AUE_NULL #define SYS_AUE_minherit AUE_MINHERIT |