9
0
Fork 0

Added support for POSIX timers

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@111 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-03-21 17:21:26 +00:00
parent a9a8941d93
commit b3a170538f
33 changed files with 1646 additions and 142 deletions

View File

@ -65,7 +65,7 @@
* Eliminate compilation warnings that that crept into
recent check-ins
* Add kill()
* Added the framework to support POSIX timers (more to be done)
* Added support for POSIX timers
* Some Documentation updates
* Added support for the Neuros OSD / DM320

View File

@ -867,7 +867,7 @@ below and discussed in the following paragraphs:</p>
</ul>
<ul>
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFIG_DISABLE_PTHREAD</code>,
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFI_DISABLE_POSIX_TIMERS</code>, <code>CONFIG_DISABLE_PTHREAD</code>,
<code>CONFIG_DISABLE_SIGNALS</code>, <code>CONFIG_DISABLE_MQUEUE</code>,
</ul>

View File

@ -21,7 +21,7 @@ User's Manual
<P>
Gregory Nutt
<P>
<SMALL>Last Update: January 28, 2007</SMALL>
<SMALL>Last Update: March 21, 2007</SMALL>
</CENTER>
<H1>1.0 <A NAME="Introduction">Introduction</A></H1>
@ -37,7 +37,7 @@ perspective of the firmware developer. This section is divided
into several paragraphs that describe different groups of OS interfaces:
<UL>
<LI>Paragraph 2.1 <A HREF="#Task_Control">Task Control Interfaces</A>
8nnnnn<LI>Paragraph 2.2 <A HREF="#Task_Schedule">Task Scheduling Interfaces</A>
<LI>Paragraph 2.2 <A HREF="#Task_Schedule">Task Scheduling Interfaces</A>
<LI>Paragraph 2.3 <A HREF="#Task_Switch">Task Switching Interfaces</A>
<LI>Paragraph 2.4 <A HREF="#Message_Queue">Named Message Queue Interfaces</A>
<LI>Paragraph 2.5 <A HREF="#Semaphores">Counting Semaphore Interfaces</A>
@ -1840,6 +1840,7 @@ interface of the same name.
<li><a href="#wddelete">2.6.2 wd_delete</a></li>
<li><a href="#wdstart">2.6.3 wd_start</a></li>
<li><a href="#wdcancel">2.6.4 wd_cancel</a></li>
<li><a href="#wdgettime">2.6.5 wd_gettime</a></li>
</ul>
<H3><a name="wdcreate">2.6.1 wd_create</a></H3>
@ -2017,6 +2018,30 @@ VxWorks provides the following comparable interface:
STATUS wdCancel (WDOG_ID wdog);
</PRE>
<h3><a name="wdgettime">2.6.5 wd_gettime</a></h3>
<p>
<b>Function Prototype:</b>
</p>
<pre>
#include &lt;wdog.h&gt;
Sint wd_gettime(WDOG_ID wdog);
</pre>
<p>
<b>Description:</b>
This function returns the time remaining before the the specified watchdog expires.
</p>
<p>
<b>Input Parameters:</b>
<ul>
<li><code>wdog</code>. Identifies the watchdog that the request is for.</li>
</ul>
</p>
<p>
<b>Returned Value:</b>
The time in system ticks remaining until the watchdog time expires. Zero
means either that wdog is not valid or that the wdog has already expired.
</p>
<HR>
<H2><A NAME="ClocksNTimers">2.7 Clocks and Timers</A></H2>
@ -2217,7 +2242,8 @@ VxWorks provides the following comparable interface:
<b>Input Parameters:</b>
</p>
<ul>
<li><code>clockid</code>. Specifies the clock to use as the timing base.</li>
<li><code>clockid</code>. Specifies the clock to use as the timing base.
Must be <code>CLOCK_REALTIME</code>.</li>
<li><code>evp</code>. Refers to a user allocated sigevent structure that defines the
asynchronous notification. evp may be NULL (see above).</li>
<li><code>timerid</code>. The pre-thread timer created by the call to timer_create().</li>
@ -2241,6 +2267,13 @@ VxWorks provides the following comparable interface:
to the CPU-time clock that is specified by clock_id and associated with a
thread different thread invoking timer_create().</li>
</ul>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name. Differences from the full POSIX implementation include:
</p>
<ul>
<li>Only <code>CLOCK_REALTIME</code> is supported for the <code>clockid</code> argument.</li>
</ul>
<H3><a name="timerdelete">2.7.8 timer_delete</A></H3>
<p>
@ -2275,6 +2308,10 @@ VxWorks provides the following comparable interface:
<ul>
<li><code>EINVAL</code>. The timer specified timerid is not valid.</li>
</ul>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name.
</p>
<H3><a name="timersettime">2.7.9 timer_settime</A></H3>
<p>
@ -2326,6 +2363,8 @@ VxWorks provides the following comparable interface:
amount of time before the timer would have expired, or zero if the timer was
disarmed, together with the previous timer reload value. Timers will not
expire before their scheduled time.
</p>
<b>NOTE:</b>At present, the <code>ovalue</code> argument is ignored.
</p>
<p>
<b>Input Parameters:</b>
@ -2334,7 +2373,7 @@ VxWorks provides the following comparable interface:
<li><code>timerid</code>. The pre-thread timer, previously created by the call to timer_create(), to be be set.</li>
<li><code>flags</code>. Specifie characteristics of the timer (see above)</li>
<li><code>value</code>. Specifies the timer value to set</li>
<li><code>ovalue</code>. A location in which to return the time remaining from the previous timer setting.</li>
<li><code>ovalue</code>. A location in which to return the time remaining from the previous timer setting (ignored).</li>
</ul>
<p>
<b>Returned Values:</b>
@ -2348,6 +2387,13 @@ VxWorks provides the following comparable interface:
<li><code>EINVAL</code>. A value structure specified a nanosecond value less than zero or greater than or equal to 1000 million,
and the it_value member of that structure did not specify zero seconds and nanoseconds.</li>
</ul>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name. Differences from the full POSIX implementation include:
</p>
<ul>
<li>The <code>ovalue</code> argument is ignored.</li>
</ul>
<H3><a name="timergettime">2.7.10 timer_gettime</A></H3>
<p>
@ -2367,6 +2413,11 @@ VxWorks provides the following comparable interface:
even if the timer was armed with absolute time. The <code>it_interval</code> member of
<code>value</code> will contain the reload value last set by <code>timer_settime()</code>.
</p>
<p>
Due to the asynchronous operation of this function, the time reported
by this function could be significantly more than that actual time
remaining on the timer at any time.
</p>
<p>
<b>Input Parameters:</b>
</p>
@ -2386,6 +2437,10 @@ VxWorks provides the following comparable interface:
The <code>timerid</code> argument does not correspond to an ID returned by
<code>timer_create()</code> but not yet deleted by <code>timer_delete()</code>.</li>
</ul>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name.
</p>
<H3><a name="timergetoverrun">2.7.11 timer_getoverrun</A></H3>
<p>
@ -2414,6 +2469,9 @@ VxWorks provides the following comparable interface:
for the timer, or if the <i>Realtime Signals Extension</i> is not supported, the
return value of <code>timer_getoverrun()</code> is unspecified.
</p>
<p>
<b>NOTE:</b> This interface is not currently implemented in NuttX.
</p>
<p>
<b>Input Parameters:</b>
</p>
@ -2431,6 +2489,13 @@ VxWorks provides the following comparable interface:
The <code>timerid</code> argument does not correspond to an ID returned by
<code>timer_create()</code> but not yet deleted by <code>timer_delete()</code>.</li>
</ul>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name. Differences from the full POSIX implementation include:
</p>
<ul>
<li>This interface is not currently implemented by NuttX.</li>
</ul>
<B>Assumptions/Limitations:</B>
<P>
@ -4925,6 +4990,7 @@ notify a task when a message is available on a queue.
<li><a href="#wdcancel">wd_cancel</a></li>
<li><a href="#wdcreate">wd_create</a></li>
<li><a href="#wddelete">wd_delete</a></li>
<li><a href="#wdgettime">wd_gettime</a></li>
<li><a href="#wdstart">wd_start</a></li>
</ul>

