sched/signal/sig_nanosleep.c and libc/time/lib_nanosleep.c: Implement clock_nanosleep(). nanosleep() is now reduced to a libc wrapper around clock_nanosleep().

This commit is contained in:
Gregory Nutt 2017-11-11 17:44:59 -06:00
parent 2ae1d62e67
commit 35ee844590
11 changed files with 223 additions and 64 deletions

22
TODO
View File

@ -13,7 +13,7 @@ nuttx/:
(1) SMP
(1) Memory Management (mm/)
(0) Power Management (drivers/pm)
(4) Signals (sched/signal, arch/)
(3) Signals (sched/signal, arch/)
(2) pthreads (sched/pthread)
(0) Message Queues (sched/mqueue)
(8) Kernel/Protected Build
@ -486,26 +486,6 @@ o Signals (sched/signal, arch/)
Status: Open
Priority: Low. Even if there are only 31 usable signals, that is still a lot.
Title: IMPLEMENT clock_nanosleep()
Description: NuttX currently supports only nanosleep(), not clock_nanosleep().
clock_nanosleep() permits you to use either CLOCK_REALTIME, CLOCK_MONOTONIC,
or any other clock that may be available. It also permits you to use
a delay to an absolute time rather than a relative delay from the
current time.
One would think that adding support for clock_nanosleep() should be
simple since it is equivalent to nanosleep() with clock_id ==
CLOCK_REALTIME and with flags == 0. However it is not because there
is an underlying assumption that nanosleep uses CLOCK_REALTIME and
logic like the POSIX timer interfaces. The NuttX nanosleep does not
use CLOCK_REALTIME. It uses the system timer directly. Being able to
switch clocks would require a complete redesign of the existing logic
and the redesign would probably not be as compact or robust as the
existing implementation.
Status: Open
Priority: I consider this low priority at least for now and have no immediate
plans to implement clock_nanosleep().
o pthreads (sched/pthreads)
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -227,7 +227,7 @@
# define SYS_sigsuspend (__SYS_signals+5)
# define SYS_sigtimedwait (__SYS_signals+6)
# define SYS_sigwaitinfo (__SYS_signals+7)
# define SYS_nanosleep (__SYS_signals+8)
# define SYS_clock_nanosleep (__SYS_signals+8)
# define __SYS_clock (__SYS_signals+9)
#else
# define __SYS_clock __SYS_signals

View File

