svn commit: r315526 - in head: contrib/netbsd-tests/lib/libc/sys include lib/libc/include lib/libc/sys lib/libc/tests/sys lib/libthr/thread share/man/man3 sys/compat/freebsd32 sys/kern sys/sys

Eric van Gyzen vangyzen at FreeBSD.org
Sun Mar 19 00:51:16 UTC 2017


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);


More information about the svn-src-all mailing list