74
nuttx/TODO Normal file
View File

@ -0,0 +1,74 @@
NuttX TODO List
^^^^^^^^^^^^^^^
Task/Scheduler
^^^^^^^^^^^^^^
- When a tasks exits, shouldn't all of its child pthreads also be terminated?
- Should task_delete() cause atexit() function to be called?
- Implement sys/mman.h and functions
- Implement sys/wait.h and functions
- Implement priority inheritance
- Implement vfork(). Could be tricky because of stack references.
- Make the system timer frequency configurable via defconfig. See:
_POSIX_CLOCKRES_MIN in limits.h
CLK_TCK in time.h
Definitions in sched/clock_internal.h
o Memory Managment
- Add an option to free all memory allocated by a task when the task exits.
This may not be worth the overhead for a deeply embedded system.
o Signals
- 'Standard' signals and signal actions are not supported. Does this
make since in a deeply embedded system?
o pthreads
- pthread_cancel(): Should implemenent cancellation points and pthread_testcancel()
o Libraries
o File system
- This probabaly needs some rethinking.
- Add some concept like mount points to handle mounted "real" filesystems.
o Console Output
o Documentation
- Document fs & driver logic
- Document filesystem, library
o Build system
- Something leaves garbage link 'include' in arch/*/include
- Separate configurations from architectures. arch/* contains
generic logic. Like arch/armnommu, arch/arm, arch/805x, etc.
config/* has like config/pjrc-8052, config/c5471, etc.
o Applications & Tests
o C5471
- At present, there is a failure in the examples/ostest POSIX timer
test when CONFIG_DEBUG is enabled. This is almost certainly yet
another case where printf (or its kin) are being called from a
sensitive area in the OS.
o pjrc-8052 / MCS51
* Current status:
- Basic OS task management seems OK
- Fails when interrupts enabled. The stack pointer is around 0x6e
before the failure occurs. It looks like some issue when the
stack pointer moves from the directly to indirectly addressable
region (0x80 boundary).
- Work on the 8052 is temporarily on hold
- Use timer 0 as system timer. Timer 2 is needed for second UART.
Logic is implemented, but there needs to be a system configuration
to change the ticks-per-second value to match the timer interrupt
rate
- During build, there are several integer overflows reported:
gmtime_r.c aroud lines 184 and 185
clock_initialize.c at line 107
pthread_create.c at 330
sighand.c at 225 and 244
o DM320
- In progress

View File

@ -108,7 +108,7 @@ defconfig -- This is a configuration file similar to the Linux
o pthread_condtimedwait() depends on signals to wake
up waiting tasks.
CONFIG_DISABLE_CLOCK, CONFIG_DISABLE_PTHREAD.
CONFIG_DISABLE_CLOCK, CONFIG_DISABLE_POSIX_TIMERS, CONFIG_DISABLE_PTHREAD.
CONFIG_DISABLE_SIGNALS, CONFIG_DISABLE_MQUEUE

View File

@ -138,6 +138,7 @@ CONFIG_DEV_CONSOLE=y
# up waiting tasks.
#
CONFIG_DISABLE_CLOCK=n
CONFIG_DISABLE_POSIX_TIMERS=n
CONFIG_DISABLE_PTHREAD=n
CONFIG_DISABLE_SIGNALS=n
CONFIG_DISABLE_MQUEUE=n
@ -207,6 +208,10 @@ CONFIG_RRLOAD_BINARY=y
# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog
# structures. The system manages a pool of preallocated
# watchdog structures to minimize dynamic allocations
# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX
# timer structures. The system manages a pool of preallocated
# timer structures to minimize dynamic allocations. Set to
# zero for all dynamic allocations.
#
CONFIG_MAX_TASKS=64
CONFIG_MAX_TASK_ARGS=4
@ -220,6 +225,7 @@ CONFIG_PREALLOC_MQ_MSGS=32
CONFIG_MQ_MAXMSGSIZE=32
CONFIG_MAX_WDOGPARMS=4
CONFIG_PREALLOC_WDOGS=32
CONFIG_PREALLOC_TIMERS=8
#
# Stack and heap information

View File

@ -135,6 +135,7 @@ CONFIG_DEV_CONSOLE=n
# up waiting tasks.
#
CONFIG_DISABLE_CLOCK=n
CONFIG_DISABLE_POSIX_TIMERS=n
CONFIG_DISABLE_PTHREAD=n
CONFIG_DISABLE_SIGNALS=n
CONFIG_DISABLE_MQUEUE=n
@ -204,6 +205,10 @@ CONFIG_RRLOAD_BINARY=y
# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog
# structures. The system manages a pool of preallocated
# watchdog structures to minimize dynamic allocations
# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX
# timer structures. The system manages a pool of preallocated
# timer structures to minimize dynamic allocations. Set to
# zero for all dynamic allocations.
#
CONFIG_MAX_TASKS=64
CONFIG_MAX_TASK_ARGS=4
@ -217,6 +222,7 @@ CONFIG_PREALLOC_MQ_MSGS=32
CONFIG_MQ_MAXMSGSIZE=32
CONFIG_MAX_WDOGPARMS=4
CONFIG_PREALLOC_WDOGS=32
CONFIG_PREALLOC_TIMERS=8
#
# Stack and heap information

View File

@ -39,7 +39,7 @@ SECTIONS
{
/* The OS entry point is here */
. = 0x01108000;
. = 0x01008000;
.text : {
_stext = ABSOLUTE(.);
*(.text)

View File

@ -132,6 +132,7 @@ CONFIG_DEV_CONSOLE=n
# up waiting tasks.
#
CONFIG_DISABLE_CLOCK=y
CONFIG_DISABLE_POSIX_TIMERS=y
CONFIG_DISABLE_PTHREAD=y
CONFIG_DISABLE_SIGNALS=y
CONFIG_DISABLE_MQUEUE=y
@ -201,6 +202,10 @@ CONFIG_RRLOAD_BINARY=n
# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog
# structures. The system manages a pool of preallocated
# watchdog structures to minimize dynamic allocations
# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX
# timer structures. The system manages a pool of preallocated
# timer structures to minimize dynamic allocations. Set to
# zero for all dynamic allocations.
#
CONFIG_MAX_TASKS=8
CONFIG_MAX_TASK_ARGS=4
@ -214,6 +219,7 @@ CONFIG_PREALLOC_MQ_MSGS=0
CONFIG_MQ_MAXMSGSIZE=0
CONFIG_MAX_WDOGPARMS=2
CONFIG_PREALLOC_WDOGS=4
CONFIG_PREALLOC_TIMERS=0
#
# Stack and heap information

View File

@ -98,6 +98,7 @@ CONFIG_DEV_CONSOLE=y
# up waiting tasks.
#
CONFIG_DISABLE_CLOCK=n
CONFIG_DISABLE_POSIX_TIMERS=n
CONFIG_DISABLE_PTHREAD=n
CONFIG_DISABLE_SIGNALS=n
CONFIG_DISABLE_MQUEUE=n
@ -167,6 +168,10 @@ CONFIG_RRLOAD_BINARY=n
# CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog
# structures. The system manages a pool of preallocated
# watchdog structures to minimize dynamic allocations
# CONFIG_PREALLOC_TIMERS - The number of pre-allocated POSIX
# timer structures. The system manages a pool of preallocated
# timer structures to minimize dynamic allocations. Set to
# zero for all dynamic allocations.
#
CONFIG_MAX_TASKS=64
CONFIG_MAX_TASK_ARGS=4
@ -180,6 +185,7 @@ CONFIG_PREALLOC_MQ_MSGS=32
CONFIG_MQ_MAXMSGSIZE=32
CONFIG_MAX_WDOGPARMS=4
CONFIG_PREALLOC_WDOGS=32
CONFIG_PREALLOC_TIMERS=8
#
# Stack and heap information

View File

@ -55,6 +55,9 @@ ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += mqueue.c
endif
endif
ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
CSRCS += posixtimer.c
endif
COBJS = $(CSRCS:.c=$(OBJEXT))

View File

@ -165,6 +165,12 @@ static int user_main(int argc, char *argv[])
sighand_test();
#endif
#if !defined(CONFIG_DISABLE_POSIX_TIMERS) && !defined(CONFIG_DISABLE_SIGNALS)
/* Verify posix timers */
timer_test();
#endif
#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_RR_INTERVAL > 0
/* Verify round robin scheduling */

View File

@ -0,0 +1,245 @@
/***********************************************************************
* posixtimer.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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.
*
***********************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sched.h>
#include <errno.h>
#include "ostest.h"
#ifndef NULL
# define NULL (void*)0
#endif
#define MY_TIMER_SIGNAL 17
#define SIGVALUE_INT 42
static sem_t sem;
static int g_nsigreceived = 0;
static void timer_expiration(int signo, siginfo_t *info, void *ucontext)
{
sigset_t oldset;
sigset_t allsigs;
int status;
printf("timer_expiration: Received signal %d\n" , signo);
g_nsigreceived++;
/* Check signo */
if (signo != MY_TIMER_SIGNAL)
{
printf("timer_expiration: ERROR expected signo=%d\n" , MY_TIMER_SIGNAL);
}
/* Check siginfo */
if (info->si_value.sival_int != SIGVALUE_INT)
{
printf("timer_expiration: ERROR sival_int=%d expected %d\n",
info->si_value.sival_int, SIGVALUE_INT);
}
else
{
printf("timer_expiration: sival_int=%d\n" , info->si_value.sival_int);
}
if (info->si_signo != MY_TIMER_SIGNAL)
{
printf("timer_expiration: ERROR expected si_signo=%d, got=%d\n",
MY_TIMER_SIGNAL, info->si_signo);
}
if (info->si_code == SI_TIMER)
{
printf("timer_expiration: si_code=%d (SI_TIMER)\n" , info->si_code);
}
else
{
printf("timer_expiration: ERROR si_code=%d, expected SI_TIMER=%d\n",
info->si_code, SI_TIMER);
}
/* Check ucontext_t */
printf("timer_expiration: ucontext=%p\n" , ucontext);
/* Check sigprocmask */
(void)sigfillset(&allsigs);
status = sigprocmask(SIG_SETMASK, NULL, &oldset);
if (status != OK)
{
printf("timer_expiration: ERROR sigprocmask failed, status=%d\n",
status);
}
if (oldset != allsigs)
{
printf("timer_expiration: ERROR sigprocmask=%x expected=%x\n",
oldset, allsigs);
}
}
void timer_test(void)
{
struct sched_param param;
sigset_t sigset;
struct sigaction act;
struct sigaction oact;
struct sigevent notify;
struct itimerspec timer;
timer_t timerid;
int status;
int i;
printf("timer_test: Initializing semaphore to 0\n" );
sem_init(&sem, 0, 0);
/* Start waiter thread */
printf("timer_test: Unmasking signal %d\n" , MY_TIMER_SIGNAL);
(void)sigemptyset(&sigset);
(void)sigaddset(&sigset, MY_TIMER_SIGNAL);
status = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
if (status != OK)
{
printf("timer_test: ERROR sigprocmask failed, status=%d\n",
status);
}
printf("timer_test: Registering signal handler\n" );
act.sa_sigaction = timer_expiration;
act.sa_flags = SA_SIGINFO;
(void)sigfillset(&act.sa_mask);
(void)sigdelset(&act.sa_mask, MY_TIMER_SIGNAL);
status = sigaction(MY_TIMER_SIGNAL, &act, &oact);
if (status != OK)
{
printf("timer_test: ERROR sigaction failed, status=%d\n" , status);
}
#ifndef SDCC
printf("timer_test: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n",
oact.sa_sigaction, oact.sa_flags, oact.sa_mask);
#endif
/* Create the POSIX timer */
printf("timer_test: Creating timer\n" );
notify.sigev_notify = SIGEV_SIGNAL;
notify.sigev_signo = MY_TIMER_SIGNAL;
notify.sigev_value.sival_int = SIGVALUE_INT;
status = timer_create(CLOCK_REALTIME, &notify, &timerid);
if (status != OK)
{
printf("timer_test: timer_create failed, errno=%d\n", get_errno_ptr());
goto errorout;
}
/* Start the POSIX timer */
printf("timer_test: Starting timer\n" );
timer.it_value.tv_sec = 2;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 2;
timer.it_interval.tv_nsec = 0;
status = timer_settime(timerid, 0, &timer, NULL);
if (status != OK)
{
printf("timer_test: timer_settime failed, errno=%d\n", get_errno_ptr());
goto errorout;
}
/* Take the semaphore */
for (i = 0; i < 5; i++)
{
printf("timer_test: Waiting on semaphore\n" );
fflush(stdout);
status = sem_wait(&sem);
if (status != 0)
{
int error = *get_errno_ptr();
if (error == EINTR)
{
printf("timer_test: sem_wait() successfully interrupted by signal\n" );
}
else
{
printf("timer_test: ERROR sem_wait failed, errno=%d\n" , error);
}
}
else
{
printf("timer_test: ERROR awakened with no error!\n" );
}
printf("timer_test: g_nsigreceived=%d\n", g_nsigreceived);
}
errorout:
sem_destroy(&sem);
/* Then delete the timer */
printf("timer_test: Deleting timer\n" );
status = timer_delete(timerid);
if (status != OK)
{
printf("timer_test: timer_create failed, errno=%d\n", get_errno_ptr());
}
/* Detach the signal handler */
act.sa_sigaction = SIG_DFL;
status = sigaction(MY_TIMER_SIGNAL, &act, &oact);
printf("timer_test: done\n" );
fflush(stdout);
}

