forked from Archive/PX4-Autopilot
Fix return values from sleep(), usleep(), and sigtimedwait(). Fix STM32 F2 I2C bug-for-bug compatibility
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4786 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
e48bc996c4
commit
81c4bcb9b5
|
@ -2833,5 +2833,20 @@
|
|||
* stmpe11*: Fix a massive naming problem. All references to STMPE11 should be
|
||||
STMPE812.
|
||||
* arch/arm/src/stm32/stm32_otgfsdev.c: Need to enabled USB reset interrupt
|
||||
(contricuted by Erik Van Der Zalm).
|
||||
(contributed by Erik Van Der Zalm).
|
||||
* sched/sleep.c: Fix the return value from sleep(). The correct behavior is
|
||||
to return the number of unwaited seconds; the implementation was always
|
||||
returning zero.
|
||||
* sched/usleep.c and include/unistd.h: Was a void function, but should return
|
||||
0 on success. usleep() needs to check the return value from sigtimedwait().
|
||||
sigtimewait() returns the signal number that awakened it and an error (EAGAIN)
|
||||
if the timeout expired (normal case).
|
||||
* sched/sig_timedwait.c: Fix sigtimedwait() return value. On a timeout, it was
|
||||
setting the 8-bit si_signo field to -1 and eded up reported successfully awakened
|
||||
by signal 255! Now detects the timeout and errors -1 with errno == EGAIN. If
|
||||
sigtimedwait() is awakened by an unblocked signal, but it is not one of the
|
||||
signals in the waited-for set, it will return -1 with errno == EINTR.
|
||||
* arch/arm/src/stm32_i2c.c: Fix STM32 F2 I2C. It is apparently bug-for-bug
|
||||
compatible with the F4 and needs the same work-around for the missing BTF
|
||||
signal that was needed for the F4.
|
||||
|
||||
|
|
|
@ -1125,11 +1125,11 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Was last byte received or sent? Hmmm... the F4 seems to differ from
|
||||
/* Was last byte received or sent? Hmmm... the F2 and F4 seems to differ from
|
||||
* the F1 in that BTF is not set after data is received (only RXNE).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STM32_STM32F40XX
|
||||
#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
|
||||
if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0)
|
||||
#else
|
||||
if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0)
|
||||
|
|
|
@ -132,7 +132,7 @@ EXTERN int optopt; /* unrecognized option character */
|
|||
EXTERN pid_t getpid(void);
|
||||
EXTERN void _exit(int status) noreturn_function;
|
||||
EXTERN unsigned int sleep(unsigned int seconds);
|
||||
EXTERN void usleep(useconds_t usec);
|
||||
EXTERN int usleep(useconds_t usec);
|
||||
|
||||
/* File descriptor operations */
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* sched/sig_timedwait.c
|
||||
*
|
||||
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2009, 2012 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
|
||||
|
@ -47,15 +47,24 @@
|
|||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "os_internal.h"
|
||||
#include "sig_internal.h"
|
||||
#include "clock_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* This is a special value of si_signo that means that it was the timeout
|
||||
* that awakened the wait... not the receipt of a signal.
|
||||
*/
|
||||
|
||||
#define SIG_WAIT_TIMEOUT 0xff
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
@ -107,7 +116,7 @@ static void sig_timeout(int argc, uint32_t itcb)
|
|||
|
||||
if (u.wtcb->task_state == TSTATE_WAIT_SIG)
|
||||
{
|
||||
u.wtcb->sigunbinfo.si_signo = ERROR;
|
||||
u.wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT;
|
||||
u.wtcb->sigunbinfo.si_code = SI_TIMER;
|
||||
u.wtcb->sigunbinfo.si_value.sival_int = 0;
|
||||
up_unblock_task(u.wtcb);
|
||||
|
@ -151,7 +160,11 @@ static void sig_timeout(int argc, uint32_t itcb)
|
|||
*
|
||||
* Return Value:
|
||||
* Signal number that cause the wait to be terminated, otherwise -1 (ERROR)
|
||||
* is returned.
|
||||
* 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.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
|
@ -270,23 +283,48 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||
|
||||
rtcb->sigwaitmask = NULL_SIGNAL_SET;
|
||||
|
||||
/* When we awaken, the cause will be in the TCB. Return the signal
|
||||
* info to the caller if so requested
|
||||
/* When we awaken, the cause will be in the TCB. Get the signal number
|
||||
* or timeout) that awakened us.
|
||||
*/
|
||||
|
||||
if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo))
|
||||
{
|
||||
/* We were awakened by a signal... but is it one of the signals that
|
||||
* we were waiting for?
|
||||
*/
|
||||
|
||||
if (sigismember(set, rtcb->sigunbinfo.si_signo))
|
||||
{
|
||||
/* Yes.. the return value is the number of the signal that
|
||||
* awakened us.
|
||||
*/
|
||||
|
||||
ret = rtcb->sigunbinfo.si_signo;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No... then set EINTR and report an error */
|
||||
|
||||
set_errno(EINTR);
|
||||
ret = ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we must have been awakened by the timeout. Set EGAIN
|
||||
* and return an error.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT);
|
||||
set_errno(EAGAIN);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
/* Return the signal info to the caller if so requested */
|
||||
|
||||
if (info)
|
||||
{
|
||||
memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo));
|
||||
|
||||
/* The return value is the number of the signal that awakened us */
|
||||
|
||||
ret = info->si_signo;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't know which signal awakened us. This is probably a bug. */
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
irqrestore(saved_state);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* sched/sleep.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007, 2009, 2012 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
|
||||
|
@ -42,6 +42,9 @@
|
|||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Preprocessor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -70,15 +73,54 @@
|
|||
* Function: sleep
|
||||
*
|
||||
* Description:
|
||||
* As typically declared in unistd.h. sleep() is a simple application of
|
||||
* sigtimedwait.
|
||||
* The sleep() function will cause the calling thread to be suspended from
|
||||
* execution until either the number of real-time seconds specified by the
|
||||
* argument 'seconds' 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
|
||||
* due to the scheduling of other activity by the system.
|
||||
*
|
||||
* If a SIGALRM signal is generated for the calling process during
|
||||
* execution of sleep() and if the SIGALRM signal is being ignored or
|
||||
* blocked from delivery, it is unspecified whether sleep() returns
|
||||
* when the SIGALRM signal is scheduled. If the signal is being blocked, it
|
||||
* is also unspecified whether it remains pending after sleep() returns or
|
||||
* it is discarded.
|
||||
*
|
||||
* If a SIGALRM signal is generated for the calling process during
|
||||
* execution of sleep(), except as a result of a prior call to alarm(),
|
||||
* and if the SIGALRM signal is not being ignored or blocked from delivery,
|
||||
* it is unspecified whether that signal has any effect other than causing
|
||||
* sleep() to return.
|
||||
*
|
||||
* If a signal-catching function interrupts sleep() and examines or changes
|
||||
* either the time a SIGALRM is scheduled to be generated, the action
|
||||
* associated with the SIGALRM signal, or whether the SIGALRM signal is
|
||||
* blocked from delivery, the results are unspecified.
|
||||
*
|
||||
* If a signal-catching function interrupts sleep() and calls siglongjmp()
|
||||
* or longjmp() to restore an environment saved prior to the sleep() call,
|
||||
* the action associated with the SIGALRM signal and the time at which a
|
||||
* SIGALRM signal is scheduled to be generated are unspecified. It is also
|
||||
* unspecified whether the SIGALRM signal is blocked, unless the process'
|
||||
* signal mask is restored as part of the environment.
|
||||
*
|
||||
* Implementations may place limitations on the granularity of timer values.
|
||||
* For each interval timer, if the requested timer value requires a finer
|
||||
* granularity than the implementation supports, the actual timer value will
|
||||
* be rounded up to the next supported value.
|
||||
*
|
||||
* Interactions between sleep() and any of setitimer(), ualarm() or sleep()
|
||||
* are unspecified.
|
||||
*
|
||||
* Parameters:
|
||||
* seconds
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero if the requested time has elapsed, or the number of seconds left
|
||||
* to sleep.
|
||||
* If sleep() returns because the requested time has elapsed, the value
|
||||
* returned will be 0. If sleep() returns because of premature arousal due
|
||||
* to delivery of a signal, the return value will be the "unslept" amount
|
||||
* (the requested time minus the time actually slept) in seconds.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
|
@ -89,14 +131,66 @@ unsigned int sleep(unsigned int seconds)
|
|||
sigset_t set;
|
||||
struct timespec ts;
|
||||
struct siginfo value;
|
||||
irqstate_t flags;
|
||||
uint32_t start;
|
||||
int32_t elapsed;
|
||||
int32_t remaining = 0;
|
||||
|
||||
/* Don't sleep if seconds == 0 */
|
||||
|
||||
if (seconds)
|
||||
{
|
||||
/* Set up for the sleep. Using the empty set means that we are not
|
||||
* waiting for any particualar signal. However, any unmasked signal
|
||||
* can still awaken sigtimedwait().
|
||||
*/
|
||||
|
||||
(void)sigemptyset(&set);
|
||||
ts.tv_sec = seconds;
|
||||
ts.tv_sec = seconds;
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
/* Interrupts are disabled around the following so that it is atomic */
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* Get the current time then sleep for the requested time.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
start = clock_systimer();
|
||||
(void)sigtimedwait(&set, &value, &ts);
|
||||
|
||||
/* Calculate the elapsed time (in clock ticks) when we wake up from the sleep.
|
||||
* This is really only necessary if we were awakened from the sleep early
|
||||
* due to the receipt of a signal.
|
||||
*/
|
||||
|
||||
elapsed = clock_systimer() - start;
|
||||
irqrestore(flags);
|
||||
|
||||
/* Get the remaining, un-waited seconds. Note that this calculation
|
||||
* truncates the elapsed seconds in the division. We may have slept some
|
||||
* fraction of a second longer than this! But if the calculation is less
|
||||
* than the 'seconds', we certainly did not sleep for the complete
|
||||
* requested interval.
|
||||
*/
|
||||
|
||||
remaining = (int32_t)seconds - elapsed / TICK_PER_SEC;
|
||||
|
||||
/* Make sure that the elapsed time is non-negative (this should always
|
||||
* be the case unless something exceptional happened while were we
|
||||
* sleeping -- like the clock was reset or we went into a low power mode,
|
||||
* OR if we had to wait a long time to run again after calling
|
||||
* sigtimedwait() making 'elapsed' bigger than it should have been).
|
||||
*/
|
||||
|
||||
if (remaining < 0)
|
||||
{
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (unsigned int)remaining;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* sched/usleep.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007, 2009, 2012 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
|
||||
|
@ -40,6 +40,8 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -69,30 +71,98 @@
|
|||
* Function: usleep
|
||||
*
|
||||
* Description:
|
||||
* BSD version as typically declared in unistd.h. usleep() is a simple
|
||||
* application of sigtimedwait.
|
||||
* The usleep() function will cause the calling thread to be suspended
|
||||
* from execution until either the number of real-time microseconds
|
||||
* specified by the argument 'usec' has elapsed or a signal is delivered
|
||||
* to the calling thread. The suspension time may be longer than requested
|
||||
* due to the scheduling of other activity by the system.
|
||||
*
|
||||
* The 'usec' argument must be less than 1,000,000. If the value of
|
||||
* 'usec' is 0, then the call has no effect.
|
||||
*
|
||||
* If a SIGALRM signal is generated for the calling process during
|
||||
* execution of usleep() and if the SIGALRM signal is being ignored or
|
||||
* blocked from delivery, it is unspecified whether usleep() returns
|
||||
* when the SIGALRM signal is scheduled. If the signal is being blocked, it
|
||||
* is also unspecified whether it remains pending after usleep() returns or
|
||||
* it is discarded.
|
||||
*
|
||||
* If a SIGALRM signal is generated for the calling process during
|
||||
* execution of usleep(), except as a result of a prior call to alarm(),
|
||||
* and if the SIGALRM signal is not being ignored or blocked from delivery,
|
||||
* it is unspecified whether that signal has any effect other than causing
|
||||
* usleep() to return.
|
||||
*
|
||||
* If a signal-catching function interrupts usleep() and examines or changes
|
||||
* either the time a SIGALRM is scheduled to be generated, the action
|
||||
* associated with the SIGALRM signal, or whether the SIGALRM signal is
|
||||
* blocked from delivery, the results are unspecified.
|
||||
*
|
||||
* If a signal-catching function interrupts usleep() and calls siglongjmp()
|
||||
* or longjmp() to restore an environment saved prior to the usleep() call,
|
||||
* the action associated with the SIGALRM signal and the time at which a
|
||||
* SIGALRM signal is scheduled to be generated are unspecified. It is also
|
||||
* unspecified whether the SIGALRM signal is blocked, unless the process'
|
||||
* signal mask is restored as part of the environment.
|
||||
*
|
||||
* Implementations may place limitations on the granularity of timer values.
|
||||
* For each interval timer, if the requested timer value requires a finer
|
||||
* granularity than the implementation supports, the actual timer value will
|
||||
* be rounded up to the next supported value.
|
||||
*
|
||||
* Interactions between usleep() and any of the following are unspecified:
|
||||
*
|
||||
* nanosleep(), setitimer(), timer_create(), timer_delete(), timer_getoverrun(),
|
||||
* timer_gettime(), timer_settime(), ualarm(), sleep()
|
||||
|
||||
* Parameters:
|
||||
* seconds
|
||||
* usec - the number of microseconds to wait.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* On successful completion, usleep() returns 0. Otherwise, it returns -1
|
||||
* and sets errno to indicate the error.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void usleep(useconds_t usec)
|
||||
int usleep(useconds_t usec)
|
||||
{
|
||||
sigset_t set;
|
||||
struct timespec ts;
|
||||
struct siginfo value;
|
||||
int errval;
|
||||
int ret = 0;
|
||||
|
||||
if (usec)
|
||||
{
|
||||
/* Set up for the sleep. Using the empty set means that we are not
|
||||
* waiting for any particualar signal. However, any unmasked signal
|
||||
* can still awaken sigtimedwait().
|
||||
*/
|
||||
|
||||
(void)sigemptyset(&set);
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = (usec % 1000000) * 1000;
|
||||
(void)sigtimedwait(&set, &value, &ts);
|
||||
|
||||
/* usleep is a simple application of sigtimedwait. */
|
||||
|
||||
ret = sigtimedwait(&set, &value, &ts);
|
||||
|
||||
/* 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 = errno;
|
||||
DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR));
|
||||
if (errval == EAGAIN)
|
||||
{
|
||||
/* The timeout "error" is the normal, successful result */
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue