diff options
33 files changed, 1646 insertions, 142 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index e9f7b1e4ff..b8546ecc17 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -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 diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index dee837cd7b..77d274b65f 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -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> diff --git a/nuttx/Documentation/NuttxUserGuide.html b/nuttx/Documentation/NuttxUserGuide.html index 134a46dbcd..09bad280c8 100644 --- a/nuttx/Documentation/NuttxUserGuide.html +++ b/nuttx/Documentation/NuttxUserGuide.html @@ -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 <wdog.h> + 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> @@ -2327,6 +2364,8 @@ VxWorks provides the following comparable interface: 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> </p> @@ -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> @@ -2368,6 +2414,11 @@ VxWorks provides the following comparable interface: <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> <ul> @@ -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> @@ -2415,6 +2470,9 @@ VxWorks provides the following comparable interface: 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> <ul> @@ -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> diff --git a/nuttx/TODO b/nuttx/TODO new file mode 100644 index 0000000000..185bcfb441 --- /dev/null +++ b/nuttx/TODO @@ -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 diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt index c614013484..63288f1142 100644 --- a/nuttx/arch/README.txt +++ b/nuttx/arch/README.txt @@ -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 diff --git a/nuttx/arch/c5471/defconfig b/nuttx/arch/c5471/defconfig index 7ebb81587d..a7d27caad8 100644 --- a/nuttx/arch/c5471/defconfig +++ b/nuttx/arch/c5471/defconfig @@ -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 diff --git a/nuttx/arch/dm320/defconfig b/nuttx/arch/dm320/defconfig index bc00741100..cdf7a4326e 100644 --- a/nuttx/arch/dm320/defconfig +++ b/nuttx/arch/dm320/defconfig @@ -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 diff --git a/nuttx/arch/dm320/ld.script b/nuttx/arch/dm320/ld.script index 72dca6590b..6ee7a5db3b 100644 --- a/nuttx/arch/dm320/ld.script +++ b/nuttx/arch/dm320/ld.script @@ -39,7 +39,7 @@ SECTIONS { /* The OS entry point is here */ - . = 0x01108000; + . = 0x01008000; .text : { _stext = ABSOLUTE(.); *(.text) diff --git a/nuttx/arch/pjrc-8051/defconfig b/nuttx/arch/pjrc-8051/defconfig index 28925eec54..cdb73acdab 100644 --- a/nuttx/arch/pjrc-8051/defconfig +++ b/nuttx/arch/pjrc-8051/defconfig @@ -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 diff --git a/nuttx/arch/sim/defconfig b/nuttx/arch/sim/defconfig index 910623d1cf..142d1d4136 100644 --- a/nuttx/arch/sim/defconfig +++ b/nuttx/arch/sim/defconfig @@ -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 diff --git a/nuttx/examples/ostest/Makefile b/nuttx/examples/ostest/Makefile index ed7859fc82..d8101368f3 100644 --- a/nuttx/examples/ostest/Makefile +++ b/nuttx/examples/ostest/Makefile @@ -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)) diff --git a/nuttx/examples/ostest/main.c b/nuttx/examples/ostest/main.c index 497aa3e4fa..b4aa5deeda 100644 --- a/nuttx/examples/ostest/main.c +++ b/nuttx/examples/ostest/main.c @@ -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 */ diff --git a/nuttx/examples/ostest/posixtimer.c b/nuttx/examples/ostest/posixtimer.c new file mode 100644 index 0000000000..619c4f59d1 --- /dev/null +++ b/nuttx/examples/ostest/posixtimer.c @@ -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, ¬ify, &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); +} diff --git a/nuttx/examples/ostest/sighand.c b/nuttx/examples/ostest/sighand.c index 4ea5566121..cab2bcf396 100644 --- a/nuttx/examples/ostest/sighand.c +++ b/nuttx/examples/ostest/sighand.c @@ -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, ¶m); if (status != OK) { diff --git a/nuttx/include/signal.h b/nuttx/include/signal.h index 72c6e3fa7c..02068c2c9b 100644 --- a/nuttx/include/signal.h +++ b/nuttx/include/signal.h @@ -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; diff --git a/nuttx/include/time.h b/nuttx/include/time.h index 5174d69b94..7a97314233 100644 --- a/nuttx/include/time.h +++ b/nuttx/include/time.h @@ -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 { diff --git a/nuttx/include/wdog.h b/nuttx/include/wdog.h index fb45cb6a2a..d54c66fed0 100644 --- a/nuttx/include/wdog.h +++ b/nuttx/include/wdog.h @@ -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 diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile index 4679a846d6..727c4d9c42 100644 --- a/nuttx/sched/Makefile +++ b/nuttx/sched/Makefile @@ -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 diff --git a/nuttx/sched/clock_abstime2ticks.c b/nuttx/sched/clock_abstime2ticks.c new file mode 100644 index 0000000000..359bd21653 --- /dev/null +++ b/nuttx/sched/clock_abstime2ticks.c @@ -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); +} diff --git a/nuttx/sched/clock_internal.h b/nuttx/sched/clock_internal.h index e97c468b7e..85cb13f065 100644 --- a/nuttx/sched/clock_internal.h +++ b/nuttx/sched/clock_internal.h @@ -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 */ diff --git a/nuttx/sched/clock_ticks2time.c b/nuttx/sched/clock_ticks2time.c new file mode 100644 index 0000000000..a7ef5dc9b5 --- /dev/null +++ b/nuttx/sched/clock_ticks2time.c @@ -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; +} diff --git a/nuttx/sched/clock_time2ticks.c b/nuttx/sched/clock_time2ticks.c new file mode 100644 index 0000000000..91c5e976c9 --- /dev/null +++ b/nuttx/sched/clock_time2ticks.c @@ -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; +} diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c index 740cffa10d..4cb128d3cc 100644 --- a/nuttx/sched/os_start.c +++ b/nuttx/sched/os_start.c @@ -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) */ diff --git a/nuttx/sched/pthread_condtimedwait.c b/nuttx/sched/pthread_condtimedwait.c index 6cc6c34eb1..dd8bfaffb0 100644 --- a/nuttx/sched/pthread_condtimedwait.c +++ b/nuttx/sched/pthread_condtimedwait.c @@ -54,8 +54,6 @@ * Definitions ************************************************************/ -#define ECHO_COND_WAIT_SIGNO 3 - /************************************************************ * Private Type Declarations ************************************************************/ @@ -106,70 +104,6 @@ static void pthread_condtimedout(int argc, uint32 pid, uint32 signo, ...) } /************************************************************ - * 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 diff --git a/nuttx/sched/sched_releasetcb.c b/nuttx/sched/sched_releasetcb.c index e37e2bab32..5d3c8fd90b 100644 --- a/nuttx/sched/sched_releasetcb.c +++ b/nuttx/sched/sched_releasetcb.c @@ -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 diff --git a/nuttx/sched/timer_create.c b/nuttx/sched/timer_create.c index b86d38d6dd..40a660f500 100644 --- a/nuttx/sched/timer_create.c +++ b/nuttx/sched/timer_create.c @@ -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 @@ -60,6 +64,52 @@ ********************************************************************************/ /******************************************************************************** + * 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 */ diff --git a/nuttx/sched/timer_delete.c b/nuttx/sched/timer_delete.c index 4dc97a9bde..aed19f76a3 100644 --- a/nuttx/sched/timer_delete.c +++ b/nuttx/sched/timer_delete.c @@ -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 @@ -60,6 +63,43 @@ ********************************************************************************/ /******************************************************************************** + * 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 */ diff --git a/nuttx/sched/timer_getoverrun.c b/nuttx/sched/timer_getoverrun.c index 8dbd8da628..9b23136da7 100644 --- a/nuttx/sched/timer_getoverrun.c +++ b/nuttx/sched/timer_getoverrun.c @@ -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 */ diff --git a/nuttx/sched/timer_gettime.c b/nuttx/sched/timer_gettime.c index 948c6043cf..91a5a60d0f 100644 --- a/nuttx/sched/timer_gettime.c +++ b/nuttx/sched/timer_gettime.c @@ -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 */ diff --git a/nuttx/sched/timer_initialize.c b/nuttx/sched/timer_initialize.c new file mode 100644 index 0000000000..a32189e891 --- /dev/null +++ b/nuttx/sched/timer_initialize.c @@ -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 */ diff --git a/nuttx/sched/timer_internal.h b/nuttx/sched/timer_internal.h new file mode 100644 index 0000000000..1c1e8ec540 --- /dev/null +++ b/nuttx/sched/timer_internal.h @@ -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 */ diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c index 8df4c7e326..fda730f9bc 100644 --- a/nuttx/sched/timer_settime.c +++ b/nuttx/sched/timer_settime.c @@ -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 @@ -56,10 +60,145 @@ ********************************************************************************/ /******************************************************************************** + * 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 */ diff --git a/nuttx/sched/wd_gettime.c b/nuttx/sched/wd_gettime.c new file mode 100644 index 0000000000..77d71eb5ce --- /dev/null +++ b/nuttx/sched/wd_gettime.c @@ -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; +} |