View File

@ -110,7 +110,6 @@ static void wakeup_action(int signo, siginfo_t *info, void *ucontext)
printf("wakeup_action: ERROR sigprocmask=%x expected=%x\n",
oldset, allsigs);
}
}
static int waiter_main(int argc, char *argv[])
@ -120,7 +119,7 @@ static int waiter_main(int argc, char *argv[])
struct sigaction oact;
int status;
printf("wakeup_action: Waiter started\n" );
printf("waiter_main: Waiter started\n" );
printf("waiter_main: Unmasking signal %d\n" , WAKEUP_SIGNAL);
(void)sigemptyset(&sigset);
@ -172,6 +171,11 @@ static int waiter_main(int argc, char *argv[])
printf("waiter_main: ERROR awakened with no error!\n" );
}
/* Detach the signal handler */
act.sa_sigaction = SIG_DFL;
status = sigaction(WAKEUP_SIGNAL, &act, &oact);
printf("waiter_main: done\n" );
fflush(stdout);
threadexited = TRUE;
@ -186,14 +190,12 @@ void sighand_test(void)
int policy;
int status;
printf("waiter_main: Initializing semaphore to 0\n" );
printf("sighand_test: Initializing semaphore to 0\n" );
sem_init(&sem, 0, 0);
/* Start waiter thread */
printf("sighand_test: Starting waiter task\n" );
status = sched_getparam (0, &param);
if (status != OK)
{

View File

@ -67,9 +67,14 @@
#define SIGRTMIN 0 /* First real time signal */
#define SIGRTMAX 31 /* Last real time signal */
/* sigprocmask() "how" definitions. Only one of the following
* can be specified:
*/
/* A few of the real time signals are used within the OS: */
#define SIGALRM 2 /* Default signal used with POSIX timers (used only */
/* no other signal is provided) */
#define SIGCONDTIMEDOUT 3 /* Used in the implementation of */
/* pthread_cond_timedwait */
/* sigprocmask() "how" definitions. Only one of the following can be specified: */
#define SIG_BLOCK 1 /* Block the given signals */
#define SIG_UNBLOCK 2 /* Unblock the given signals */
@ -97,44 +102,49 @@
#define SIGEV_NONE 0 /* No notification desired */
#define SIGEV_SIGNAL 1 /* Notify via signal */
/* Special values of sigaction (all treated like NULL) */
#define SIG_DFL ((CODE void*)0)
#define SIG_IGN ((CODE void*)0)
/********************************************************************************
* Global Type Declarations
********************************************************************************/
/* This defines a set of 32 signals (numbered 0 through 31). */
typedef uint32 sigset_t;
typedef uint32 sigset_t; /* Bit set of 32 signals */
/* This defines the type of the siginfo si_value field */
union sigval
{
int sival_int;
void *sival_ptr;
int sival_int; /* Integer value */
void *sival_ptr; /* Pointer value */
};
/* This structure contains elements that define a queue signal.
* The following is used to attach a signal to a message queue
* to notify a task when a message is available on a queue
/* This structure contains elements that define a queue signal. The following is
* used to attach a signal to a message queue to notify a task when a message is
* available on a queue
*/
struct sigevent
{
int sigev_signo; /* Notification: SIGNAL or NONE */
union sigval sigev_value; /* Generate this signal */
int sigev_notify; /* Queue this value */
ubyte sigev_notify; /* Notification method: SIGEV_SIGNAL or SIGEV_NONE */
ubyte sigev_signo; /* Notification signal */
union sigval sigev_value; /* Data passed with notification */
};
/* The following types is used to pass parameters to/from
* signal handlers
*/
/* The following types is used to pass parameters to/from signal handlers */
typedef struct siginfo
struct siginfo
{
int si_signo;
int si_code;
union sigval si_value;
} siginfo_t;
ubyte si_signo; /* Identifies signal */
ubyte si_code; /* Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ */
union sigval si_value; /* Data passed with signal */
};
typedef struct siginfo siginfo_t;
/* The following structure defines the action to take for given signal */
@ -142,8 +152,8 @@ struct sigaction
{
union
{
void (*_sa_handler)(int);
void (*_sa_sigaction)(int, FAR siginfo_t *, FAR void *);
CODE void (*_sa_handler)(int);
CODE void (*_sa_sigaction)(int, FAR siginfo_t *, FAR void *);
} sa_u;
sigset_t sa_mask;
int sa_flags;

View File

@ -70,9 +70,9 @@
* Global Type Declarations
********************************************************************************/
typedef ubyte time_t;
typedef ubyte clockid_t;
typedef ubyte timer_t;
typedef uint32 time_t; /* Holds time in seconds */
typedef ubyte clockid_t; /* Identifies one time base source */
typedef FAR void *timer_t; /* Represents one POSIX timer */
struct timespec
{

View File

@ -102,6 +102,7 @@ EXTERN STATUS wd_delete(WDOG_ID wdog);
EXTERN STATUS wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry,
int argc, ...);
EXTERN STATUS wd_cancel(WDOG_ID wdog);
EXTERN int wd_gettime(WDOG_ID wdog);
#undef EXTERN
#ifdef __cplusplus

View File

@ -55,10 +55,11 @@ SCHED_SRCS = sched_setparam.c sched_getparam.c \
sched_yield.c sched_rrgetinterval.c sched_foreach.c \
sched_getprioritymax.c sched_getprioritymin.c \
sched_lock.c sched_unlock.c sched_lockcount.c
WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c
WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c \
wd_gettime.c
TIME_SRCS = sched_processtimer.c sleep.c usleep.c
CLOCK_SRCS = clock_initialize.c mktime.c gmtime_r.c clock_settime.c \
clock_gettime.c clock_getres.c
CLOCK_SRCS = clock_initialize.c mktime.c gmtime_r.c clock_settime.c clock_gettime.c \
clock_getres.c clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c
SIGNAL_SRCS = sig_initialize.c \
sig_action.c sig_procmask.c sig_pending.c sig_suspend.c \
sig_kill.c sig_queue.c sig_waitinfo.c sig_timedwait.c \
@ -99,8 +100,9 @@ SEM_SRCS = sem_initialize.c sem_init.c sem_destroy.c\
sem_open.c sem_close.c sem_unlink.c \
sem_wait.c sem_trywait.c sem_post.c sem_getvalue.c \
sem_waitirq.c sem_findnamed.c
ifneq ($(CONFIG_DISABLE_POSIX_TIMERSA),y)
TIMERS_SRCS = timer_create.c timer_delete.c timer_getoverrun.c timer_gettime.c timer_settime.c
ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c \
timer_gettime.c timer_settime.c
endif
IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c

View File

@ -0,0 +1,129 @@
/********************************************************************************
* clock_abstime2ticks.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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 <sys/types.h>
#include <time.h>
#include <errno.h>
#include <debug.h>
#include "clock_internal.h"
/********************************************************************************
* Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Global Variables
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/
/********************************************************************************
* Function: clock_abstime2ticks
*
* Description:
* Convert an absolute timespec delay to system timer ticks.
*
* Parameters:
* clockid - The timing source to use in the conversion
* reltime - Convert this absolue time to system clock ticks.
* ticks - Return the converted number of ticks here.
*
* Return Value:
* OK on success; A non-zero error number on failure;
*
* Assumptions:
* Interrupts should be disabled so that the time is not changing during the
* calculation
*
********************************************************************************/
extern int clock_abstime2ticks(clockid_t clockid, const struct timespec *abstime,
int *ticks)
{
struct timespec currtime;
struct timespec reltime;
sint32 relusec;
int ret;
/* Convert the timespec to clock ticks. NOTE: Here we use
* internal knowledge that CLOCK_REALTIME is defined to be zero!
*/
ret = clock_gettime(clockid, &currtime);
if (ret)
{
return EINVAL;
}
/* The relative time to wait is the absolute time minus the
* current time.
*/
reltime.tv_nsec = (abstime->tv_nsec - currtime.tv_nsec);
reltime.tv_sec = (abstime->tv_sec - currtime.tv_sec);
/* Check if we were supposed to borrow from the seconds to
* borrow from the seconds
*/
if (reltime.tv_nsec < 0)
{
reltime.tv_nsec += NSEC_PER_SEC;
reltime.tv_sec -= 1;
}
/* Convert this relative time into microseconds.*/
return clock_time2ticks(&reltime, ticks);
}

View File

@ -1,4 +1,4 @@
/************************************************************
/********************************************************************************
* clock_internal.h
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
@ -31,21 +31,21 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************/
********************************************************************************/
#ifndef __CLOCK_INTERNAL_H
#define __CLOCK_INTERNAL_H
/************************************************************
/********************************************************************************
* Included Files
************************************************************/
********************************************************************************/
#include <sys/types.h>
#include <nuttx/compiler.h>
/************************************************************
/********************************************************************************
* Definitions
************************************************************/
********************************************************************************/
/* Timing constants */
@ -59,7 +59,7 @@
#define MSEC_PER_TICK 10
#define USEC_PER_TICK (MSEC_PER_TICK * USEC_PER_MSEC)
#define NSEC_PER_TICK (MSEC_PER_TICK * NSEC_PER_MSEC)
#define TICK_PER_SEC (MSEC_PER_SEC / MSEC_PER_TICK)
#define TICK_PER_SEC (MSEC_PER_SEC / MSEC_PER_TICK)
#define MSEC2TICK(msec) (((msec)+(MSEC_PER_TICK/2))/MSEC_PER_TICK)
#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK)
@ -73,25 +73,29 @@
# define GREG_DAY 15
#endif /* CONFIG_JULIAN_TIME */
/************************************************************
/********************************************************************************
* Public Type Definitions
************************************************************/
********************************************************************************/
/************************************************************
/********************************************************************************
* Global Variables
************************************************************/
********************************************************************************/
extern volatile uint32 g_system_timer;
extern struct timespec g_basetime;
extern uint32 g_tickbias;
extern uint32 g_tickbias;
/************************************************************
/********************************************************************************
* Public Function Prototypes
************************************************************/
********************************************************************************/
extern void weak_function clock_initialize(void);
extern void weak_function clock_timer(void);
extern time_t clock_calendar2utc(int year, int month, int day);
extern int clock_abstime2ticks(clockid_t clockid, const struct timespec *abstime,
int *ticks);
extern int clock_time2ticks(const struct timespec *reltime, int *ticks);
extern int clock_ticks2time(int ticks, struct timespec *reltime);
#endif /* __CLOCK_INTERNAL_H */

View File

@ -0,0 +1,94 @@
/********************************************************************************
* clock_ticks2time.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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 <sys/types.h>
#include <time.h>
#include "clock_internal.h"
/********************************************************************************
* Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Global Variables
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/
/********************************************************************************
* Function: clock_ticks2time
*
* Description:
* Convert the system time tick value to a relative time.
*
* Parameters:
* ticks - The number of system time ticks to convert.
* reltime - Return the converted system time here.
*
* Return Value:
* Always returns OK
*
* Assumptions:
*
********************************************************************************/
int clock_ticks2time(int ticks, struct timespec *reltime)
{
int remainder;
reltime->tv_sec = ticks / TICK_PER_SEC;
remainder = ticks - TICK_PER_SEC * reltime->tv_sec;
reltime->tv_nsec = remainder * NSEC_PER_TICK;
return OK;
}

View File

@ -0,0 +1,100 @@
/********************************************************************************
* clock_time2ticks.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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 <sys/types.h>
#include <time.h>
#include "clock_internal.h"
/********************************************************************************
* Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Global Variables
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/
/********************************************************************************
* Function: clock_time2ticks
*
* Description:
* Convert a timespec delay to system timer ticks. This function is suitable
* for calculating relative time delays and does not depend on the other
* clock_* logic.
*
* Parameters:
* reltime - Convert this relative time to system clock ticks.
* ticks - Return the converted number of ticks here.
*
* Return Value:
* Always returns OK
*
* Assumptions:
*
********************************************************************************/
int clock_time2ticks(const struct timespec *reltime, int *ticks)
{
sint32 relusec;
/* Convert the relative time into microseconds.*/
relusec = reltime->tv_sec * USEC_PER_SEC + reltime->tv_nsec / NSEC_PER_USEC;
/* Convert microseconds to clock ticks */
*ticks = relusec / USEC_PER_TICK;
return OK;
}

View File

@ -57,6 +57,7 @@
# include "pthread_internal.h"
#endif
#include "clock_internal.h"
#include "timer_internal.h"
#include "irq_internal.h"
/************************************************************
@ -304,6 +305,15 @@ void os_start(void)
user_initialize();
}
/* Initialize the watchdog facility (if included in the link) */
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (wd_initialize != NULL)
#endif
{
wd_initialize();
}
/* Initialize the POSIX timer facility (if included in the link) */
#ifndef CONFIG_DISABLE_CLOCK
@ -315,14 +325,14 @@ void os_start(void)
}
#endif
/* Initialize the watchdog facility (if included in the link) */
#ifndef CONFIG_DISABLE_POSIX_TIMERS
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (wd_initialize != NULL)
if (timer_initialize != NULL)
#endif
{
wd_initialize();
timer_initialize();
}
#endif
/* Initialize the signal facility (if in link) */

