diff options
author | px4dev <px4@purgatory.org> | 2012-08-04 15:12:36 -0700 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2012-08-04 15:12:36 -0700 |
commit | 8a365179eafdf3aea98e60ab9f5882b200d4c759 (patch) | |
tree | 4f38d6d4cd80bd0b6e22e2bb534c3f117ce44e56 /nuttx/sched/sleep.c | |
download | px4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.tar.gz px4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.tar.bz2 px4-firmware-8a365179eafdf3aea98e60ab9f5882b200d4c759.zip |
Fresh import of the PX4 firmware sources.
Diffstat (limited to 'nuttx/sched/sleep.c')
-rw-r--r-- | nuttx/sched/sleep.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/nuttx/sched/sleep.c b/nuttx/sched/sleep.c new file mode 100644 index 000000000..03884a5b6 --- /dev/null +++ b/nuttx/sched/sleep.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * sched/sleep.c + * + * 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 + * 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 <unistd.h> +#include <signal.h> + +#include <nuttx/clock.h> +#include <arch/irq.h> + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sleep + * + * Description: + * 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: + * 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: + * + ****************************************************************************/ + +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_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 (unsigned int)remaining; +} |