summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html2
-rw-r--r--nuttx/Documentation/NuttxUserGuide.html74
-rw-r--r--nuttx/TODO74
-rw-r--r--nuttx/arch/README.txt2
-rw-r--r--nuttx/arch/c5471/defconfig6
-rw-r--r--nuttx/arch/dm320/defconfig6
-rw-r--r--nuttx/arch/dm320/ld.script2
-rw-r--r--nuttx/arch/pjrc-8051/defconfig6
-rw-r--r--nuttx/arch/sim/defconfig6
-rw-r--r--nuttx/examples/ostest/Makefile3
-rw-r--r--nuttx/examples/ostest/main.c6
-rw-r--r--nuttx/examples/ostest/posixtimer.c245
-rw-r--r--nuttx/examples/ostest/sighand.c12
-rw-r--r--nuttx/include/signal.h54
-rw-r--r--nuttx/include/time.h6
-rw-r--r--nuttx/include/wdog.h1
-rw-r--r--nuttx/sched/Makefile12
-rw-r--r--nuttx/sched/clock_abstime2ticks.c129
-rw-r--r--nuttx/sched/clock_internal.h32
-rw-r--r--nuttx/sched/clock_ticks2time.c94
-rw-r--r--nuttx/sched/clock_time2ticks.c100
-rw-r--r--nuttx/sched/os_start.c18
-rw-r--r--nuttx/sched/pthread_condtimedwait.c70
-rw-r--r--nuttx/sched/sched_releasetcb.c17
-rw-r--r--nuttx/sched/timer_create.c110
-rw-r--r--nuttx/sched/timer_delete.c60
-rw-r--r--nuttx/sched/timer_getoverrun.c4
-rw-r--r--nuttx/sched/timer_gettime.c27
-rw-r--r--nuttx/sched/timer_initialize.c163
-rw-r--r--nuttx/sched/timer_internal.h96
-rw-r--r--nuttx/sched/timer_settime.c233
-rw-r--r--nuttx/sched/wd_gettime.c116
33 files changed, 1646 insertions, 142 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index e9f7b1e4f..b8546ecc1 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 dee837cd7..77d274b65 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 134a46dbc..09bad280c 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 &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>
@@ -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 000000000..185bcfb44
--- /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 c61401348..63288f114 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 7ebb81587..a7d27caad 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 bc0074110..cdf7a4326 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 72dca6590..6ee7a5db3 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 28925eec5..cdb73acda 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 910623d1c..142d1d413 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 ed7859fc8..d8101368f 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 497aa3e4f..b4aa5deed 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 000000000..619c4f59d
--- /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, &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);
+}
diff --git a/nuttx/examples/ostest/sighand.c b/nuttx/examples/ostest/sighand.c
index 4ea556612..cab2bcf39 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, &param);
if (status != OK)
{
diff --git a/nuttx/include/signal.h b/nuttx/include/signal.h
index 72c6e3fa7..02068c2c9 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 5174d69b9..7a9731423 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 fb45cb6a2..d54c66fed 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 4679a846d..727c4d9c4 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 000000000..359bd2165
--- /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 e97c468b7..85cb13f06 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 000000000..a7ef5dc9b
--- /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 000000000..91c5e976c
--- /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 740cffa10..4cb128d3c 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 6cc6c34eb..dd8bfaffb 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 e37e2bab3..5d3c8fd90 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 b86d38d6d..40a660f50 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 4dc97a9bd..aed19f76a 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 8dbd8da62..9b23136da 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 948c6043c..91a5a60d0 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 000000000..a32189e89
--- /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 000000000..1c1e8ec54
--- /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 8df4c7e32..fda730f9b 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 000000000..77d71eb5c
--- /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;
+}