View File

@ -54,8 +54,6 @@
* Definitions
************************************************************/
#define ECHO_COND_WAIT_SIGNO 3
/************************************************************
* Private Type Declarations
************************************************************/
@ -105,70 +103,6 @@ static void pthread_condtimedout(int argc, uint32 pid, uint32 signo, ...)
#endif
}
/************************************************************
* Function: pthread_timeoutticks
*
* Description:
* Convert a timespec delay to system timer ticks.
*
* Parameters:
* abstime - wait until this absolute time
*
* Return Value:
* The relative number of ticks to wait (or ERROR on
* failure;
*
* Assumptions:
* Interrupts should be disabled so that the time is
* not changing during the calculation
*
************************************************************/
int pthread_timeouticks(const struct timespec *abstime, int *ticks)
{
struct timespec currtime;
struct timespec reltime;
sint32 relusec;
int ret;
/* Convert the timespec to clock ticks. NOTE: Here we use
* internal knowledge that CLOCK_REALTIME is defined to be zero!
*/
ret = clock_gettime(0, &currtime);
if (ret)
{
return EINVAL;
}
/* The relative time to wait is the absolute time minus the
* current time.
*/
reltime.tv_nsec = (abstime->tv_nsec - currtime.tv_nsec);
reltime.tv_sec = (abstime->tv_sec - currtime.tv_sec);
/* Check if we were supposed to borrow from the seconds to
* borrow from the seconds
*/
if (reltime.tv_nsec < 0)
{
reltime.tv_nsec += NSEC_PER_SEC;
reltime.tv_sec -= 1;
}
/* Convert this relative time into microseconds.*/
relusec = reltime.tv_sec * USEC_PER_SEC +
reltime.tv_nsec / NSEC_PER_USEC;
/* Convert microseconds to clock ticks */
*ticks = relusec / USEC_PER_TICK;
return OK;
}
/************************************************************
* Public Functions
************************************************************/
@ -255,7 +189,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
* here so that this time stays valid until the wait begins.
*/
ret = pthread_timeouticks(abstime, &ticks);
ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
if (ret)
{
/* Restore interrupts (pre-emption will be enabled when
@ -299,7 +233,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
/* Start the watchdog */
wd_start(wdog, ticks, (wdentry_t)pthread_condtimedout,
2, (uint32)mypid, (uint32)ECHO_COND_WAIT_SIGNO);
2, (uint32)mypid, (uint32)SIGCONDTIMEDOUT);
/* Take the condition semaphore. Do not restore interrupts
* until we return from the wait. This is necessary to

View File

@ -45,6 +45,7 @@
#include <errno.h>
#include <nuttx/arch.h>
#include "os_internal.h"
#include "timer_internal.h"
/************************************************************
* Private Functions
@ -87,6 +88,7 @@ static void sched_releasepid(pid_t pid)
* OK on success; ERROR on failure
*
* Assumptions:
* Interrupts are disabled.
*
************************************************************/
@ -97,6 +99,21 @@ int sched_releasetcb(FAR _TCB *tcb)
if (tcb)
{
/* Relase any timers that the task might hold. We do this
* before release the PID because it may still be trying to
* deliver signals (although interrupts are should be
* disabled here).
*/
#ifndef CONFIG_DISABLE_POSIX_TIMERS
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (timer_deleteall != NULL)
#endif
{
timer_deleteall(tcb->pid);
}
#endif
/* Release the task's process ID if one was assigned. PID
* zero is reserved for the IDLE task. The TCB of the IDLE
* task is never release so a value of zero simply means that

View File

@ -38,10 +38,14 @@
********************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <wdog.h>
#include <errno.h>
#include "timer_internal.h"
#ifdef CONFIG_POSIX_TIMERS
#ifndef CONFIG_DISABLE_POSIX_TIMERS
/********************************************************************************
* Definitions
@ -59,6 +63,52 @@
* Private Functions
********************************************************************************/
/********************************************************************************
* Function: timer_allocate
*
* Description:
* Allocate one POSIX timer and place it into the allocated timer list.
*
********************************************************************************/
static struct posix_timer_s *timer_allocate(void)
{
struct posix_timer_s *ret;
irqstate_t flags;
/* Try to get a preallocated timer from the free list */
#if CONFIG_PREALLOC_TIMERS > 0
flags = irqsave();
ret = (struct posix_timer_s*)sq_remfirst((sq_queue_t*)&g_freetimers);
irqrestore(flags);
/* Did we get one? */
if (!ret)
#endif
{
/* Allocate a new timer from the heap */
ret = (struct posix_timer_s*)malloc(sizeof(struct posix_timer_s));
if (ret)
{
ret->pt_flags = 0;
}
}
/* If we have a timer, then put it into the allocated timer list */
if (ret)
{
flags = irqsave();
sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers);
irqrestore(flags);
}
return ret;
}
/********************************************************************************
* Public Functions
********************************************************************************/
@ -113,8 +163,60 @@
int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid)
{
#warning "Not Implemented"
return ENOTSUP;
struct posix_timer_s *ret;
WDOG_ID wdog;
/* Sanity checks. Also, we support only CLOCK_REALTIME */
if (!timerid || clockid != CLOCK_REALTIME)
{
*get_errno_ptr() = EINVAL;
return ERROR;
}
/* Allocate a watchdog to provide the underling CLOCK_REALTIME timer */
wdog = wd_create();
if (!wdog)
{
*get_errno_ptr() = EAGAIN;
return ERROR;
}
/* Allocate a timer instance to contain the watchdog */
ret = timer_allocate();
if (!ret)
{
*get_errno_ptr() = EAGAIN;
return ERROR;
}
/* Initialize the timer instance */
ret->pt_owner = getpid();
ret->pt_delay = 0;
ret->pt_wdog = wdog;
if (evp)
{
ret->pt_signo = evp->sigev_signo;
#ifdef CONFIG_CAN_PASS_STRUCTS
ret->pt_value = evp->sigev_value;
#else
ret->pt_value.sival_ptr = evp->sigev_value.sigval_ptr;
#endif
}
else
{
ret->pt_signo = SIGALRM;
ret->pt_value.sival_ptr = ret;
}
/* Return the timer */
*timerid = ret;
return OK;
}
#endif /* CONFIG_POSIX_TIMERS */
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

View File

@ -39,7 +39,10 @@
#include <nuttx/config.h>
#include <time.h>
#include <queue.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include "timer_internal.h"
#ifndef CONFIG_DISABLE_POSIX_TIMERS
@ -59,6 +62,43 @@
* Private Functions
********************************************************************************/
/********************************************************************************
* Function: timer_free
*
* Description:
* Remove the timer from the allocated timer list and free it or return it to
* the free list (depending on whether or not the timer is one of the
* preallocated timers)
*
********************************************************************************/
static void timer_free(struct posix_timer_s *timer)
{
irqstate_t flags;
/* Remove the timer from the allocated list */
flags = irqsave();
sq_rem((FAR sq_entry_t*)timer, (sq_queue_t*)&g_alloctimers);
/* Return it to the free list if it is one of the preallocated timers */
#if CONFIG_PREALLOC_TIMERS > 0
if ((timer->pt_flags & PT_FLAGS_PREALLOCATED) != 0)
{
sq_addlast((FAR sq_entry_t*)&timer, (FAR sq_queue_t*)&g_freetimers);
irqrestore(flags);
}
else
#endif
{
/* Otherwise, return it to the heap */
irqrestore(flags);
sched_free(timer);
}
}
/********************************************************************************
* Public Functions
********************************************************************************/
@ -88,8 +128,24 @@
int timer_delete(timer_t timerid)
{
#warning "Not Implemented"
return ENOTSUP;
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid;
/* Some sanity checks */
if (!timer)
{
*get_errno_ptr() = EINVAL;
return ERROR;
}
/* Disarm the timer */
(void)wd_cancel(timer->pt_wdog);
/* Release the timer structure */
timer_free(timer);
return OK;
}
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <time.h>
#include <errno.h>
#include "timer_internal.h"
#ifndef CONFIG_DISABLE_POSIX_TIMERS
@ -102,7 +103,8 @@
int timer_getoverrun(timer_t timerid)
{
#warning "Not Implemented"
return ENOTSUP;
*get_errno_ptr() = ENOSYS;
return ERROR;
}
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

View File

@ -40,6 +40,8 @@
#include <nuttx/config.h>
#include <time.h>
#include <errno.h>
#include "clock_internal.h"
#include "timer_internal.h"
#ifndef CONFIG_DISABLE_POSIX_TIMERS
@ -87,14 +89,33 @@
* EINVAL - The timerid argument does not correspond to an ID returned by
* timer_create() but not yet deleted by timer_delete().
*
* Assumptions:
* Assumptions/Limitations:
* Due to the asynchronous operation of this function, the time reported
* by this function could be significantly more than that actual time
* remaining on the timer at any time.
*
********************************************************************************/
int timer_gettime(timer_t timerid, FAR struct itimerspec *value)
{
#warning "Not Implemented"
return ENOTSUP;
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid;
int ticks;
if (!timer || !value)
{
*get_errno_ptr() = EINVAL;
return ERROR;
}
/* Get the number of ticks before the underlying watchdog expires */
ticks = wd_gettime(timer->pt_wdog);
/* Convert that to a struct timespec and return it */
(void)clock_ticks2time(ticks, &value->it_value);
(void)clock_ticks2time(timer->pt_delay, &value->it_interval);
return OK;
}
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

View File

@ -0,0 +1,163 @@
/********************************************************************************
* timer_initialize.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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>
#include <queue.h>
#include <errno.h>
#include <nuttx/compiler.h>
#include "timer_internal.h"
#ifndef CONFIG_DISABLE_POSIX_TIMERS
/********************************************************************************
* Definitions
********************************************************************************/
/********************************************************************************
* Private Data
********************************************************************************/
/* These are the preallocated times */
#if CONFIG_PREALLOC_TIMERS > 0
static struct posix_timer_s g_prealloctimers[CONFIG_PREALLOC_TIMERS];
#endif
/********************************************************************************
* Public Data
********************************************************************************/
/* This is a list of free, preallocated timer structures */
#if CONFIG_PREALLOC_TIMERS > 0
volatile sq_queue_t g_freetimers;
#endif
/* This is a list of instantiated timer structures -- active and inactive. The
* timers are place on this list by timer_create() and removed from the list by
* timer_delete() or when the owning thread exits.
*/
volatile sq_queue_t g_alloctimers;
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/
/********************************************************************************
* Function: timer_initialize
*
* Description:
* Boot up configuration of the POSIX timer facility.
*
* Parameters:
* None
*
* Return Value:
* None
*
* Assumptions:
*
********************************************************************************/
void weak_function timer_initialize(void)
{
int i;
/* Place all of the pre-allocated timers into the free timer list */
#if CONFIG_PREALLOC_TIMERS > 0
sq_init((sq_queue_t*)&g_freetimers);
for (i = 0; i < CONFIG_PREALLOC_TIMERS; i++)
{
g_prealloctimers[i].pt_flags = PT_FLAGS_PREALLOCATED;
sq_addlast((FAR sq_entry_t*)&g_prealloctimers[i], (FAR sq_queue_t*)&g_freetimers);
}
#endif
/* Initialize the list of allocated timers */
sq_init((sq_queue_t*)&g_alloctimers);
}
/********************************************************************************
* Function: timer_deleteall
*
* Description:
* This function is called whenever a thread exits. Any timers owned by that
* thread are deleted as though called by timer_delete().
*
* It is provided in this file so that it can be weakly defined but also,
* like timer_intitialize(), be brought into the link whenever the timer
* resources are referenced.
*
* Parameters:
* pid - the task ID of the thread that exitted
*
* Return Value:
* None
*
* Assumptions:
*
********************************************************************************/
void weak_function timer_deleteall(pid_t pid)
{
FAR struct posix_timer_s *timer;
FAR struct posix_timer_s *next;
irqstate_t flags;
flags = irqsave();
for (timer = g_alloctimers.head; timer; timer = next)
{
next = timer->flink;
if (timer->pt_owner = pid)
{
timer_delete((timer_t)timer);
}
}
}
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

View File

@ -0,0 +1,96 @@
/********************************************************************************
* timer_internal.h
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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.
*
********************************************************************************/
#ifndef __TIMER_INTERNAL_H
#define __TIMER_INTERNAL_H
/********************************************************************************
* Included Files
********************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <wdog.h>
#include <nuttx/compiler.h>
/********************************************************************************
* Definitions
********************************************************************************/
#define PT_FLAGS_PREALLOCATED 0x01
/********************************************************************************
* Public Types
********************************************************************************/
/* This structure represents one POSIX timer */
struct posix_timer_s
{
FAR struct posix_timer_s *flink;
ubyte pt_flags; /* See PT_FLAGS_* definitions */
ubyte pt_signo; /* Notification signal */
pid_t pt_owner; /* Creator of timer */
int pt_delay; /* If non-zero, used to reset repetitive timers */
WDOG_ID pt_wdog; /* The watchdog that provides the timing */
union sigval pt_value; /* Data passed with notification */
};
/********************************************************************************
* Public Data
********************************************************************************/
/* This is a list of free, preallocated timer structures */
#if CONFIG_PREALLOC_TIMERS > 0
extern volatile sq_queue_t g_freetimers;
#endif
/* This is a list of instantiated timer structures -- active and inactive. The
* timers are place on this list by timer_create() and removed from the list by
* timer_delete() or when the owning thread exits.
*/
extern volatile sq_queue_t g_alloctimers;
/********************************************************************************
* Public Function Prototypes
********************************************************************************/
extern void weak_function timer_initialize(void);
extern void weak_function timer_deleteall(pid_t pid);
#endif /* __TIMER_INTERNAL_H */

View File

