diff --git a/ChangeLog b/ChangeLog
index 4675250845..36c6d86415 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1927,4 +1927,4 @@
SDIO transfer completion events and DMA completion eventes were
not being coordinated correctly.
* configs/stm3210e-eval/nsh2: Enable FAT long file name support
-
+ * sched/sem_timedwait.c: Add the standard sem_timedwait() interface.
diff --git a/Documentation/NuttxUserGuide.html b/Documentation/NuttxUserGuide.html
index 8e97173114..60c63f181f 100644
--- a/Documentation/NuttxUserGuide.html
+++ b/Documentation/NuttxUserGuide.html
@@ -13,7 +13,7 @@
NuttX Operating SystemUser's Manual
by
Gregory Nutt
-
Last Updated: May 8, 2011
+ Last Updated: July 19, 2011
@@ -247,11 +247,11 @@ paragraphs.
Input Parameters:
- - name. Name of the new task
- - priority. Priority of the new task
- - stack_size. size (in bytes) of the stack needed
- - entry. Entry point of a new task
- - argv. A pointer to an array of input parameters. Up to
+
- name. Name of the new task
+ - priority. Priority of the new task
+ - stack_size. size (in bytes) of the stack needed
+ - entry. Entry point of a new task
+ - argv. A pointer to an array of input parameters. Up to
CONFIG_MAX_TASK_ARG
parameters may be provided.
If fewer than CONFIG_MAX_TASK_ARG
parameters are
passed, the list should be terminated with a NULL argv[] value.
@@ -314,13 +314,13 @@ VxWorks provides the following similar interface:
Input Parameters:
- - tcb. Address of the new task's TCB
-
- name. Name of the new task (not used)
-
- priority. Priority of the new task
-
- stack. Start of the pre-allocated stack
-
- stack_size. size (in bytes) of the pre-allocated stack
-
- entry. Entry point of a new task
-
- argv. A pointer to an array of input parameters. Up to
+
- tcb. Address of the new task's TCB
+
- name. Name of the new task (not used)
+
- priority. Priority of the new task
+
- stack. Start of the pre-allocated stack
+
- stack_size. size (in bytes) of the pre-allocated stack
+
- entry. Entry point of a new task
+
- argv. A pointer to an array of input parameters. Up to
CONFIG_MAX_TASK_ARG
parameters may be provided.
If fewer than CONFIG_MAX_TASK_ARG
parameters are
passed, the list should be terminated with a NULL argv[] value.
@@ -378,7 +378,7 @@ scheduler.
Input Parameters:
-- tcb. The TCB for the task for the task (same as the
+
- tcb. The TCB for the task for the task (same as the
task_init argument).
@@ -428,7 +428,7 @@ is the companion to task_create().
Input Parameters:
-- pid. The task ID of the task to delete. An ID of
+
- pid. The task ID of the task to delete. An ID of
zero signifies the calling task.
@@ -482,7 +482,7 @@ execute any function registered with atexit().
Input Parameters:
-- code. (ignored)
+
- code. (ignored)
@@ -505,7 +505,7 @@ And the UNIX interface:
The NuttX exit() differs from ANSI exit() in the following ways:
-- The code parameter is ignored.
+
- The code parameter is ignored.
@@ -525,7 +525,7 @@ it had when it was first started.
Input Parameters:
-- pid. The task ID of the task to delete. An ID of
+
- pid. The task ID of the task to delete. An ID of
zero signifies the calling task.
@@ -556,7 +556,7 @@ VxWorks provides the following similar interface:
- Restart of the currently running task is not supported.
- The VxWorks description says that the ID, priority, etc. take
-the value that they had when the task was terminated.
+the value that they had when the task was terminated.
@@ -743,11 +743,11 @@ interface of the same name.
Input Parameters:
-
- pid. The task ID of the task. If pid is zero, the
+ pid. The task ID of the task. If pid is zero, the
priority of the calling task is set.
-
- policy. Scheduling policy requested (either
SCHED_FIFO
or SCHED_RR
).
+ policy. Scheduling policy requested (either SCHED_FIFO
or SCHED_RR
).
-
param
. A structure whose member sched_priority is the
@@ -795,7 +795,7 @@ policy.
Input Parameters:
- - pid.
+
- pid.
The task ID of the task to query.
If pid is zero, the calling task is queried.
@@ -863,7 +863,7 @@ possible task priority for a specified scheduling policy.
Input Parameters:
-- policy. Scheduling policy requested.
+
- policy. Scheduling policy requested.
@@ -893,7 +893,7 @@ possible task priority for a specified scheduling policy.
Input Parameters:
-- policy. Scheduling policy requested.
+
- policy. Scheduling policy requested.
@@ -930,9 +930,9 @@ interface of the same name.
Input Parameters:
-- pid. The task ID of the task. If pid is zero, the
+
- pid. The task ID of the task. If pid is zero, the
priority of the calling task is returned.
-
- interval. A structure used to return the time slice.
+
- interval. A structure used to return the time slice.
@@ -1105,27 +1105,27 @@ until it is closed by a successful call to mq_close().
Input Parameters:
+ - Task A attempts to acquire the semaphore held by Task C and
+ gets blocked until Task C relinquishes the semaphore.
+ - Task C is allowed to execute again, but gets suspended by some
+ medium-priority Task B.
- At this point, the high-priority Task A cannot execute until
- Task B (and possibly other medium-priority tasks) completes and until
- Task C relinquishes the semaphore. In effect, the high-priority task,
- Task A behaves as though it were lower in priority than the
- low-priority task, Task C! This phenomenon is called priority
- inversion.
+ At this point, the high-priority Task A cannot execute until
+ Task B (and possibly other medium-priority tasks) completes and until
+ Task C relinquishes the semaphore. In effect, the high-priority task,
+ Task A behaves as though it were lower in priority than the
+ low-priority task, Task C! This phenomenon is called priority
+ inversion.
- Some operating systems avoid priority inversion by automatically
- increasing the priority of the low-priority Task C (the operable
- buzz-word for this behavior is priority inheritance). NuttX
+ Some operating systems avoid priority inversion by automatically
+ increasing the priority of the low-priority Task C (the operable
+ buzz-word for this behavior is priority inheritance). NuttX
supports this behavior, but only if CONFIG_PRIORITY_INHERITANCE
is defined in your OS configuration file. If CONFIG_PRIORITY_INHERITANCE
is not defined, then it is left to the designer to provide implementations
@@ -1819,9 +1819,10 @@ interface of the same name.
- 2.5.4 sem_close
- 2.5.5 sem_unlink
- 2.5.6 sem_wait
- - 2.5.7 sem_trywait
- - 2.5.8 sem_post
- - 2.5.9 sem_getvalue
+ - 2.5.7 sem_timedwait
+ - 2.5.8 sem_trywait
+ - 2.5.9 sem_post
+ - 2.5.10 sem_getvalue
@@ -1839,16 +1840,16 @@ sem. Following a successful call to sem_init(), the semaphore
may be used in subsequent calls to sem_wait(), sem_post(), and
sem_trywait(). The semaphore remains usable until it is destroyed.
-Only sem itself may be used for performing synchronization. The
-result of referring to copies of sem in calls to sem_wait(),
-sem_trywait(), sem_post(), and sem_destroy(), is
+Only sem itself may be used for performing synchronization. The
+result of referring to copies of sem in calls to sem_wait(),
+sem_trywait(), sem_post(), and sem_destroy(), is
not defined.
Input Parameters:
-- sem. Semaphore to be initialized
-
- pshared. Process sharing (not used)
-
- value. Semaphore initialization value
+
- sem. Semaphore to be initialized
+
- pshared. Process sharing (not used)
+
- value. Semaphore initialization value
@@ -1878,18 +1879,18 @@ Differences from the full POSIX implementation include:
Description: This function is used to destroy the un-named semaphore
-indicated by sem. Only a semaphore that was created using
-sem_init() may be destroyed using sem_destroy(). The effect
-of calling sem_destroy() with a named semaphore is undefined. The
-effect of subsequent use of the semaphore sem is undefined until
-sem is re-initialized by another call to sem_init().
+indicated by sem. Only a semaphore that was created using
+sem_init() may be destroyed using sem_destroy(). The effect
+of calling sem_destroy() with a named semaphore is undefined. The
+effect of subsequent use of the semaphore sem is undefined until
+sem is re-initialized by another call to sem_init().
The effect of destroying a semaphore upon which other tasks are currently
blocked is undefined.
Input Parameters:
-- sem. Semaphore to be destroyed.
+
- sem. Semaphore to be destroyed.
@@ -1928,27 +1929,27 @@ been no calls to sem_unlink()).
Input Parameters:
-- name. Semaphore name
-
- oflag. Semaphore creation options. This may one of
+
- name. Semaphore name
+
- oflag. Semaphore creation options. This may one of
the following bit settings:
-- oflag = 0: Connect to the semaphore only if it already
+
- oflag = 0: Connect to the semaphore only if it already
exists.
-
- oflag = O_CREAT: Connect to the semaphore if it exists,
+
- oflag = O_CREAT: Connect to the semaphore if it exists,
otherwise create the semaphore.
-
- oflag = O_CREAT with O_EXCL (O_CREAT|O_EXCL): Create
+
- oflag = O_CREAT with O_EXCL (O_CREAT|O_EXCL): Create
a new semaphore unless one of this name already exists.
- ... Optional parameters.
NOTE: When the O_CREAT flag is specified, POSIX requires that a third
and fourth parameter be supplied:
-- mode. The mode parameter is of type mode_t.
+
- mode. The mode parameter is of type mode_t.
This parameter is required but not used in the present
implementation.
-
- value. The value parameter is type unsigned int. The semaphore
-is created with an initial value of value. Valid initial values for
-semaphores must be less than or equal to SEM_VALUE_MAX (defined in
+
- value. The value parameter is type unsigned int. The semaphore
+is created with an initial value of value. Valid initial values for
+semaphores must be less than or equal to SEM_VALUE_MAX (defined in
include/limits.h
).
@@ -1995,7 +1996,7 @@ that another calling task has already locked.
Input Parameters:
-- sem. Semaphore descriptor
+
- sem. Semaphore descriptor
@@ -2033,7 +2034,7 @@ sem_close().
Input Parameters:
-- name. Semaphore name
+
- name. Semaphore name
@@ -2078,7 +2079,7 @@ the lock or the call is interrupted by a signal.
Input Parameters:
-- sem. Semaphore descriptor.
+
- sem. Semaphore descriptor.
@@ -2087,14 +2088,14 @@ the lock or the call is interrupted by a signal.
- 0 (OK), or -1 (ERROR) is unsuccessful
-If sem_wait returns -1 (ERROR) then the cause of the failure
+If sem_wait returns -1 (ERROR) then the cause of the failure
will be indicated by the thread-specific errno
.
The following lists the possible values for errno
:
-- EINVAL: Indicates that the sem input parameter is
+
- EINVAL: Indicates that the sem input parameter is
not valid.
-
- EINTR: Indicates that the wait was interrupt by a signal
+
- EINTR: Indicates that the wait was interrupt by a signal
received by this task. In this case, the semaphore has not be acquired.
@@ -2103,7 +2104,76 @@ received by this task. In this case, the semaphore has not be acquired.
POSIX Compatibility: Comparable to the POSIX
interface of the same name.
-
+
+
+
+Function Prototype:
+
+ #include <semaphore.h>
+ #include <time.h>
+ int sem_wait ( sem_t *sem, const struct timespec *abstime);
+
+
+
+Description:
+ This function will lock the semaphore referenced by sem as in the sem_wait()
function.
+ However, if the semaphore cannot be locked without waiting for another process or thread to unlock the semaphore by performing a sem_post()
function, this wait will be terminated when the specified timeout expires.
+
+ The timeout will expire when the absolute time specified by abstime
passes, as measured by the clock on which timeouts are based (that is, when the value of that clock equals or exceeds abstime), or if the absolute time specified by abstime has already been passed at the time of the call.
+ This function attempts to lock the semaphore referenced by sem
.
+ If the semaphore as already locked by another task, the calling task will not return until it either successfully acquires the lock or the call is interrupted by a signal.
+
+Input Parameters:
+
+ -
+ sem. Semaphore descriptor.
+
+ -
+ abstime. The absolute time to wait until a timeout is declared.
+
+
+
+
+Returned Values:
+
+- 0 (OK), or -1 (ERROR) is unsuccessful
+
+
+If sem_wait returns -1 (ERROR) then the cause of the failure
+will be indicated by the thread-specific errno
.
+The following lists the possible values for errno
:
+
+
+ -
+
EINVAL
:
+ Indicates that the sem input parameter is not valid or the
+ thread would have blocked, and the abstime parameter specified
+ a nanoseconds field value less than zero or greater than or
+ equal to 1000 million.
+
+ -
+
ETIMEDOUT
:
+ The semaphore could not be locked before the specified timeout expired.
+
+ -
+
EDEADLK
:
+ A deadlock condition was detected.
+
+ -
+
EINTR
:
+ Indicates that the wait was interrupt by a signal received by this task.
+ In this case, the semaphore has not be acquired.
+
+
+
+ Assumptions/Limitations:
+
+
+ POSIX Compatibility: Derived from IEEE Std 1003.1d-1999.
+
+
+
Function Prototype:
@@ -2119,7 +2189,7 @@ returns without blocking.
Input Parameters:
-- sem. The semaphore descriptor
+
- sem. The semaphore descriptor
@@ -2127,14 +2197,14 @@ returns without blocking.
- 0 (OK) or -1 (ERROR) if unsuccessful
-If sem_wait returns -1 (ERROR) then the cause of the failure
+If sem_wait returns -1 (ERROR) then the cause of the failure
will be indicated by the thread-specific errno
.
The following lists the possible values for errno
:
-- EINVAL: Indicates that the sem input parameter is
+
- EINVAL: Indicates that the sem input parameter is
not valid.
-
- EAGAIN: Indicates that the semaphore was not acquired.
+
- EAGAIN: Indicates that the semaphore was not acquired.
@@ -2144,7 +2214,7 @@ not valid.
POSIX Compatibility: Comparable to the POSIX
interface of the same name.
-
+
Function Prototype:
@@ -2156,7 +2226,7 @@ interface of the same name.
Description: When a task has finished with a semaphore,
it will call sem_post(). This function unlocks the semaphore referenced
-by sem by performing the semaphore unlock operation.
+by sem by performing the semaphore unlock operation.
If the semaphore value resulting from this operation is positive, then
no tasks were blocked waiting for the semaphore to become unlocked;
@@ -2164,13 +2234,13 @@ The semaphore value is simply incremented.
If the value of the semaphore resulting from this operation is zero, then
on of the tasks blocked waiting for the semaphore will be allowed to
-return successfully from its call to sem_wait().
+return successfully from its call to sem_wait().
-NOTE: sem_post() may be called from an interrupt handler.
+NOTE: sem_post() may be called from an interrupt handler.
Input Parameters:
-- sem. Semaphore descriptor
+
- sem. Semaphore descriptor
@@ -2187,7 +2257,7 @@ task is the one that is performing the unlock.
POSIX Compatibility: Comparable to the POSIX
interface of the same name.
-
+
Function Prototype:
@@ -2210,8 +2280,8 @@ number of tasks waiting for the semaphore.
Input Parameters:
-- sem. Semaphore descriptor
-
- sval. Buffer by which the value is returned
+
- sem. Semaphore descriptor
+
- sval. Buffer by which the value is returned
@@ -2306,7 +2376,7 @@ has been started.
Input Parameters:
-- wdog. The watchdog ID to delete. This is actually a
+
- wdog. The watchdog ID to delete. This is actually a
pointer to a watchdog structure.
@@ -2360,11 +2430,11 @@ wd_start() on a given watchdog ID has any effect.
Input Parameters:
-- wdog. Watchdog ID
-
- delay. Delay count in clock ticks
-
- wdentry. Function to call on timeout
-
- argc. The number of uint32_t parameters to pass to wdentry.
-
- .... uint32_t size parameters to pass to wdentry
+
- wdog. Watchdog ID
+
- delay. Delay count in clock ticks
+
- wdentry. Function to call on timeout
+
- argc. The number of uint32_t parameters to pass to wdentry.
+
- .... uint32_t size parameters to pass to wdentry
@@ -2407,7 +2477,7 @@ level.
Input Parameters:
-- wdog. ID of the watchdog to cancel.
+
- wdog. ID of the watchdog to cancel.
@@ -2495,7 +2565,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the clock_settime() function will return zero (OK).
+ If successful, the clock_settime() function will return zero (OK).
Otherwise, an non-zero error number will be returned to indicate the error:
@@ -2523,7 +2593,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the clock_gettime() function will return zero (OK).
+ If successful, the clock_gettime() function will return zero (OK).
Otherwise, an non-zero error number will be returned to indicate the error:
@@ -2551,7 +2621,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the clock_getres() function will return zero (OK).
+ If successful, the clock_getres() function will return zero (OK).
Otherwise, an non-zero error number will be returned to indicate the error:
@@ -2579,7 +2649,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the mktime() function will return zero (OK).
+ If successful, the mktime() function will return zero (OK).
Otherwise, an non-zero error number will be returned to indicate the error:
@@ -2611,7 +2681,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the gmtime() function will return the pointer to a statically
+ If successful, the gmtime() function will return the pointer to a statically
defined instance of struct tim
.
Otherwise, a NULL will be returned to indicate the error:
@@ -2651,7 +2721,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the gmtime_r() function will return the pointer, result
,
+ If successful, the gmtime_r() function will return the pointer, result
,
provided by the caller.
Otherwise, a NULL will be returned to indicate the error:
@@ -2762,7 +2832,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the timer_delete() function will return zero (OK).
+ If successful, the timer_delete() function will return zero (OK).
Otherwise, the function will return a value of -1 (ERROR) and set
errno
to indicate the error:
@@ -2891,7 +2961,7 @@ VxWorks provides the following comparable interface:
Returned Values:
- If successful, the timer_gettime() function will return zero (OK).
+ If successful, the timer_gettime() function will return zero (OK).
Otherwise, an non-zero error number will be returned to indicate the error:
@@ -3054,7 +3124,7 @@ by set such that all signals are excluded.
Input Parameters:
-- set. Signal set to initialize.
+
- set. Signal set to initialize.
@@ -3084,7 +3154,7 @@ by set such that all signals are included.
Input Parameters:
-- set. Signal set to initialize
+
- set. Signal set to initialize
@@ -3114,8 +3184,8 @@ signo to the signal set specified by set.
Input Parameters:
-- set. Signal set to add signal to
-
- signo. Signal to add
+
- set. Signal set to add signal to
+
- signo. Signal to add
@@ -3145,8 +3215,8 @@ by signo from the signal set specified by set.
Input Parameters:
-- set. Signal set to delete the signal from
-
- signo. Signal to delete
+
- set. Signal set to delete the signal from
+
- signo. Signal to delete
@@ -3176,8 +3246,8 @@ by signo is a member of the set specified by set.
Input Parameters:
-- set. Signal set to test
-
- signo. Signal to test for
+
- set. Signal set to test
+
- signo. Signal to test for
@@ -3212,12 +3282,12 @@ signal.
The structure sigaction, used to describe an action to be taken, is defined
to include the following members:
-- sa_u.sa_handler. A pointer to a signal-catching function.
-
- sa_u.sa_sigaction. An alternative form for the signal catching
+
- sa_u.sa_handler. A pointer to a signal-catching function.
+
- sa_u.sa_sigaction. An alternative form for the signal catching
function.
-
- sa_mask. Additional set of signals to be blocked during
+
- sa_mask. Additional set of signals to be blocked during
execution of the signal-catching function.
-
- sa_flags: Special flags to affect behavior of a signal.
+
- sa_flags: Special flags to affect behavior of a signal.
If the argument act is not NULL, it points to a structure specifying the
@@ -3243,9 +3313,9 @@ sigaction().
Input Parameters:
-- sig. Signal of interest
-
- act. Location of new handler
-
- oact. Location to store old handler
+
- sig. Signal of interest
+
- act. Location of new handler
+
- oact. Location to store old handler
@@ -3290,19 +3360,19 @@ If sigprocmask() fails, the signal mask of the task is not changed.
Input Parameters:
-- how. How the signal mast will be changed:
+
- how. How the signal mast will be changed:
-- SIG_BLOCK. The resulting set is the union of the
-current set and the signal set pointed to by the set input parameter.
-
- SIG_UNBLOCK. The resulting set is the intersection
+
- SIG_BLOCK. The resulting set is the union of the
+current set and the signal set pointed to by the set input parameter.
+
- SIG_UNBLOCK. The resulting set is the intersection
of the current set and the complement of the signal set pointed
-to by the set input parameter.
-
- SIG_SETMASK. The resulting set is the signal set
-pointed to by the set input parameter.
+to by the set input parameter.
+
- SIG_SETMASK. The resulting set is the signal set
+pointed to by the set input parameter.
- - set. Location of the new signal mask
-
- oset. Location to store the old signal mask
+
- set. Location of the new signal mask
+
- oset. Location to store the old signal mask
@@ -3340,7 +3410,7 @@ is delivered more than once."
Input Parameters:
-- set. The location to return the pending signal set.
+
- set. The location to return the pending signal set.
@@ -3379,7 +3449,7 @@ resources (a very bad idea).
Input Parameters:
-- set. The value of the signal mask to use while
+
- set. The value of the signal mask to use while
suspended.
@@ -3418,8 +3488,8 @@ with a NULL timeout parameter. (see below).
Input Parameters:
-- set. The set of pending signals to wait for.
-
- info. The returned signal values
+
- set. The set of pending signals to wait for.
+
- info. The returned signal values
@@ -3461,19 +3531,19 @@ in the si_code member. The content of si_value is only meaningful
if the signal was generated by sigqueue(). The following values
for si_code are defined in signal.h:
- - SI_USER. Signal sent from kill, raise, or abort
-
- SI_QUEUE. Signal sent from sigqueue
-
- SI_TIMER. Signal is result of timer expiration
-
- SI_ASYNCIO. Signal is the result of asynchronous IO completion
-
- SI_MESGQ. Signal generated by arrival of a message on an empty message queue.
+
- SI_USER. Signal sent from kill, raise, or abort
+
- SI_QUEUE. Signal sent from sigqueue
+
- SI_TIMER. Signal is result of timer expiration
+
- SI_ASYNCIO. Signal is the result of asynchronous IO completion
+
- SI_MESGQ. Signal generated by arrival of a message on an empty message queue.
Input Parameters:
-- set. The set of pending signals to wait for.
-
- info. The returned signal values
-
- timeout. The amount of time to wait
+
- set. The set of pending signals to wait for.
+
- info. The returned signal values
+
- timeout. The amount of time to wait
@@ -3496,7 +3566,7 @@ from si_code in a non-standard way).
- POSIX states that "If no signal is pending at the time of the
call, the calling task shall be suspended until one or more signals
in set become pending or until it is interrupted by an unblocked,
-caught signal." The present implementation does not require
+caught signal." The present implementation does not require
that the unblocked signal be caught; the task will be resumed even if
the unblocked signal is ignored.
@@ -3524,9 +3594,9 @@ is delivered more than once."
Input Parameters:
-- tid. ID of the task to receive signal
-
- signo. Signal number
-
- value. Value to pass to task with signal
+
- tid. ID of the task to receive signal
+
- signo. Signal number
+
- value. Value to pass to task with signal
@@ -3584,12 +3654,12 @@ be sent.
Input Parameters:
-- pid. The id of the task to receive the signal.
+
- pid. The id of the task to receive the signal.
The POSIX
kill()
specification encodes process group
information as zero and negative pid values.
Only positive, non-zero values of pid are supported by this
implementation. ID of the task to receive signal
- - signo. The signal number to send.
+
- signo. The signal number to send.
If signo is zero, no signal is sent, but all error checking is performed.
@@ -3766,8 +3836,8 @@ for all of the individual attributes used by the implementation.
Returned Values:
-If successful, the pthread_attr_init() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_init() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3798,8 +3868,8 @@ An attributes object can be deleted when it is no longer needed.
Returned Values:
-If successful, the pthread_attr_destroy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_destroy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3829,8 +3899,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_setschedpolicy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_setschedpolicy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3860,8 +3930,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_getschedpolicy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_getschedpolicy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3892,8 +3962,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_getschedpolicy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_getschedpolicy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3924,8 +3994,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_getschedparam() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_getschedparam() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3956,8 +4026,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_setinheritsched() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_setinheritsched() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -3988,8 +4058,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_getinheritsched() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_getinheritsched() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4019,8 +4089,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_setstacksize() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_setstacksize() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4050,8 +4120,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_attr_getstacksize() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_attr_getstacksize() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4089,8 +4159,8 @@ specify details about the kind of thread being created.
Returned Values:
-If successful, the pthread_create() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_create() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4122,8 +4192,8 @@ return value and completion status will not be requested.
Returned Values:
-If successful, the pthread_detach() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_detach() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4154,8 +4224,8 @@ A thread may terminate it's own execution.
Returned Values:
-If successful, the pthread_exit() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_exit() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4195,17 +4265,17 @@ immediately (when enable), interrupting the thread with its processing.
Input Parameters:
-- thread.
+
- thread.
Identifies the thread to be canceled.
Returned Values:
-If successful, the pthread_cancel() function will return zero (OK).
+If successful, the pthread_cancel() function will return zero (OK).
Otherwise, an error number will be returned to indicate the error:
-- ESRCH.
+
- ESRCH.
No thread could be found corresponding to that specified by the given thread ID.
Assumptions/Limitations:
@@ -4244,19 +4314,19 @@ cancellation state is set to PTHREAD_CANCEL_ENABLE.
Input Parameters:
-- state
+
- state
New cancellation state. One of PTHREAD_CANCEL_ENABLE or PTHREAD_CANCEL_DISABLE.<.li>
-
- oldstate.
+
- oldstate.
Location to return the previous cancellation state.
Returned Values:
-If successful, the pthread_setcancelstate() function will return
-zero (OK). Otherwise, an error number will be returned to indicate the error:
+If successful, the pthread_setcancelstate() function will return
+zero (OK). Otherwise, an error number will be returned to indicate the error:
-- ESRCH.
+
- ESRCH.
No thread could be found corresponding to that specified by the given thread ID.
Assumptions/Limitations:
@@ -4283,8 +4353,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_setcancelstate() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_setcancelstate() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4316,8 +4386,8 @@ the return value of the thread.
Returned Values:
-If successful, the pthread_join() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_join() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4349,8 +4419,8 @@ made available.
Returned Values:
-If successful, the pthread_yield() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_yield() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4381,8 +4451,8 @@ A thread may obtain a copy of its own thread handle.
Returned Values:
-If successful, the pthread_self() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_self() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4514,8 +4584,8 @@ interface of the same name.
Returned Values:
- If successful, the pthread_setschedparam() function will return
- zero (OK). Otherwise, an error number will be
+ If successful, the pthread_setschedparam() function will return
+ zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4565,20 +4635,20 @@ interface of the same name.
This function creates a thread-specific data key visible
to all threads in the system. Although the same key value
may be used by different threads, the values bound to
-the key by pthread_setspecific() are maintained on a
+the key by pthread_setspecific() are maintained on a
per-thread basis and persist for the life of the calling
thread.
-Upon key creation, the value NULL will be associated with
+Upon key creation, the value NULL will be associated with
the new key in all active threads. Upon thread
-creation, the value NULL will be associated with all
+creation, the value NULL will be associated with all
defined keys in the new thread.
Input Parameters:
-- key is a pointer to the key to create.
-
- destructor is an optional destructor() function that may
+
- key is a pointer to the key to create.
+
- destructor is an optional destructor() function that may
be associated with each key that is invoked when a
thread exits. However, this argument is ignored in
the current implementation.
@@ -4586,17 +4656,17 @@ the current implementation.
Returned Values:
-If successful, the pthread_key_create() function will
-store the newly created key value at *key and return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_key_create() function will
+store the newly created key value at *key and return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
-- EAGAIN. The system lacked sufficient resources
+
- EAGAIN. The system lacked sufficient resources
to create another thread-specific data key, or the
system-imposed limit on the total number of keys
-per task {PTHREAD_KEYS_MAX} has been exceeded
-
- ENONMEM Insufficient memory exists to create the key.
+per task {PTHREAD_KEYS_MAX} has been exceeded
+
- ENONMEM Insufficient memory exists to create the key.
Assumptions/Limitations:
@@ -4617,34 +4687,34 @@ interface of the same name.
Description:
-The pthread_setspecific() function associates a thread-
+The pthread_setspecific() function associates a thread-
specific value with a key obtained via a previous call
-to pthread_key_create(). Different threads may bind
+to pthread_key_create(). Different threads may bind
different values to the same key. These values are
typically pointers to blocks of dynamically allocated
memory that have been reserved for use by the calling
thread.
-The effect of calling pthread_setspecific() with a key value
-not obtained from pthread_key_create() or after a key has been
-deleted with pthread_key_delete() is undefined.
+The effect of calling pthread_setspecific() with a key value
+not obtained from pthread_key_create() or after a key has been
+deleted with pthread_key_delete() is undefined.
Input Parameters:
-- key. The data key to set the binding for.
-
- value. The value to bind to the key.
+
- key. The data key to set the binding for.
+
- value. The value to bind to the key.
Returned Values:
-If successful, pthread_setspecific() will return zero (OK).
+If successful, pthread_setspecific() will return zero (OK).
Otherwise, an error number will be returned:
-- ENOMEM. Insufficient memory exists to associate the value
+
- ENOMEM. Insufficient memory exists to associate the value
with the key.
-
- EINVAL. The key value is invalid.
+
- EINVAL. The key value is invalid.
Assumptions/Limitations:
@@ -4667,26 +4737,26 @@ destructor function.
Description:
-The pthread_getspecific() function returns the value
+The pthread_getspecific() function returns the value
currently bound to the specified key on behalf of the
calling thread.
-The effect of calling pthread_getspecific() with a key value
-not obtained from pthread_key_create() or after a key has been
-deleted with pthread_key_delete() is undefined.
+The effect of calling pthread_getspecific() with a key value
+not obtained from pthread_key_create() or after a key has been
+deleted with pthread_key_delete() is undefined.
Input Parameters:
-- key. The data key to get the binding for.
+
- key. The data key to get the binding for.
Returned Values:
-The function pthread_getspecific() returns the thread-
+The function pthread_getspecific() returns the thread-
specific data associated with the given key. If no
thread specific data is associated with the key, then
-the value NULL is returned.
+the value NULL is returned.
Assumptions/Limitations:
@@ -4709,19 +4779,19 @@ destructor function.
Description:
This POSIX function should delete a thread-specific data
-key previously returned by pthread_key_create(). However,
+key previously returned by pthread_key_create(). However,
this function does nothing in the present implementation.
Input Parameters:
-- key. The key to delete
+
- key. The key to delete
Returned Values:
-- Always returns EINVAL.
+
- Always returns EINVAL.
Assumptions/Limitations:
@@ -4748,8 +4818,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutexattr_init() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_init() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4779,8 +4849,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutexattr_destroy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_destroy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4811,8 +4881,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutexattr_getpshared() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_getpshared() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4843,8 +4913,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutexattr_setpshared() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_setpshared() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4879,8 +4949,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutexattr_settype() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_settype() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4933,8 +5003,8 @@ returned to indicate the error:
Returned Values:
-If successful, the pthread_mutexattr_settype() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutexattr_settype() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4964,8 +5034,8 @@ returned to indicate the error:
Returned Values:
-If successful, the pthread_mutex_init() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutex_init() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -4995,8 +5065,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutex_destroy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutex_destroy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5061,7 +5131,7 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutex_lock() function will return zero (OK).
+If successful, the pthread_mutex_lock() function will return zero (OK).
Otherwise, an error number will be returned to indicate the error:
@@ -5101,7 +5171,7 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutex_trylock() function will return zero (OK).
+If successful, the pthread_mutex_trylock() function will return zero (OK).
Otherwise, an error number will be returned to indicate the error:
@@ -5146,8 +5216,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_mutex_unlock() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_mutex_unlock() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5178,8 +5248,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_condattr_init() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_condattr_init() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5209,8 +5279,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_condattr_destroy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_condattr_destroy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5240,8 +5310,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_cond_init() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_cond_init() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5271,8 +5341,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_cond_destroy() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_cond_destroy() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5302,8 +5372,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_cond_broadcast() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_cond_broadcast() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5333,8 +5403,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_cond_signal() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_cond_signal() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
@@ -5364,8 +5434,8 @@ interface of the same name.
Returned Values:
-If successful, the pthread_cond_wait() function will return
-zero (OK). Otherwise, an error number will be
+If successful, the pthread_cond_wait() function will return
+zero (OK). Otherwise, an error number will be
returned to indicate the error:
diff --git a/configs/stm3210e-eval/README.txt b/configs/stm3210e-eval/README.txt
index 8a2dcc7007..f01d3987dc 100755
--- a/configs/stm3210e-eval/README.txt
+++ b/configs/stm3210e-eval/README.txt
@@ -476,7 +476,7 @@ Where is one of the following:
Apps
----------- ----------------------- --------------------------------
Built-in None apps/examples/nx
- AppS
+ Apps apps/examples/nxhello
=========== ======================= ================================
* You will probably need to modify nsh/setenv.sh or nsh2/setenv.sh
diff --git a/include/semaphore.h b/include/semaphore.h
index aba024f8b7..7eea3a41bb 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -92,6 +92,9 @@ typedef struct sem_s sem_t;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
+/* Forward references needed by some prototypes */
+
+struct timespec; /* Defined in time.h */
/* Counting Semaphore Interfaces (based on POSIX APIs) */
@@ -101,6 +104,8 @@ EXTERN FAR sem_t *sem_open(FAR const char *name, int oflag, ...);
EXTERN int sem_close(FAR sem_t *sem);
EXTERN int sem_unlink(FAR const char *name);
EXTERN int sem_wait(FAR sem_t *sem);
+EXTERN int sem_timedwait(FAR sem_t *sem,
+ FAR const struct timespec *abstime);
EXTERN int sem_trywait(FAR sem_t *sem);
EXTERN int sem_post(FAR sem_t *sem);
EXTERN int sem_getvalue(FAR sem_t *sem, FAR int *sval);
diff --git a/sched/Makefile b/sched/Makefile
index 9ea7ca1bae..75d07676a4 100644
--- a/sched/Makefile
+++ b/sched/Makefile
@@ -120,7 +120,7 @@ SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \
sem_wait.c sem_trywait.c sem_post.c sem_findnamed.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
-SEM_SRCS += sem_waitirq.c
+SEM_SRCS += sem_waitirq.c sem_timedwait.c
endif
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
diff --git a/sched/sem_timedwait.c b/sched/sem_timedwait.c
new file mode 100644
index 0000000000..c02bc48db5
--- /dev/null
+++ b/sched/sem_timedwait.c
@@ -0,0 +1,287 @@
+/****************************************************************************
+ * sched/sem_timedwait.c
+ *
+ * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "os_internal.h"
+#include "clock_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: sem_timeout
+ *
+ * Description:
+ * This function is called if the timeout elapses before the message queue
+ * becomes non-empty.
+ *
+ * Parameters:
+ * argc - the number of arguments (should be 1)
+ * pid - the task ID of the task to wakeup
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void sem_timeout(int argc, uint32_t pid)
+{
+ FAR _TCB *wtcb;
+ irqstate_t flags;
+
+ /* Disable interrupts to avoid race conditions */
+
+ flags = irqsave();
+
+ /* Get the TCB associated with this pid. It is possible that
+ * task may no longer be active when this watchdog goes off.
+ */
+
+ wtcb = sched_gettcb((pid_t)pid);
+
+ /* It is also possible that an interrupt/context switch beat us to the
+ * punch and already changed the task's state.
+ */
+
+ if (wtcb && wtcb->task_state == TSTATE_WAIT_SEM)
+ {
+ /* Mark the errno value for the thread. */
+
+ wtcb->pterrno = ETIMEDOUT;
+
+ /* Restart the task. */
+
+ up_unblock_task(wtcb);
+ }
+
+ /* Interrupts may now be enabled. */
+
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: sem_timedwait
+ *
+ * Description:
+ * This function will lock the semaphore referenced by sem as in the
+ * sem_wait() function. However, if the semaphore cannot be locked without
+ * waiting for another process or thread to unlock the semaphore by
+ * performing a sem_post() function, this wait will be terminated when the
+ * specified timeout expires.
+ *
+ * The timeout will expire when the absolute time specified by abstime
+ * passes, as measured by the clock on which timeouts are based (that is,
+ * when the value of that clock equals or exceeds abstime), or if the
+ * absolute time specified by abstime has already been passed at the
+ * time of the call.
+ *
+ * Parameters:
+ * sem - Semaphore object
+ * abstime - The absolute time to wait until a timeout is declared.
+ *
+ * Return Value:
+ * One success, the length of the selected message in bytes.is
+ * returned. On failure, -1 (ERROR) is returned and the errno
+ * is set appropriately:
+ *
+ * EINVAL The sem argument does not refer to a valid semaphore. Or the
+ * thread would have blocked, and the abstime parameter specified
+ * a nanoseconds field value less than zero or greater than or
+ * equal to 1000 million.
+ * ETIMEDOUT The semaphore could not be locked before the specified timeout
+ * expired.
+ * EDEADLK A deadlock condition was detected.
+ * EINTR A signal interrupted this function.
+ *
+ ****************************************************************************/
+
+int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
+{
+ WDOG_ID wdog;
+ irqstate_t flags;
+ int ticks;
+ int err;
+ int ret = ERROR;
+
+ DEBUGASSERT(up_interrupt_context() == false);
+
+ /* Verify the input parameters and, in case of an error, set
+ * errno appropriately.
+ */
+
+#ifdef CONFIG_DEBUG
+ if (!abstime || !sem)
+ {
+ err = EINVAL;
+ goto errout;
+ }
+#endif
+
+ /* Create a watchdog. We will not actually need this watchdog
+ * unless the the semaphore is unavailable, but we will reserve it up
+ * front before we enter the following critical section.
+ */
+
+ wdog = wd_create();
+ if (!wdog)
+ {
+ err = ENOMEM;
+ goto errout;
+ }
+
+ /* We will disable interrupts until we have completed the semaphore
+ * wait. We need to do this (as opposed to just disabling pre-emption)
+ * because there could be interrupt handlers that are asynchronoulsy
+ * posting semaphores and to prevent race conditions with watchdog
+ * timeout. This is not too bad because interrupts will be re-
+ * enabled while we are blocked waiting for the semaphore.
+ */
+
+ flags = irqsave();
+
+ /* Try to take the semaphore without waiting. */
+
+ ret = sem_trywait(sem);
+ if (ret == 0)
+ {
+ /* We got it! */
+
+ irqrestore(flags);
+ wd_delete(wdog);
+ return OK;
+ }
+
+ /* We will have to wait for the semphore. Make sure that we were provided
+ * with a valid timeout.
+ */
+
+ if (abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000)
+ {
+ err = EINVAL;
+ goto errout_disabled;
+ }
+
+ /* Convert the timespec to clock ticks. We must have interrupts
+ * disabled here so that this time stays valid until the wait begins.
+ */
+
+ err = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
+
+ /* If the time has already expired return immediately. */
+
+ if (err == OK && ticks <= 0)
+ {
+ err = ETIMEDOUT;
+ goto errout_disabled;
+ }
+
+ /* Handle any time-related errors */
+
+ if (err != OK)
+ {
+ goto errout_disabled;
+ }
+
+ /* Start the watchdog */
+
+ err = OK;
+ wd_start(wdog, ticks, (wdentry_t)sem_timeout, 1, getpid());
+
+ /* Now perform the blocking wait */
+
+ ret = sem_wait(sem);
+
+ /* Stop the watchdog timer */
+
+ wd_cancel(wdog);
+
+ /* We can now restore interrupts and delete the watchdog */
+
+ irqrestore(flags);
+ wd_delete(wdog);
+
+ /* We are either returning success or an error detected by sem_wait()
+ * or the timeout detected by sem_timeout().
+ */
+
+ return ret;
+
+/* Error exits */
+
+errout_disabled:
+ irqrestore(flags);
+ wd_delete(wdog);
+errout:
+ set_errno(err);
+ return ERROR;
+}