forked from nuttx/nuttx-update
This commit adds internal versions of the signal interfaces:
sigtimedwait() -> nxsig_timedwait() sigwaitinfo() -> nxsig_waitinfo() nanosleep() -> nxsig_nanosleep() The internal OS versions differ from the standard application interfaces in that: - They do not create cancellation points, and - they do not modify the application's errno variable Squashed commit of the following: sched/signal: Replace all usage of sigwaitinfo(), sigtimedwait(), and nanosleep() with the OS internal counterparts nxsig_waitinfo(), nxsig_timedwait(), and nxsig_nanosleep(). sched/signal: Add nxsig_nanosleep(). This is an internal OS version of nanosleep(). It differs in that it does not set the errno varaiable and does not create a cancellation point. sched/signal: Add nxsig_timedwait() and nxsig_waitinfo(). These are internal OS versions of sigtimedwait() and sigwaitinfo(). They differ in that they do not set the errno varaiable and they do not create cancellation points.
This commit is contained in:
parent
aeb3944f0a
commit
fdd0dcc0b6
8 changed files with 390 additions and 144 deletions
|
@ -45,12 +45,132 @@
|
|||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
struct timespec; /* Forward reference */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsig_waitinfo
|
||||
*
|
||||
* Description:
|
||||
* This function is equivalent to nxsig_timedwait with a NULL timeout
|
||||
* parameter.
|
||||
*
|
||||
* This is an internal OS interface. It is functionally equivalent to
|
||||
* sigwaitinfo() except that:
|
||||
*
|
||||
* - It is not a cancellaction point, and
|
||||
* - It does not modify the errno value.
|
||||
*
|
||||
* Parameters:
|
||||
* set - The pending signal set
|
||||
* info - The returned value
|
||||
*
|
||||
* Return Value:
|
||||
* This is an internal OS interface and should not be used by applications.
|
||||
* It follows the NuttX internal error return policy: Zero (OK) is
|
||||
* returned on success. A negated errno value is returned on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define nxsig_waitinfo(s,i) nxsig_timedwait(s,i,NULL)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsig_timedwait
|
||||
*
|
||||
* Description:
|
||||
* This function selects the pending signal set specified by the argument
|
||||
* set. If multiple signals are pending in set, it will remove and return
|
||||
* the lowest numbered one. If no signals in set are pending at the time
|
||||
* of the call, the calling process will be suspended until one of the
|
||||
* signals in set becomes pending, OR until the process is interrupted by
|
||||
* an unblocked signal, OR until the time interval specified by timeout
|
||||
* (if any), has expired. If timeout is NULL, then the timeout interval
|
||||
* is forever.
|
||||
*
|
||||
* If the info argument is non-NULL, the selected signal number is stored
|
||||
* in the si_signo member and the cause of the signal is store din the
|
||||
* si_code member. The content of si_value is only meaningful if the
|
||||
* signal was generated by sigqueue().
|
||||
*
|
||||
* This is an internal OS interface. It is functionally equivalent to
|
||||
* sigtimedwait() except that:
|
||||
*
|
||||
* - It is not a cancellaction point, and
|
||||
* - It does not modify the errno value.
|
||||
*
|
||||
* Parameters:
|
||||
* set - The pending signal set.
|
||||
* info - The returned value (may be NULL).
|
||||
* timeout - The amount of time to wait (may be NULL)
|
||||
*
|
||||
* Return Value:
|
||||
* This is an internal OS interface and should not be used by applications.
|
||||
* It follows the NuttX internal error return policy: Zero (OK) is
|
||||
* returned on success. A negated errno value is returned on failure.
|
||||
*
|
||||
* EAGAIN - No signal specified by set was generated within the specified
|
||||
* timeout period.
|
||||
* EINTR - The wait was interrupted by an unblocked, caught signal.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
||||
FAR const struct timespec *timeout);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsig_nanosleep
|
||||
*
|
||||
* Description:
|
||||
* The nxsig_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 nxsig_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 nxsig_nanosleep() function returns because the requested time
|
||||
* has elapsed, its return value is zero.
|
||||
*
|
||||
* If the nxsig_nanosleep() function returns because it has been
|
||||
* interrupted by a signal, the function returns a negated errno value
|
||||
* 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 nxsig_nanosleep() fails, it returns a negated errno indicating the
|
||||
* cause of the failure. The nxsig_nanosleep() function will fail if:
|
||||
*
|
||||
* EINTR - The nxsig_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 nxsig_nanosleep() function is not supported by this
|
||||
* implementation.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxsig_nanosleep(FAR const struct timespec *rqtp,
|
||||
FAR struct timespec *rmtp);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsig_notification
|
||||
*
|
||||
|
@ -71,7 +191,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_SIG_EVTHREAD) && defined(CONFIG_BUILD_FLAT)
|
||||
int nxsig_notification(pid_t pid, FAR struct sigevent *event);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SIG_EVTHREAD && CONFIG_BUILD_FLAT */
|
||||
#endif /* __INCLUDE_NUTTX_SIGNAL_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* sched/sched/sched_waitid.c
|
||||
*
|
||||
* Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 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
|
||||
|
@ -44,6 +44,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/cancelpt.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
@ -366,10 +367,11 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||
|
||||
/* Wait for any death-of-child signal */
|
||||
|
||||
ret = sigwaitinfo(&set, info);
|
||||
ret = nxsig_waitinfo(&set, info);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
errcode = -ret;
|
||||
goto errout_with_errno;
|
||||
}
|
||||
|
||||
/* Make there this was SIGCHLD */
|
||||
|
@ -403,8 +405,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||
|
||||
else /* if (idtype == P_PGID) */
|
||||
{
|
||||
set_errno(ENOSYS);
|
||||
goto errout;
|
||||
errcode = ENOSYS;
|
||||
goto errout_with_errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +417,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||
|
||||
errout_with_errno:
|
||||
set_errno(errcode);
|
||||
errout:
|
||||
|
||||
leave_cancellation_point();
|
||||
sched_unlock();
|
||||
return ERROR;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/cancelpt.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
|
@ -528,10 +529,11 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||
|
||||
/* Wait for any death-of-child signal */
|
||||
|
||||
ret = sigwaitinfo(&set, &info);
|
||||
ret = nxsig_waitinfo(&set, &info);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_lock;
|
||||
errcode = -ret;
|
||||
goto errout_with_errno;
|
||||
}
|
||||
|
||||
/* Was this the death of the thread we were waiting for? In the of
|
||||
|
@ -569,7 +571,6 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||
errout_with_errno:
|
||||
set_errno(errcode);
|
||||
|
||||
errout_with_lock:
|
||||
leave_cancellation_point();
|
||||
sched_unlock();
|
||||
return ERROR;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* sched/signal/sig/nanosleep.c
|
||||
*
|
||||
* Copyright (C) 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/cancelpt.h>
|
||||
|
||||
#include "clock/clock.h"
|
||||
|
@ -54,6 +55,149 @@
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsig_nanosleep
|
||||
*
|
||||
* Description:
|
||||
* The nxsig_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 nxsig_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 nxsig_nanosleep() function returns because the requested time
|
||||
* has elapsed, its return value is zero.
|
||||
*
|
||||
* If the nxsig_nanosleep() function returns because it has been
|
||||
* interrupted by a signal, the function returns a negated errno value
|
||||
* 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 nxsig_nanosleep() fails, it returns a negated errno indicating the
|
||||
* cause of the failure. The nxsig_nanosleep() function will fail if:
|
||||
*
|
||||
* EINTR - The nxsig_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 nxsig_nanosleep() function is not supported by this
|
||||
* implementation.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxsig_nanosleep(FAR const struct timespec *rqtp,
|
||||
FAR struct timespec *rmtp)
|
||||
{
|
||||
irqstate_t flags;
|
||||
systime_t starttick;
|
||||
sigset_t set;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the start time of the wait. Interrupts are disabled to prevent
|
||||
* timer interrupts while we do tick-related calculations before and
|
||||
* after the wait.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
starttick = clock_systimer();
|
||||
|
||||
/* Set up for the sleep. Using the empty set means that we are not
|
||||
* waiting for any particular signal. However, any unmasked signal can
|
||||
* still awaken nxsig_timedwait().
|
||||
*/
|
||||
|
||||
(void)sigemptyset(&set);
|
||||
|
||||
/* nxsig_nanosleep is a simple application of nxsig_timedwait. */
|
||||
|
||||
ret = nxsig_timedwait(&set, NULL, rqtp);
|
||||
|
||||
/* nxsig_timedwait() cannot succeed. It should always return error with
|
||||
* either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR
|
||||
* meaning that some other unblocked signal was caught.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(ret < 0 && (ret == -EAGAIN || ret == -EINTR));
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
/* The timeout "error" is the normal, successful result */
|
||||
|
||||
leave_critical_section(flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If we get there, the wait has failed because we were awakened by a
|
||||
* signal. Return the amount of "unwaited" time if rmtp is non-NULL.
|
||||
*/
|
||||
|
||||
if (rmtp)
|
||||
{
|
||||
systime_t elapsed;
|
||||
systime_t remaining;
|
||||
ssystime_t ticks;
|
||||
|
||||
/* REVISIT: The conversion from time to ticks and back could
|
||||
* be avoided. clock_timespec_subtract() would be used instead
|
||||
* to get the time difference.
|
||||
*/
|
||||
|
||||
/* First get the number of clock ticks that we were requested to
|
||||
* wait.
|
||||
*/
|
||||
|
||||
(void)clock_time2ticks(rqtp, &ticks);
|
||||
|
||||
/* Get the number of ticks that we actually waited */
|
||||
|
||||
elapsed = clock_systimer() - starttick;
|
||||
|
||||
/* The difference between the number of ticks that we were requested
|
||||
* to wait and the number of ticks that we actualy waited is that
|
||||
* amount of time that we failed to wait.
|
||||
*/
|
||||
|
||||
if (elapsed >= (systime_t)ticks)
|
||||
{
|
||||
remaining = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
remaining = (systime_t)ticks - elapsed;
|
||||
}
|
||||
|
||||
(void)clock_ticks2time((ssystime_t)remaining, rmtp);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nanosleep
|
||||
*
|
||||
|
@ -104,110 +248,21 @@
|
|||
|
||||
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
|
||||
{
|
||||
irqstate_t flags;
|
||||
systime_t starttick;
|
||||
sigset_t set;
|
||||
int errval;
|
||||
#ifdef CONFIG_DEBUG_ASSERTIONS /* Warning avoidance */
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
/* nanosleep() is a cancellation point */
|
||||
|
||||
(void)enter_cancellation_point();
|
||||
|
||||
if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
|
||||
/* Just a wrapper around nxsig_nanosleep() */
|
||||
|
||||
ret = nxsig_nanosleep(rqtp, rmtp);
|
||||
if (ret < 0)
|
||||
{
|
||||
errval = EINVAL;
|
||||
goto errout;
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
/* Get the start time of the wait. Interrupts are disabled to prevent
|
||||
* timer interrupts while we do tick-related calculations before and
|
||||
* after the wait.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
starttick = clock_systimer();
|
||||
|
||||
/* Set up for the sleep. Using the empty set means that we are not
|
||||
* waiting for any particular signal. However, any unmasked signal can
|
||||
* still awaken sigtimedwait().
|
||||
*/
|
||||
|
||||
(void)sigemptyset(&set);
|
||||
|
||||
/* nanosleep is a simple application of sigtimedwait. */
|
||||
|
||||
#ifdef CONFIG_DEBUG_ASSERTIONS /* Warning avoidance */
|
||||
ret = sigtimedwait(&set, NULL, rqtp);
|
||||
#else
|
||||
(void)sigtimedwait(&set, NULL, rqtp);
|
||||
#endif
|
||||
|
||||
/* sigtimedwait() cannot succeed. It should always return error with
|
||||
* either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR
|
||||
* meaning that some other unblocked signal was caught.
|
||||
*/
|
||||
|
||||
errval = get_errno();
|
||||
DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR));
|
||||
|
||||
if (errval == EAGAIN)
|
||||
{
|
||||
/* The timeout "error" is the normal, successful result */
|
||||
|
||||
leave_critical_section(flags);
|
||||
leave_cancellation_point();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If we get there, the wait has failed because we were awakened by a
|
||||
* signal. Return the amount of "unwaited" time if rmtp is non-NULL.
|
||||
*/
|
||||
|
||||
if (rmtp)
|
||||
{
|
||||
systime_t elapsed;
|
||||
systime_t remaining;
|
||||
ssystime_t ticks;
|
||||
|
||||
/* REVISIT: The conversion from time to ticks and back could
|
||||
* be avoided. clock_timespec_subtract() would be used instead
|
||||
* to get the time difference.
|
||||
*/
|
||||
|
||||
/* First get the number of clock ticks that we were requested to
|
||||
* wait.
|
||||
*/
|
||||
|
||||
(void)clock_time2ticks(rqtp, &ticks);
|
||||
|
||||
/* Get the number of ticks that we actually waited */
|
||||
|
||||
elapsed = clock_systimer() - starttick;
|
||||
|
||||
/* The difference between the number of ticks that we were requested
|
||||
* to wait and the number of ticks that we actualy waited is that
|
||||
* amount of time that we failed to wait.
|
||||
*/
|
||||
|
||||
if (elapsed >= (systime_t)ticks)
|
||||
{
|
||||
remaining = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
remaining = (systime_t)ticks - elapsed;
|
||||
}
|
||||
|
||||
(void)clock_ticks2time((ssystime_t)remaining, rmtp);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
errout:
|
||||
set_errno(errval);
|
||||
leave_cancellation_point();
|
||||
return ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/cancelpt.h>
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -92,7 +94,13 @@ int pause(void)
|
|||
* meaning that some unblocked signal was caught.
|
||||
*/
|
||||
|
||||
ret = sigwaitinfo(&set, NULL);
|
||||
ret = nxsig_waitinfo(&set, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
leave_cancellation_point();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/signal.h>
|
||||
#include <nuttx/cancelpt.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
@ -145,7 +146,7 @@ static void nxsig_timeout(int argc, wdparm_t itcb)
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sigtimedwait
|
||||
* Name: nxsig_timedwait
|
||||
*
|
||||
* Description:
|
||||
* This function selects the pending signal set specified by the argument
|
||||
|
@ -162,13 +163,11 @@ static void nxsig_timeout(int argc, wdparm_t itcb)
|
|||
* si_code member. The content of si_value is only meaningful if the
|
||||
* signal was generated by sigqueue().
|
||||
*
|
||||
* The following values for si_code are defined in signal.h:
|
||||
* SI_USER - Signal sent from kill, raise, or abort
|
||||
* SI_QUEUE - Signal sent from sigqueue
|
||||
* SI_TIMER - Signal is result of timer expiration
|
||||
* SI_ASYNCIO - Signal is the result of asynch IO completion
|
||||
* SI_MESGQ - Signal generated by arrival of a message on an
|
||||
* empty message queue.
|
||||
* This is an internal OS interface. It is functionally equivalent to
|
||||
* sigtimedwait() except that:
|
||||
*
|
||||
* - It is not a cancellaction point, and
|
||||
* - It does not modify the errno value.
|
||||
*
|
||||
* Parameters:
|
||||
* set - The pending signal set.
|
||||
|
@ -176,33 +175,28 @@ static void nxsig_timeout(int argc, wdparm_t itcb)
|
|||
* timeout - The amount of time to wait (may be NULL)
|
||||
*
|
||||
* Return Value:
|
||||
* Signal number that cause the wait to be terminated, otherwise -1 (ERROR)
|
||||
* is returned with errno set to either:
|
||||
* This is an internal OS interface and should not be used by applications.
|
||||
* It follows the NuttX internal error return policy: Zero (OK) is
|
||||
* returned on success. A negated errno value is returned on failure.
|
||||
*
|
||||
* EAGAIN - No signal specified by set was generated within the specified
|
||||
* timeout period.
|
||||
* EINTR - The wait was interrupted by an unblocked, caught signal.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
||||
FAR const struct timespec *timeout)
|
||||
int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
||||
FAR const struct timespec *timeout)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
sigset_t intersection;
|
||||
FAR sigpendq_t *sigpend;
|
||||
irqstate_t flags;
|
||||
int32_t waitticks;
|
||||
int ret = ERROR;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(rtcb->waitdog == NULL);
|
||||
|
||||
/* sigtimedwait() is a cancellation point */
|
||||
|
||||
(void)enter_cancellation_point();
|
||||
sched_lock(); /* Not necessary */
|
||||
sched_lock(); /* Should not be necessary */
|
||||
|
||||
/* Several operations must be performed below: We must determine if any
|
||||
* signal is pending and, if not, wait for the signal. Since signals can
|
||||
|
@ -225,7 +219,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||
*/
|
||||
|
||||
sigpend = nxsig_remove_pendingsignal(rtcb, nxsig_lowest(&intersection));
|
||||
ASSERT(sigpend);
|
||||
DEBUGASSERT(sigpend);
|
||||
|
||||
/* Return the signal info to the caller if so requested */
|
||||
|
||||
|
@ -344,10 +338,9 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* No... then set EINTR and report an error */
|
||||
/* No... then report the EINTR error */
|
||||
|
||||
set_errno(EINTR);
|
||||
ret = ERROR;
|
||||
ret = -EINTR;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -357,8 +350,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||
*/
|
||||
|
||||
DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT);
|
||||
set_errno(EAGAIN);
|
||||
ret = ERROR;
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
/* Return the signal info to the caller if so requested */
|
||||
|
@ -372,6 +364,68 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||
}
|
||||
|
||||
sched_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sigtimedwait
|
||||
*
|
||||
* Description:
|
||||
* This function selects the pending signal set specified by the argument
|
||||
* set. If multiple signals are pending in set, it will remove and return
|
||||
* the lowest numbered one. If no signals in set are pending at the time
|
||||
* of the call, the calling process will be suspended until one of the
|
||||
* signals in set becomes pending, OR until the process is interrupted by
|
||||
* an unblocked signal, OR until the time interval specified by timeout
|
||||
* (if any), has expired. If timeout is NULL, then the timeout interval
|
||||
* is forever.
|
||||
*
|
||||
* If the info argument is non-NULL, the selected signal number is stored
|
||||
* in the si_signo member and the cause of the signal is store din the
|
||||
* si_code member. The content of si_value is only meaningful if the
|
||||
* signal was generated by sigqueue().
|
||||
*
|
||||
* The following values for si_code are defined in signal.h:
|
||||
* SI_USER - Signal sent from kill, raise, or abort
|
||||
* SI_QUEUE - Signal sent from sigqueue
|
||||
* SI_TIMER - Signal is result of timer expiration
|
||||
* SI_ASYNCIO - Signal is the result of asynch IO completion
|
||||
* SI_MESGQ - Signal generated by arrival of a message on an
|
||||
* empty message queue.
|
||||
*
|
||||
* Parameters:
|
||||
* set - The pending signal set.
|
||||
* info - The returned value (may be NULL).
|
||||
* timeout - The amount of time to wait (may be NULL)
|
||||
*
|
||||
* Return Value:
|
||||
* Signal number that cause the wait to be terminated, otherwise -1 (ERROR)
|
||||
* is returned with errno set to either:
|
||||
*
|
||||
* EAGAIN - No signal specified by set was generated within the specified
|
||||
* timeout period.
|
||||
* EINTR - The wait was interrupted by an unblocked, caught signal.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
||||
FAR const struct timespec *timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* sigtimedwait() is a cancellation point */
|
||||
|
||||
(void)enter_cancellation_point();
|
||||
|
||||
/* Let nxsig_timedwait() do the work. */
|
||||
|
||||
ret = nxsig_timedwait(set, info, timeout);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
leave_cancellation_point();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* sched/signal/sig_waitinfo.c
|
||||
*
|
||||
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -39,9 +39,10 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/cancelpt.h>
|
||||
#include <nuttx/signal.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
@ -60,9 +61,7 @@
|
|||
*
|
||||
* Return Value:
|
||||
* Signal number that cause the wait to be terminated, otherwise -1 (ERROR)
|
||||
* is returned.
|
||||
*
|
||||
* Assumptions:
|
||||
* is returned and the errno variable is set appropriately.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -74,9 +73,15 @@ int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *info)
|
|||
|
||||
(void)enter_cancellation_point();
|
||||
|
||||
/* Just a wrapper around sigtimedwait() */
|
||||
/* Just a wrapper around nxsig_timedwait() */
|
||||
|
||||
ret = nxsig_timedwait(set, info, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
ret = sigtimedwait(set, info, NULL);
|
||||
leave_cancellation_point();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ void work_process(FAR struct kwork_wqueue_s *wqueue, systime_t period, int wndx)
|
|||
sigaddset(&set, SIGWORK);
|
||||
|
||||
wqueue->worker[wndx].busy = false;
|
||||
DEBUGVERIFY(sigwaitinfo(&set, NULL));
|
||||
DEBUGVERIFY(nxsig_waitinfo(&set, NULL));
|
||||
wqueue->worker[wndx].busy = true;
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue