Author: vangyzen
Date: Sun Mar 19 00:51:12 2017
New Revision: 315526
URL: https://svnweb.freebsd.org/changeset/base/315526

Log:
  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

Added:
  head/lib/libc/sys/clock_nanosleep.c
     - copied, changed from r315525, head/lib/libc/sys/nanosleep.c
Modified:
  head/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c
  head/include/time.h
  head/lib/libc/include/libc_private.h
  head/lib/libc/include/namespace.h
  head/lib/libc/include/un-namespace.h
  head/lib/libc/sys/Makefile.inc
  head/lib/libc/sys/Symbol.map
  head/lib/libc/sys/interposing_table.c
  head/lib/libc/sys/nanosleep.2
  head/lib/libc/tests/sys/Makefile
  head/lib/libthr/thread/thr_private.h
  head/lib/libthr/thread/thr_syscalls.c
  head/share/man/man3/pthread_testcancel.3
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/kern_time.c
  head/sys/kern/syscalls.master
  head/sys/sys/syscallsubr.h

Modified: head/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c
==============================================================================
--- head/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c  Sun Mar 19 
00:36:29 2017        (r315525)
+++ head/contrib/netbsd-tests/lib/libc/sys/t_clock_nanosleep.c  Sun Mar 19 
00:51:12 2017        (r315526)
@@ -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;

Modified: head/include/time.h
==============================================================================
--- head/include/time.h Sun Mar 19 00:36:29 2017        (r315525)
+++ head/include/time.h Sun Mar 19 00:51:12 2017        (r315526)
@@ -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

Modified: head/lib/libc/include/libc_private.h
==============================================================================
--- head/lib/libc/include/libc_private.h        Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/include/libc_private.h        Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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 aioc
 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, ...);

Modified: head/lib/libc/include/namespace.h
==============================================================================
--- head/lib/libc/include/namespace.h   Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/include/namespace.h   Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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

Modified: head/lib/libc/include/un-namespace.h
==============================================================================
--- head/lib/libc/include/un-namespace.h        Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/include/un-namespace.h        Sun Mar 19 00:51:12 2017        
(r315526)
@@ -37,6 +37,7 @@
 #undef         bind
 #undef         __cap_get_fd
 #undef         __cap_set_fd
+#undef         clock_nanosleep
 #undef         close
 #undef         connect
 #undef         dup

Modified: head/lib/libc/sys/Makefile.inc
==============================================================================
--- head/lib/libc/sys/Makefile.inc      Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/sys/Makefile.inc      Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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

Modified: head/lib/libc/sys/Symbol.map
==============================================================================
--- head/lib/libc/sys/Symbol.map        Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/sys/Symbol.map        Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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;

Copied and modified: head/lib/libc/sys/clock_nanosleep.c (from r315525, 
head/lib/libc/sys/nanosleep.c)
==============================================================================
--- head/lib/libc/sys/nanosleep.c       Sun Mar 19 00:36:29 2017        
(r315525, copy source)
+++ head/lib/libc/sys/clock_nanosleep.c Sun Mar 19 00:51:12 2017        
(r315526)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2017 Eric van Gyzen
  * Copyright (c) 2014 The FreeBSD Foundation.
  * All rights reserved.
  *
@@ -37,13 +38,16 @@ __FBSDID("$FreeBSD$");
 #include <time.h>
 #include "libc_private.h"
 
-__weak_reference(__sys_nanosleep, __nanosleep);
+__weak_reference(__sys_clock_nanosleep, __clock_nanosleep);
 
-#pragma weak nanosleep
+#pragma weak clock_nanosleep
 int
-nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
+    struct timespec *rmtp)
 {
 
-       return (((int (*)(const struct timespec *, struct timespec *))
-           __libc_interposing[INTERPOS_nanosleep])(rqtp, rmtp));
+       return (((int (*)(clockid_t, int, const struct timespec *,
+           struct timespec *))
+           __libc_interposing[INTERPOS_clock_nanosleep])(clock_id, flags,
+           rqtp, rmtp));
 }

Modified: head/lib/libc/sys/interposing_table.c
==============================================================================
--- head/lib/libc/sys/interposing_table.c       Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/sys/interposing_table.c       Sun Mar 19 00:51:12 2017        
(r315526)
@@ -80,6 +80,7 @@ interpos_func_t __libc_interposing[INTER
        SLOT(ppoll, __sys_ppoll),
        SLOT(map_stacks_exec, __libc_map_stacks_exec),
        SLOT(fdatasync, __sys_fdatasync),
+       SLOT(clock_nanosleep, __sys_clock_nanosleep),
 };
 #undef SLOT
 

Modified: head/lib/libc/sys/nanosleep.2
==============================================================================
--- head/lib/libc/sys/nanosleep.2       Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/sys/nanosleep.2       Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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 .

Modified: head/lib/libc/tests/sys/Makefile
==============================================================================
--- head/lib/libc/tests/sys/Makefile    Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libc/tests/sys/Makefile    Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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

Modified: head/lib/libthr/thread/thr_private.h
==============================================================================
--- head/lib/libthr/thread/thr_private.h        Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libthr/thread/thr_private.h        Sun Mar 19 00:51:12 2017        
(r315526)
@@ -865,6 +865,8 @@ int __sys_sigwaitinfo(const sigset_t *se
 
 /* #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
 

Modified: head/lib/libthr/thread/thr_syscalls.c
==============================================================================
--- head/lib/libthr/thread/thr_syscalls.c       Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/lib/libthr/thread/thr_syscalls.c       Sun Mar 19 00:51:12 2017        
(r315526)
@@ -260,6 +260,22 @@ __thr_msync(void *addr, size_t len, int 
 }
 
 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)) =

Modified: head/share/man/man3/pthread_testcancel.3
==============================================================================
--- head/share/man/man3/pthread_testcancel.3    Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/share/man/man3/pthread_testcancel.3    Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c  Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/sys/compat/freebsd32/freebsd32_misc.c  Sun Mar 19 00:51:12 2017        
(r315526)
@@ -129,6 +129,8 @@ CTASSERT(sizeof(struct sigaction32) == 2
 
 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;
        }

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master   Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/sys/compat/freebsd32/syscalls.master   Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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(\

Modified: head/sys/kern/kern_time.c
==============================================================================
--- head/sys/kern/kern_time.c   Sun Mar 19 00:36:29 2017        (r315525)
+++ head/sys/kern/kern_time.c   Sun Mar 19 00:51:12 2017        (r315526)
@@ -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, clo
        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);
@@ -537,21 +588,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;
        }

Modified: head/sys/kern/syscalls.master
==============================================================================
--- head/sys/kern/syscalls.master       Sun Mar 19 00:36:29 2017        
(r315525)
+++ head/sys/kern/syscalls.master       Sun Mar 19 00:51:12 2017        
(r315526)
@@ -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,\

Modified: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h  Sun Mar 19 00:36:29 2017        (r315525)
+++ head/sys/sys/syscallsubr.h  Sun Mar 19 00:51:12 2017        (r315526)
@@ -82,6 +82,8 @@ int   kern_clock_getres(struct thread *td,
            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);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to