@ -1,7 +1,7 @@
/********************************************************************************
* include/time.h
*
* Copyright (C) 2007-2011, 2013-2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2011, 2013-2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -90,15 +90,17 @@
# define CLOCK_MONOTONIC 1
#endif
/* This is a flag that may be passed to the timer_settime() function */
/* This is a flag that may be passed to the timer_settime() and
* clock_nanosleep() functions.
*/
#define TIMER_ABSTIME 1
#ifndef CONFIG_LIBC_LOCALTIME
/* Local time is the same as gmtime in this implementation */
# define localtime(c) gmtime(c)
# define localtime_r(c,r) gmtime_r(c,r)
# define localtime(c) gmtime(c)
# define localtime_r(c,r) gmtime_r(c,r)
#endif
/********************************************************************************
@ -231,6 +233,9 @@ int timer_settime(timer_t timerid, int flags,
int timer_gettime(timer_t timerid, FAR struct itimerspec *value);
int timer_getoverrun(timer_t timerid);
int clock_nanosleep(clockid_t clockid, int flags,
FAR const struct timespec *rqtp,
FAR struct timespec *rmtp);
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp);
#ifdef CONFIG_LIBC_LOCALTIME

View File

@ -39,6 +39,10 @@ CSRCS += lib_strftime.c lib_calendar2utc.c lib_daysbeforemonth.c
CSRCS += lib_gettimeofday.c lib_isleapyear.c lib_settimeofday.c lib_time.c
CSRCS += lib_difftime.c
ifndef CONFIG_DISABLE_SIGNALS
CSRCS += lib_nanosleep.c
endif
ifdef CONFIG_LIBC_LOCALTIME
CSRCS += lib_localtime.c lib_asctime.c lib_asctimer.c lib_ctime.c
CSRCS += lib_ctimer.c

104
libc/time/lib_nanosleep.c Normal file
View File

@ -0,0 +1,104 @@
/****************************************************************************
* libc/time/nanosleep.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 OWNER OR CONTRIBUTORS 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <time.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nanosleep
*
* Description:
* The nanosleep() function causes the current thread to be suspended from
* execution until either the time interval specified by the rqtp argument
* has elapsed or a signal is delivered to the calling thread and its
* action is to invoke a signal-catching function or to terminate the
* process. The suspension time may be longer than requested because the
* argument value is rounded up to an integer multiple of the sleep
* resolution or because of the scheduling of other activity by the
* system. But, except for the case of being interrupted by a signal, the
* suspension time will not be less than the time specified by rqtp, as
* measured by the system clock, CLOCK_REALTIME.
*
* The use of the nanosleep() function has no effect on the action or
* blockage of any signal.
*
* Parameters:
* rqtp - The amount of time to be suspended from execution.
* rmtp - If the rmtp argument is non-NULL, the timespec structure
* referenced by it is updated to contain the amount of time
* remaining in the interval (the requested time minus the time
* actually slept)
*
* Returned Value:
* If the nanosleep() function returns because the requested time has
* elapsed, its return value is zero.
*
* If the nanosleep() function returns because it has been interrupted by
* a signal, the function returns a value of -1 and sets errno to indicate
* the interruption. If the rmtp argument is non-NULL, the timespec
* structure referenced by it is updated to contain the amount of time
* remaining in the interval (the requested time minus the time actually
* slept). If the rmtp argument is NULL, the remaining time is not
* returned.
*
* If nanosleep() fails, it returns a value of -1 and sets errno to
* indicate the error. The nanosleep() function will fail if:
*
* EINTR - The nanosleep() function was interrupted by a signal.
* EINVAL - The rqtp argument specified a nanosecond value less than
* zero or greater than or equal to 1000 million.
* ENOSYS - The nanosleep() function is not supported by this
* implementation.
*
****************************************************************************/
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
{
/* Calling clock_nanosleep() with the value TIMER_ABSTIME not set in the
* flags argument and with a clock_id of CLOCK_REALTIME is equivalent t
* calling nanosleep() with the same rqtp and rmtp arguments.
*/
return clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp);
}

View File

@ -1,7 +1,8 @@
/****************************************************************************
* lib/lib_sleep.c
*
* Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2009, 2012-2013, 2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -117,14 +118,14 @@ unsigned int sleep(unsigned int seconds)
if (seconds > 0)
{
/* Let nanosleep() do all of the work. */
/* Let clock_nanosleep() do all of the work. */
rqtp.tv_sec = seconds;
rqtp.tv_nsec = 0;
ret = nanosleep(&rqtp, &rmtp);
ret = clock_nanosleep(CLOCK_REALTIME, 0, &rqtp, &rmtp);
/* nanosleep() should only fail if it was interrupted by a signal,
/* clock_nanosleep() should only fail if it was interrupted by a signal,
* but we treat all errors the same,
*/

View File

@ -1,7 +1,8 @@
/****************************************************************************
* lib/lib_usleep.c
*
* Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2009, 2012-2013, 2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -114,13 +115,13 @@ int usleep(useconds_t usec)
if (usec)
{
/* Let nanosleep() do all of the work. */
/* Let clock_nanosleep() do all of the work. */
sec = usec / 1000000;
rqtp.tv_sec = sec;
rqtp.tv_nsec = (usec - (sec * 1000000)) * 1000;
ret = nanosleep(&rqtp, NULL);
ret = clock_nanosleep(CLOCK_REALTIME, 0, &rqtp, NULL);
}
return ret;

View File

@ -199,35 +199,60 @@ int nxsig_nanosleep(FAR const struct timespec *rqtp,
}
/****************************************************************************
* Name: nanosleep
* Name: clock_nanosleep
*
* Description:
* The nanosleep() function causes the current thread to be suspended from
* execution until either the time interval specified by the rqtp argument
* has elapsed or a signal is delivered to the calling thread and its
* action is to invoke a signal-catching function or to terminate the
* process. The suspension time may be longer than requested because the
* argument value is rounded up to an integer multiple of the sleep
* resolution or because of the scheduling of other activity by the
* system. But, except for the case of being interrupted by a signal, the
* suspension time will not be less than the time specified by rqtp, as
* measured by the system clock, CLOCK_REALTIME.
* If the flag TIMER_ABSTIME is not set in the flags argument, the
* clock_nanosleep() function will cause the current thread to be suspended
* from execution until either the time interval specified by the rqtp
* argument has elapsed, or a signal is delivered to the calling thread
* and its action is to invoke a signal-catching function, or the process
* is terminated. The clock used to measure the time will be the clock
* specified by clock_id.
*
* The use of the nanosleep() function has no effect on the action or
* blockage of any signal.
* If the flag TIMER_ABSTIME is set in the flags argument, the
* clock_nanosleep() function will cause the current thread to be
* suspended from execution until either the time value of the clock
* specified by clock_id reaches the absolute time specified by the rqtp
* argument, or a signal is delivered to the calling thread and its action
* is to invoke a signal-catching function, or the process is terminated. If,
* at the time of the call, the time value specified by rqtp is less than
* or equal to the time value of the specified clock, then clock_nanosleep()
* will return immediately and the calling process will not be suspended.
*
* The suspension time caused by this function may be longer than requested
* because the argument value is rounded up to an integer multiple of the
* sleep resolution, or because of the scheduling of other activity by the
* system. But, except for the case of being interrupted by a signal, the
* suspension time for the relative clock_nanosleep() function (that is,
* with the TIMER_ABSTIME flag not set) will not be less than the time
* interval specified by rqtp, as measured by the corresponding clock. The
* suspension for the absolute clock_nanosleep() function (that is, with
* the TIMER_ABSTIME flag set) will be in effect at least until the value
* of the corresponding clock reaches the absolute time specified by rqtp,
* except for the case of being interrupted by a signal.
*
* The use of the clock_nanosleep() function will have no effect on the
* action or blockage of any signal.
*
* The clock_nanosleep() function will fail if the clock_id argument refers
* to the CPU-time clock of the calling thread. It is unspecified whether
* clock_id values of other CPU-time clocks are allowed.
*
* Parameters:
* rqtp - The amount of time to be suspended from execution.
* rmtp - If the rmtp argument is non-NULL, the timespec structure
* referenced by it is updated to contain the amount of time
* remaining in the interval (the requested time minus the time
* actually slept)
* clockid - The clock to use to interpret the absolute time
* flags - Open flags. TIMER_ABSTIME is the only supported flag.
* rqtp - The amount of time to be suspended from execution.
* rmtp - If the rmtp argument is non-NULL, the timespec structure
* referenced by it is updated to contain the amount of time
* remaining in the interval (the requested time minus the time
* actually slept)
*
* Returned Value:
* If the nanosleep() function returns because the requested time has
* If the clock_nanosleep() function returns because the requested time has
* elapsed, its return value is zero.
*
* If the nanosleep() function returns because it has been interrupted by
* If the clock_nanosleep() function returns because it has been interrupted by
* a signal, the function returns a value of -1 and sets errno to indicate
* the interruption. If the rmtp argument is non-NULL, the timespec
* structure referenced by it is updated to contain the amount of time
@ -235,28 +260,66 @@ int nxsig_nanosleep(FAR const struct timespec *rqtp,
* slept). If the rmtp argument is NULL, the remaining time is not
* returned.
*
* If nanosleep() fails, it returns a value of -1 and sets errno to
* indicate the error. The nanosleep() function will fail if:
* If clock_nanosleep() fails, it returns a value of -1 and sets errno to
* indicate the error. The clock_nanosleep() function will fail if:
*
* EINTR - The nanosleep() function was interrupted by a signal.
* EINTR - The clock_nanosleep() function was interrupted by a signal.
* EINVAL - The rqtp argument specified a nanosecond value less than
* zero or greater than or equal to 1000 million.
* ENOSYS - The nanosleep() function is not supported by this
* ENOSYS - The clock_nanosleep() function is not supported by this
* implementation.
*
****************************************************************************/
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
int clock_nanosleep(clockid_t clockid, int flags,
FAR const struct timespec *rqtp,
FAR struct timespec *rmtp)
{
int ret;
/* nanosleep() is a cancellation point */
/* clock_nanosleep() is a cancellation point */
(void)enter_cancellation_point();
/* Just a wrapper around nxsig_nanosleep() */
/* Check if absolute time is selected */
if ((flags & TIMER_ABSTIME) != 0)
{
struct timespec reltime;
struct timespec now;
irqstate_t irqstate;
/* Calculate the relative time delay. We need to enter a critical
* section early to assure the relative time is valid from this
* point in time.
*/
irqstate = enter_critical_section();
ret = clock_gettime(clockid, &now);
if (ret >= 0)
{
clock_timespec_subtract(rqtp, &now, &reltime);
}
/* Now that we have the relative time, the remaining operations are
* equivalent to nxsig_nanosleep().
*/
ret = nxsig_nanosleep(&reltime, rmtp);
leave_critical_section(irqstate);
}
else
{
/* In the relative time case, clock_nanosleep() is equivalent to
* nanosleep. In this case, it is a paper thin wrapper around
* nxsig_nanosleep().
*/
ret = nxsig_nanosleep(rqtp, rmtp);
}
/* Check if nxsig_nanosleep() succeeded */
ret = nxsig_nanosleep(rqtp, rmtp);
if (ret < 0)
{
set_errno(-ret);

View File

@ -11,6 +11,7 @@
"clearenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int"
"clock_getres","time.h","","int","clockid_t","struct timespec*"
"clock_gettime","time.h","","int","clockid_t","struct timespec*"
"clock_nanosleep","time.h","!defined(CONFIG_DISABLE_SIGNALS)","int","clockid_t","int","FAR const struct timespec *", "FAR struct timespec*"
"clock_settime","time.h","","int","clockid_t","const struct timespec*"
"clock_systimer","nuttx/clock.h","!defined(__HAVE_KERNEL_GLOBALS)","systime_t"
"close","unistd.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","int","int"
@ -55,7 +56,6 @@
"mq_timedsend","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const char*","size_t","int","const struct timespec*"
"mq_unlink","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","const char*"
"on_exit","stdlib.h","defined(CONFIG_SCHED_ONEXIT)","int","CODE void (*)(int, FAR void *)","FAR void *"
"nanosleep","time.h","!defined(CONFIG_DISABLE_SIGNALS)","int","FAR const struct timespec *", "FAR struct timespec*"
"open","fcntl.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","int","..."
"opendir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","FAR DIR*","FAR const char*"
"pgalloc", "nuttx/arch.h", "defined(CONFIG_BUILD_KERNEL)", "uintptr_t", "uintptr_t", "unsigned int"

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -157,7 +157,7 @@ SYSCALL_LOOKUP(up_assert, 2, STUB_up_assert)
SYSCALL_LOOKUP(sigsuspend, 1, STUB_sigsuspend)
SYSCALL_LOOKUP(sigtimedwait, 3, STUB_sigtimedwait)
SYSCALL_LOOKUP(sigwaitinfo, 2, STUB_sigwaitinfo)
SYSCALL_LOOKUP(nanosleep, 2, STUB_nanosleep)
SYSCALL_LOOKUP(clock_nanosleep, 4, STUB_clock_nanosleep)
#endif
/* The following are only defined if the system clock is enabled in the

View File

@ -153,7 +153,8 @@ uintptr_t STUB_sigsuspend(int nbr, uintptr_t parm1);
uintptr_t STUB_sigtimedwait(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3);
uintptr_t STUB_sigwaitinfo(int nbr, uintptr_t parm1, uintptr_t parm2);
uintptr_t STUB_nanosleep(int nbr, uintptr_t parm1, uintptr_t parm2);
uintptr_t STUB_clock_nanosleep(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3, uintptr_t parm4);
/* The following are only defined if the system clock is enabled in the
* NuttX configuration.