@ -40,6 +40,10 @@
#include <nuttx/config.h>
#include <time.h>
#include <errno.h>
#include "os_internal.h"
#include "clock_internal.h"
#include "sig_internal.h"
#include "timer_internal.h"
#ifndef CONFIG_DISABLE_POSIX_TIMERS
@ -55,10 +59,145 @@
* Public Data
********************************************************************************/
/********************************************************************************
* Private Function Prototypes
********************************************************************************/
static void inline timer_sigqueue(FAR struct posix_timer_s *timer);
static void inline timer_restart(FAR struct posix_timer_s *timer, uint32 itimer);
static void timer_timeout(int argc, uint32 itimer, ...);
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Function: timer_sigqueue
*
* Description:
* This function basically reimplements sigqueue() so that the si_code can
* be correctly set to SI_TIMER
*
* Parameters:
* timer - A reference to the POSIX timer that just timed out
*
* Return Value:
* None
*
* Assumptions:
* This function executes in the context of the watchod timer interrupt.
*
********************************************************************************/
static void inline timer_sigqueue(FAR struct posix_timer_s *timer)
{
FAR _TCB *tcb;
/* Get the TCB of the receiving task */
tcb = sched_gettcb(timer->pt_owner);
if (tcb)
{
siginfo_t info;
/* Create the siginfo structure */
info.si_signo = timer->pt_signo;
info.si_code = SI_TIMER;
#ifndef CONFIG_CAN_PASS_STRUCTS
info.si_value = timer->pt_value;
#else
info.si_value.sival_ptr = timer->pt_value.sival_ptr;
#endif
/* Send the signal */
(void)sig_received(tcb, &info);
}
}
/********************************************************************************
* Function: timer_restart
*
* Description:
* If a periodic timer has been selected, then restart the watchdog.
*
* Parameters:
* timer - A reference to the POSIX timer that just timed out
*
* Return Value:
* None
*
* Assumptions:
* This function executes in the context of the watchod timer interrupt.
*
********************************************************************************/
static void inline timer_restart(FAR struct posix_timer_s *timer, uint32 itimer)
{
/* If this is a repetitive timer, then restart the watchdog */
if (timer->pt_delay)
{
(void)wd_start(timer->pt_wdog, timer->pt_delay, timer_timeout, 1, itimer);
}
}
/********************************************************************************
* Function: timer_timeout
*
* Description:
* This function is called if the timeout elapses before
* the condition is signaled.
*
* Parameters:
* argc - the number of arguments (should be 1)
* itimer - A reference to the POSIX timer that just timed out
* signo - The signal to use to wake up the task
*
* Return Value:
* None
*
* Assumptions:
* This function executes in the context of the watchod timer interrupt.
*
********************************************************************************/
static void timer_timeout(int argc, uint32 itimer, ...)
{
#ifndef CONFIG_CAN_PASS_STRUCTS
/* On many small machines, pointers are encoded and cannot be simply cast from
* uint32 to _TCB*. The following union works around this (see wdogparm_t).
*/
union
{
FAR struct posix_timer_s *timer;
uint32 itimer;
} u;
u.itimer = itimer;
/* Send the specified signal to the specified task. */
timer_sigqueue(u.timer);
/* If this is a repetitive timer, the restart the watchdog */
timer_restart(u.timer, itimer);
#else
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)itimer;
/* Send the specified signal to the specified task. */
timer_sigqueue(timer);
/* If this is a repetitive timer, the restart the watchdog */
timer_restart(timer, itimer);
#endif
}
/********************************************************************************
* Public Functions
********************************************************************************/
@ -109,7 +248,7 @@
* flags - Specifie characteristics of the timer (see above)
* value - Specifies the timer value to set
* ovalue - A location in which to return the time remaining from the previous
* timer setting.
* timer setting. (ignored)
*
* Return Value:
* If the timer_settime() succeeds, a value of 0 (OK) will be returned.
@ -129,8 +268,96 @@
int timer_settime(timer_t timerid, int flags, FAR const struct itimerspec *value,
FAR struct itimerspec *ovalue)
{
#warning "Not Implemented"
return ENOTSUP;
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid;
irqstate_t state;
int delay;
int ret = OK;
/* Some sanity checks */
if (!timer || !value)
{
*get_errno_ptr() = EINVAL;
return ERROR;
}
/* Disarm the timer (in case the timer was already armed when timer_settime()
* is called).
*/
(void)wd_cancel(timer->pt_wdog);
/* If the it_value member of value is zero, the timer will not be re-armed */
if (value->it_value.tv_sec <= 0 && value->it_value.tv_nsec <= 0)
{
return OK;
}
/* Setup up any repititive timer */
if (value->it_interval.tv_sec > 0 || value->it_interval.tv_nsec > 0)
{
(void)clock_time2ticks(&value->it_interval, &timer->pt_delay);
}
else
{
timer->pt_delay = 0;
}
/* We need to disable timer interrupts through the following section so
* that the system timer is stable.
*/
state = irqsave();
/* Check if abstime is selected */
if ((flags & TIMER_ABSTIME) != 0)
{
#ifdef CONFIG_DISABLE_CLOCK
/* Absolute timing depends upon having access to clock functionality */
*get_errno_ptr() = ENOSYS;
return ERROR;
#else
/* Calculate a delay corresponding to the absolute time in 'value'.
* NOTE: We have internal knowledge the clock_abstime2ticks only
* returns an error if clockid != CLOCK_REALTIME.
*/
(void)clock_abstime2ticks(CLOCK_REALTIME, &value->it_value, &delay);
#endif
}
else
{
/* Calculate a delay assuming that 'value' holds the relative time
* to wait. We have internal knowledge that clock_time2ticks always
* returns success.
*/
(void)clock_time2ticks(&value->it_value, &delay);
}
/* If the time is in the past or now, then set up the next interval
* instead.
*/
if (delay <= 0)
{
delay = timer->pt_delay;
}
/* Then start the watchdog */
if (delay > 0)
{
ret = wd_start(timer->pt_wdog, timer->pt_delay, timer_timeout, 1, (uint32)timer);
}
irqrestore(state);
return ret;
}
#endif /* CONFIG_DISABLE_POSIX_TIMERS */

116
nuttx/sched/wd_gettime.c Normal file
View File

@ -0,0 +1,116 @@
/********************************************************************************
* wd_gettime.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 Gregory Nutt 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 <sys/types.h>
#include <wdog.h>
#include "os_internal.h"
#include "wd_internal.h"
/********************************************************************************
* Definitions
********************************************************************************/
/********************************************************************************
* Private Types
********************************************************************************/
/********************************************************************************
* Global Variables
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Functions
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/
/********************************************************************************
* Function: wd_gettime
*
* Description:
* This function returns the time remaining before the the specified watchdog
* expires.
*
* Parameters:
* wdog = watchdog ID
*
* Return Value:
* The time in system ticks remaining until the watchdog time expires. Zero
* means either that wdog is not valid or that the wdog has already expired.
*
* Assumptions:
*
********************************************************************************/
int wd_gettime(WDOG_ID wdog)
{
irqstate_t flags;
/* Verify the wdog */
flags = irqsave();
if (wdog && wdog->active)
{
/* Traverse the watchdog list accumulating lag times until we find the wdog
* that we are looking for
*/
wdog_t *curr;
int delay = 0;
for (curr = (wdog_t*)g_wdactivelist.head; curr; curr = curr->next)
{
delay += curr->lag;
if (curr == wdog)
{
irqrestore(flags);
return delay;
}
}
}
irqrestore(flags);
return 0;
}