summaryrefslogtreecommitdiff
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog37
-rw-r--r--cpukit/itron/inline/rtems/itron/semaphore.inl2
-rw-r--r--cpukit/itron/src/twai_sem.c12
-rw-r--r--cpukit/posix/Makefile.am9
-rw-r--r--cpukit/posix/include/mqueue.h36
-rw-r--r--cpukit/posix/include/rtems/posix/mqueue.h2
-rw-r--r--cpukit/posix/include/rtems/posix/semaphore.h6
-rw-r--r--cpukit/posix/include/rtems/posix/time.h37
-rw-r--r--cpukit/posix/src/condtimedwait.c42
-rw-r--r--cpukit/posix/src/mqueuereceive.c1
-rw-r--r--cpukit/posix/src/mqueuerecvsupp.c18
-rw-r--r--cpukit/posix/src/mqueuesend.c1
-rw-r--r--cpukit/posix/src/mqueuesendsupp.c15
-rw-r--r--cpukit/posix/src/mqueuetimedreceive.c28
-rw-r--r--cpukit/posix/src/mqueuetimedsend.c28
-rw-r--r--cpukit/posix/src/mutexfromcorestatus.c2
-rw-r--r--cpukit/posix/src/mutextimedlock.c54
-rw-r--r--cpukit/posix/src/posixtimespecabsolutetimeout.c126
-rw-r--r--cpukit/posix/src/semaphorewaitsupp.c9
-rw-r--r--cpukit/posix/src/semtimedwait.c69
-rw-r--r--cpukit/posix/src/semtrywait.c2
-rw-r--r--cpukit/posix/src/semwait.c6
-rw-r--r--cpukit/rtems/src/semobtain.c3
-rw-r--r--cpukit/rtems/src/semtranslatereturncode.c3
-rw-r--r--cpukit/score/include/rtems/score/coresem.h38
-rw-r--r--cpukit/score/src/coremsgseize.c4
-rw-r--r--cpukit/score/src/coresemseize.c39
27 files changed, 465 insertions, 164 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 29814c16b8..e32283e8cc 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,40 @@
+2008-07-24 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ PR 1291/cpukit
+ * posix/src/posixtimespecabsolutetimeout.c: New file.
+ * itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c,
+ posix/Makefile.am, posix/include/mqueue.h,
+ posix/include/rtems/posix/mqueue.h,
+ posix/include/rtems/posix/semaphore.h,
+ posix/include/rtems/posix/time.h, posix/src/condtimedwait.c,
+ posix/src/mqueuereceive.c, posix/src/mqueuerecvsupp.c,
+ posix/src/mqueuesend.c, posix/src/mqueuesendsupp.c,
+ posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c,
+ posix/src/mutexfromcorestatus.c, posix/src/mutextimedlock.c,
+ posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c,
+ posix/src/semtrywait.c, posix/src/semwait.c, rtems/src/semobtain.c,
+ rtems/src/semtranslatereturncode.c,
+ score/include/rtems/score/coresem.h, score/src/coremsgseize.c,
+ score/src/coresemseize.c:
+ This patch addresses issues on implementation of the timeout on the
+ following POSIX services. Some of these services incorrectly took a
+ timeout as a relative time. Others would compute a 0 delta to timeout
+ if the absolute time and the current time were equal and thus
+ incorrectly block the caller forever. The root of the confusion is
+ that POSIX specifies that if the timeout is incorrect (e.g. in the
+ past, is now, or is numerically invalid), that it does not matter if
+ the call would succeed without blocking. This is in contrast to RTEMS
+ programming style where all errors are checked before any critical
+ sections are entered. This fix implemented a more uniform way of
+ handling POSIX absolute time timeouts.
+ + pthread_cond_timedwait - could block forever
+ + mq_timedreceive - used relative not absolute time
+ + mq_timedsend - used relative not absolute time
+ + pthread_mutex_timedlock - used relative not absolute time
+ + pthread_rwlock_timedrdlock- used relative not absolute time
+ + pthread_rwlock_timedwrlock- used relative not absolute time
+ + sem_timedwait - could block forever
+
2008-04-25 Joel Sherrill <joel.sherrill@OARcorp.com>
* score/include/rtems/system.h: Fix typo in comment.
diff --git a/cpukit/itron/inline/rtems/itron/semaphore.inl b/cpukit/itron/inline/rtems/itron/semaphore.inl
index 1822fb8884..c57347f319 100644
--- a/cpukit/itron/inline/rtems/itron/semaphore.inl
+++ b/cpukit/itron/inline/rtems/itron/semaphore.inl
@@ -172,8 +172,6 @@ RTEMS_INLINE_ROUTINE ER _ITRON_Semaphore_Translate_core_semaphore_return_code (
return E_TMOUT;
case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
return E_QOVR;
- case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
- return E_PAR;
case THREAD_STATUS_PROXY_BLOCKING:
return THREAD_STATUS_PROXY_BLOCKING;
}
diff --git a/cpukit/itron/src/twai_sem.c b/cpukit/itron/src/twai_sem.c
index 90b3121051..0f7510a949 100644
--- a/cpukit/itron/src/twai_sem.c
+++ b/cpukit/itron/src/twai_sem.c
@@ -30,16 +30,16 @@ ER twai_sem(
TMO tmout
)
{
- ITRON_Semaphore_Control *the_semaphore;
- Objects_Locations location;
- Watchdog_Interval interval;
- Core_semaphore_Blocking_option blocking;
+ ITRON_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+ Watchdog_Interval interval;
+ boolean blocking;
interval = 0;
if ( tmout == TMO_POL ) {
- blocking = CORE_SEMAPHORE_NO_WAIT;
+ blocking = FALSE;
} else {
- blocking = CORE_SEMAPHORE_BLOCK_FOREVER;
+ blocking = TRUE;
if ( tmout != TMO_FEVR )
interval = TOD_MILLISECONDS_TO_TICKS(tmout);
diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 65e3dae375..dce2dcb1b3 100644
--- a/cpukit/posix/Makefile.am
+++ b/cpukit/posix/Makefile.am
@@ -132,10 +132,11 @@ libposix_a_SOURCES += src/semaphore.c src/semaphorecreatesupp.c \
## TIME_C_FILES
libposix_a_SOURCES += src/adjtime.c src/time.c src/posixtimespecsubtract.c \
- src/posixtimespectointerval.c src/posixintervaltotimespec.c \
- src/clockgetcpuclockid.c src/clockgetenableattr.c src/clockgetres.c \
- src/clockgettime.c src/clocksetenableattr.c src/clocksettime.c \
- src/nanosleep.c src/sleep.c src/usleep.c
+ src/posixtimespecabsolutetimeout.c src/posixtimespectointerval.c \
+ src/posixintervaltotimespec.c src/clockgetcpuclockid.c \
+ src/clockgetenableattr.c src/clockgetres.c src/clockgettime.c \
+ src/clocksetenableattr.c src/clocksettime.c src/nanosleep.c src/sleep.c \
+ src/usleep.c
# the timer manager needs to be split further but only after its
# dependence on the Classic API Timer Manager is removed.
diff --git a/cpukit/posix/include/mqueue.h b/cpukit/posix/include/mqueue.h
index 0c2a513345..0e1ad8370a 100644
--- a/cpukit/posix/include/mqueue.h
+++ b/cpukit/posix/include/mqueue.h
@@ -26,47 +26,53 @@ extern "C" {
* 15.1.1 Data Structures, P1003.1b-1993, p. 271
*/
+/**
+ * Message queue id type
+ */
typedef Objects_Id mqd_t;
+/**
+ * This is the message queue attributes structure.
+ */
struct mq_attr {
- long mq_flags; /* Message queue flags */
- long mq_maxmsg; /* Maximum number of messages */
- long mq_msgsize; /* Maximum message size */
- long mq_curmsgs; /* Number of messages currently queued */
+ /** This is the message queue flags */
+ long mq_flags;
+ /** This is the maximum number of messages */
+ long mq_maxmsg;
+ /** This is the maximum message size */
+ long mq_msgsize;
+ /** This is the mumber of messages currently queued */
+ long mq_curmsgs;
};
-/*
+/**
* 15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
*/
-
mqd_t mq_open(
const char *name,
int oflag,
...
);
-/*
+/**
* 15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
*/
-
int mq_close(
mqd_t mqdes
);
-/*
+/**
* 15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
*/
-
int mq_unlink(
const char *name
);
-/*
+/**
* 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
*
- * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
+ * @note P1003.4b/D8, p. 45 adds mq_timedsend().
*/
-
int mq_send(
mqd_t mqdes,
const char *msg_ptr,
@@ -83,7 +89,7 @@ int mq_timedsend(
const char *msg_ptr,
size_t msg_len,
unsigned int msg_prio,
- const struct timespec *timeout
+ const struct timespec *abstime
);
#endif /* _POSIX_TIMEOUTS */
@@ -108,7 +114,7 @@ ssize_t mq_timedreceive(
char *msg_ptr,
size_t msg_len,
unsigned int *msg_prio,
- const struct timespec *timeout
+ const struct timespec *abstime
);
#endif /* _POSIX_TIMEOUTS */
diff --git a/cpukit/posix/include/rtems/posix/mqueue.h b/cpukit/posix/include/rtems/posix/mqueue.h
index 7b831ac141..cddcfdba72 100644
--- a/cpukit/posix/include/rtems/posix/mqueue.h
+++ b/cpukit/posix/include/rtems/posix/mqueue.h
@@ -112,6 +112,7 @@ ssize_t _POSIX_Message_queue_Receive_support(
char *msg_ptr,
size_t msg_len,
unsigned int *msg_prio,
+ boolean wait,
Watchdog_Interval timeout
);
@@ -128,6 +129,7 @@ int _POSIX_Message_queue_Send_support(
const char *msg_ptr,
size_t msg_len,
uint32_t msg_prio,
+ boolean wait,
Watchdog_Interval timeout
);
diff --git a/cpukit/posix/include/rtems/posix/semaphore.h b/cpukit/posix/include/rtems/posix/semaphore.h
index 26e0a6b804..78b8e022d8 100644
--- a/cpukit/posix/include/rtems/posix/semaphore.h
+++ b/cpukit/posix/include/rtems/posix/semaphore.h
@@ -153,9 +153,9 @@ void _POSIX_Semaphore_Delete(
*/
int _POSIX_Semaphore_Wait_support(
- sem_t *sem,
- Core_semaphore_Blocking_option blocking,
- Watchdog_Interval timeout
+ sem_t *sem,
+ boolean blocking,
+ Watchdog_Interval timeout
);
/*
diff --git a/cpukit/posix/include/rtems/posix/time.h b/cpukit/posix/include/rtems/posix/time.h
index 13418cf473..eb3376cc60 100644
--- a/cpukit/posix/include/rtems/posix/time.h
+++ b/cpukit/posix/include/rtems/posix/time.h
@@ -13,6 +13,23 @@
#include <rtems/score/tod.h>
+/* Absolute Timeout Conversion Results
+ *
+ * This enumeration defines the possible results of converting
+ * an absolute time used for timeouts to POSIX blocking calls to
+ * a number of ticks.
+ */
+typedef enum {
+ /* The timeout is invalid. */
+ POSIX_ABSOLUTE_TIMEOUT_INVALID,
+ /* The timeout represents a time that is in the past. */
+ POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,
+ /* The timeout represents a time that is equal to the current time. */
+ POSIX_ABSOLUTE_TIMEOUT_IS_NOW,
+ /* The timeout represents a time that is in the future. */
+ POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
+} POSIX_Absolute_timeout_conversion_results_t;
+
/*
* Seconds from January 1, 1970 to January 1, 1988. Used to account for
* differences between POSIX API and RTEMS core.
@@ -51,4 +68,24 @@ void _POSIX_Interval_to_timespec(
struct timespec *time
);
+/*
+ * Convert Absolute Timeout to Ticks
+ *
+ * This method takes an absolute time being used as a timeout
+ * to a blocking directive, validates it and returns the number
+ * of corresponding clock ticks for use by the SuperCore.
+ *
+ * abstime - is the timeout
+ * ticks_out - will contain the number of ticks
+ *
+ * This method returns the number of ticks in @a ticks_out
+ * and a status value indicating whether the absolute time
+ * is valid, in the past, equal to the current time or in
+ * the future as it should be.
+ */
+POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
+ const struct timespec *abstime,
+ Watchdog_Interval *ticks_out
+);
+
#endif
diff --git a/cpukit/posix/src/condtimedwait.c b/cpukit/posix/src/condtimedwait.c
index 32ce1d4a05..204dae858c 100644
--- a/cpukit/posix/src/condtimedwait.c
+++ b/cpukit/posix/src/condtimedwait.c
@@ -28,34 +28,34 @@ int pthread_cond_timedwait(
const struct timespec *abstime
)
{
- Watchdog_Interval timeout;
- struct timespec current_time;
- struct timespec difference;
- boolean already_timedout = FALSE;
-
- if ( !abstime )
- return EINVAL;
+ Watchdog_Interval ticks;
+ boolean already_timedout;
/*
- * The abstime is a walltime. We turn it into an interval.
+ * POSIX requires that blocking calls with timeouts that take
+ * an absolute timeout must ignore issues with the absolute
+ * time provided if the operation would otherwise succeed.
+ * So we check the abstime provided, and hold on to whether it
+ * is valid or not. If it isn't correct and in the future,
+ * then we do a polling operation and convert the UNSATISFIED
+ * status into the appropriate error.
*/
-
- (void) clock_gettime( CLOCK_REALTIME, &current_time );
-
- /* XXX probably some error checking should go here */
-
- _POSIX_Timespec_subtract( &current_time, abstime, &difference );
-
- if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
- ( difference.tv_nsec < 0 ) ) )
- already_timedout = TRUE;
-
- timeout = _POSIX_Timespec_to_interval( &difference );
+ switch ( _POSIX_Absolute_timeout_to_ticks(abstime, &ticks) ) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ return EINVAL;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ already_timedout = TRUE;
+ break;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ already_timedout = FALSE;
+ break;
+ }
return _POSIX_Condition_variables_Wait_support(
cond,
mutex,
- timeout,
+ ticks,
already_timedout
);
}
diff --git a/cpukit/posix/src/mqueuereceive.c b/cpukit/posix/src/mqueuereceive.c
index e87d5fa8e9..1ba213e58a 100644
--- a/cpukit/posix/src/mqueuereceive.c
+++ b/cpukit/posix/src/mqueuereceive.c
@@ -51,6 +51,7 @@ ssize_t mq_receive(
msg_ptr,
msg_len,
msg_prio,
+ TRUE,
THREAD_QUEUE_WAIT_FOREVER
);
}
diff --git a/cpukit/posix/src/mqueuerecvsupp.c b/cpukit/posix/src/mqueuerecvsupp.c
index d97db51642..9badfb65d4 100644
--- a/cpukit/posix/src/mqueuerecvsupp.c
+++ b/cpukit/posix/src/mqueuerecvsupp.c
@@ -32,8 +32,7 @@
#include <rtems/posix/mqueue.h>
#include <rtems/posix/time.h>
-/*PAGE
- *
+/*
* _POSIX_Message_queue_Receive_support
*
* NOTE: XXX Document how size, priority, length, and the buffer go
@@ -45,6 +44,7 @@ ssize_t _POSIX_Message_queue_Receive_support(
char *msg_ptr,
size_t msg_len,
unsigned int *msg_prio,
+ boolean wait,
Watchdog_Interval timeout
)
{
@@ -52,6 +52,7 @@ ssize_t _POSIX_Message_queue_Receive_support(
POSIX_Message_queue_Control_fd *the_mq_fd;
Objects_Locations location;
size_t length_out;
+ boolean do_wait;
the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
switch ( location ) {
@@ -81,12 +82,23 @@ ssize_t _POSIX_Message_queue_Receive_support(
length_out = -1;
+ /*
+ * A timed receive with a bad time will do a poll regardless.
+ */
+ if ( wait )
+ do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE;
+ else
+ do_wait = wait;
+
+ /*
+ * Now perform the actual message receive
+ */
_CORE_message_queue_Seize(
&the_mq->Message_queue,
mqdes,
msg_ptr,
&length_out,
- (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
+ do_wait,
timeout
);
diff --git a/cpukit/posix/src/mqueuesend.c b/cpukit/posix/src/mqueuesend.c
index 484fe72183..3bb11c3ab4 100644
--- a/cpukit/posix/src/mqueuesend.c
+++ b/cpukit/posix/src/mqueuesend.c
@@ -51,6 +51,7 @@ int mq_send(
msg_ptr,
msg_len,
msg_prio,
+ TRUE,
THREAD_QUEUE_WAIT_FOREVER
);
}
diff --git a/cpukit/posix/src/mqueuesendsupp.c b/cpukit/posix/src/mqueuesendsupp.c
index 60f48fcdba..006c1ba4a2 100644
--- a/cpukit/posix/src/mqueuesendsupp.c
+++ b/cpukit/posix/src/mqueuesendsupp.c
@@ -43,6 +43,7 @@ int _POSIX_Message_queue_Send_support(
const char *msg_ptr,
size_t msg_len,
uint32_t msg_prio,
+ boolean wait,
Watchdog_Interval timeout
)
{
@@ -50,6 +51,7 @@ int _POSIX_Message_queue_Send_support(
POSIX_Message_queue_Control_fd *the_mq_fd;
Objects_Locations location;
CORE_message_queue_Status msg_status;
+ boolean do_wait;
/*
* Validate the priority.
@@ -77,6 +79,17 @@ int _POSIX_Message_queue_Send_support(
the_mq = the_mq_fd->Queue;
+ /*
+ * A timed receive with a bad time will do a poll regardless.
+ */
+ if ( wait )
+ do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE;
+ else
+ do_wait = wait;
+
+ /*
+ * Now perform the actual message receive
+ */
msg_status = _CORE_message_queue_Submit(
&the_mq->Message_queue,
(void *) msg_ptr,
@@ -88,7 +101,7 @@ int _POSIX_Message_queue_Send_support(
NULL,
#endif
_POSIX_Message_queue_Priority_to_core( msg_prio ),
- (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
+ do_wait,
timeout /* no timeout */
);
diff --git a/cpukit/posix/src/mqueuetimedreceive.c b/cpukit/posix/src/mqueuetimedreceive.c
index 2ad5f4c6d6..436fddebcf 100644
--- a/cpukit/posix/src/mqueuetimedreceive.c
+++ b/cpukit/posix/src/mqueuetimedreceive.c
@@ -44,14 +44,38 @@ ssize_t mq_timedreceive(
char *msg_ptr,
size_t msg_len,
unsigned int *msg_prio,
- const struct timespec *timeout
+ const struct timespec *abstime
)
{
+ Watchdog_Interval ticks;
+ boolean do_wait;
+
+ /*
+ * POSIX requires that blocking calls with timeouts that take
+ * an absolute timeout must ignore issues with the absolute
+ * time provided if the operation would otherwise succeed.
+ * So we check the abstime provided, and hold on to whether it
+ * is valid or not. If it isn't correct and in the future,
+ * then we do a polling operation and convert the UNSATISFIED
+ * status into the appropriate error.
+ */
+ switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ do_wait = FALSE;
+ break;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ do_wait = TRUE;
+ break;
+ }
+
return _POSIX_Message_queue_Receive_support(
mqdes,
msg_ptr,
msg_len,
msg_prio,
- _POSIX_Timespec_to_interval( timeout )
+ do_wait,
+ ticks
);
}
diff --git a/cpukit/posix/src/mqueuetimedsend.c b/cpukit/posix/src/mqueuetimedsend.c
index 89569368be..87458b7f02 100644
--- a/cpukit/posix/src/mqueuetimedsend.c
+++ b/cpukit/posix/src/mqueuetimedsend.c
@@ -44,14 +44,38 @@ int mq_timedsend(
const char *msg_ptr,
size_t msg_len,
unsigned int msg_prio,
- const struct timespec *timeout
+ const struct timespec *abstime
)
{
+ Watchdog_Interval ticks;
+ boolean do_wait;
+
+ /*
+ * POSIX requires that blocking calls with timeouts that take
+ * an absolute timeout must ignore issues with the absolute
+ * time provided if the operation would otherwise succeed.
+ * So we check the abstime provided, and hold on to whether it
+ * is valid or not. If it isn't correct and in the future,
+ * then we do a polling operation and convert the UNSATISFIED
+ * status into the appropriate error.
+ */
+ switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ do_wait = FALSE;
+ break;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ do_wait = TRUE;
+ break;
+ }
+
return _POSIX_Message_queue_Send_support(
mqdes,
msg_ptr,
msg_len,
msg_prio,
- _POSIX_Timespec_to_interval( timeout )
+ do_wait,
+ ticks
);
}
diff --git a/cpukit/posix/src/mutexfromcorestatus.c b/cpukit/posix/src/mutexfromcorestatus.c
index 3c6f617861..dddc3cea4b 100644
--- a/cpukit/posix/src/mutexfromcorestatus.c
+++ b/cpukit/posix/src/mutexfromcorestatus.c
@@ -41,7 +41,7 @@ int _POSIX_Mutex_From_core_mutex_status(
case CORE_MUTEX_WAS_DELETED:
return EINVAL;
case CORE_MUTEX_TIMEOUT:
- return EAGAIN;
+ return ETIMEDOUT;
case CORE_MUTEX_STATUS_CEILING_VIOLATED:
return EINVAL;
default:
diff --git a/cpukit/posix/src/mutextimedlock.c b/cpukit/posix/src/mutextimedlock.c
index e86c3040dd..f1963c2efe 100644
--- a/cpukit/posix/src/mutextimedlock.c
+++ b/cpukit/posix/src/mutextimedlock.c
@@ -28,12 +28,58 @@
int pthread_mutex_timedlock(
pthread_mutex_t *mutex,
- const struct timespec *timeout
+ const struct timespec *abstime
)
{
- return _POSIX_Mutex_Lock_support(
+ Watchdog_Interval ticks;
+ boolean do_wait;
+ POSIX_Absolute_timeout_conversion_results_t status;
+ int lock_status;
+
+ /*
+ * POSIX requires that blocking calls with timeouts that take
+ * an absolute timeout must ignore issues with the absolute
+ * time provided if the operation would otherwise succeed.
+ * So we check the abstime provided, and hold on to whether it
+ * is valid or not. If it isn't correct and in the future,
+ * then we do a polling operation and convert the UNSATISFIED
+ * status into the appropriate error.
+ */
+ status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
+ switch ( status ) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ do_wait = FALSE;
+ break;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ do_wait = TRUE;
+ break;
+ }
+
+ lock_status = _POSIX_Mutex_Lock_support(
mutex,
- TRUE,
- _POSIX_Timespec_to_interval( timeout )
+ do_wait,
+ ticks
);
+
+ /*
+ * This service only gives us the option to block. We used a polling
+ * attempt to lock if the abstime was not in the future. If we did
+ * not obtain the mutex, then not look at the status immediately,
+ * make sure the right reason is returned.
+ */
+ if ( !do_wait && (lock_status == EBUSY) ) {
+ switch (lock_status) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ return EINVAL;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ return ETIMEDOUT;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ break;
+ }
+ }
+
+ return lock_status;
}
diff --git a/cpukit/posix/src/posixtimespecabsolutetimeout.c b/cpukit/posix/src/posixtimespecabsolutetimeout.c
new file mode 100644
index 0000000000..4c6a84e1e9
--- /dev/null
+++ b/cpukit/posix/src/posixtimespecabsolutetimeout.c
@@ -0,0 +1,126 @@
+/*
+ * Convert abstime timeout to ticks
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+static boolean _Timespec_Is_valid(
+ const struct timespec *time
+)
+{
+ if ( !time )
+ return FALSE;
+
+ if ( time->tv_sec < 0 )
+ return FALSE;
+
+ if ( time->tv_nsec < 0 )
+ return FALSE;
+
+ if ( time->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
+ return FALSE;
+
+ return TRUE;
+}
+
+static boolean _Timespec_Less_than(
+ const struct timespec *lhs,
+ const struct timespec *rhs
+)
+{
+ if ( lhs->tv_sec < rhs->tv_sec )
+ return TRUE;
+
+ if ( lhs->tv_sec > rhs->tv_sec )
+ return FALSE;
+
+ /* ASSERT: lhs->tv_sec == rhs->tv_sec */
+ if ( lhs->tv_nsec < rhs->tv_nsec )
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*
+ * The abstime is a walltime. We turn it into an interval.
+ */
+POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
+ const struct timespec *abstime,
+ Watchdog_Interval *ticks_out
+)
+{
+ struct timespec current_time;
+ struct timespec difference;
+
+
+ /*
+ * Make sure there is always a value returned.
+ */
+ *ticks_out = 0;
+
+ /*
+ * Is the absolute time even valid?
+ */
+ if ( !_Timespec_Is_valid(abstime) )
+ return POSIX_ABSOLUTE_TIMEOUT_INVALID;
+
+ /*
+ * Is the absolute time in the past?
+ */
+ clock_gettime( CLOCK_REALTIME, &current_time );
+
+ if ( _Timespec_Less_than( abstime, &current_time ) )
+ return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST;
+
+ /*
+ * How long until the requested absolute time?
+ */
+ _POSIX_Timespec_subtract( &current_time, abstime, &difference );
+
+ /*
+ * Internally the SuperCore uses ticks, so convert to them.
+ */
+ *ticks_out = _POSIX_Timespec_to_interval( &difference );
+
+ /*
+ * If the difference was 0, then the future is now. It is so bright
+ * we better wear shades.
+ */
+ if ( !*ticks_out )
+ return POSIX_ABSOLUTE_TIMEOUT_IS_NOW;
+
+ /*
+ * This is the case we were expecting and it took this long to
+ * get here.
+ */
+ return POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
+}
+
diff --git a/cpukit/posix/src/semaphorewaitsupp.c b/cpukit/posix/src/semaphorewaitsupp.c
index 1c5f815b25..f460331612 100644
--- a/cpukit/posix/src/semaphorewaitsupp.c
+++ b/cpukit/posix/src/semaphorewaitsupp.c
@@ -26,9 +26,9 @@
*/
int _POSIX_Semaphore_Wait_support(
- sem_t *sem,
- Core_semaphore_Blocking_option blocking,
- Watchdog_Interval timeout
+ sem_t *sem,
+ boolean blocking,
+ Watchdog_Interval timeout
)
{
POSIX_Semaphore_Control *the_semaphore;
@@ -65,9 +65,6 @@ int _POSIX_Semaphore_Wait_support(
* count to the largest value the count can hold.
*/
break;
- case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
- rtems_set_errno_and_return_minus_one( EINVAL );
- break;
}
}
return 0;
diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c
index 662845ecd9..6a78c742d0 100644
--- a/cpukit/posix/src/semtimedwait.c
+++ b/cpukit/posix/src/semtimedwait.c
@@ -32,40 +32,51 @@ int sem_timedwait(
const struct timespec *abstime
)
{
+ Watchdog_Interval ticks;
+ boolean do_wait = TRUE;
+ POSIX_Absolute_timeout_conversion_results_t status;
+ int lock_status;
+
/*
- * The abstime is a walltime. We turn it into an interval.
+ * POSIX requires that blocking calls with timeouts that take
+ * an absolute timeout must ignore issues with the absolute
+ * time provided if the operation would otherwise succeed.
+ * So we check the abstime provided, and hold on to whether it
+ * is valid or not. If it isn't correct and in the future,
+ * then we do a polling operation and convert the UNSATISFIED
+ * status into the appropriate error.
*/
- Watchdog_Interval ticks = 0;
- struct timespec current_time;
- struct timespec difference;
- Core_semaphore_Blocking_option blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
+ status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
+ switch ( status ) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ do_wait = FALSE;
+ break;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ do_wait = TRUE;
+ break;
+ }
+
+ lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks );
/*
- * Error check the absolute time to timeout
+ * This service only gives us the option to block. We used a polling
+ * attempt to obtain if the abstime was not in the future. If we did
+ * not obtain the semaphore, then not look at the status immediately,
+ * make sure the right reason is returned.
*/
-#if 0
- if ( /* abstime->tv_sec < 0 || */ abstime->tv_nsec ) /* tv_sec is unsigned */
- blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
- else
-#endif
- if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
- blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
- } else {
- clock_gettime( CLOCK_REALTIME, &current_time );
- /*
- * Make sure the abstime is in the future
- */
- if ( abstime->tv_sec < current_time.tv_sec )
- blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
- else if ( (abstime->tv_sec == current_time.tv_sec) &&
- (abstime->tv_nsec <= current_time.tv_nsec) )
- blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
- else {
- _POSIX_Timespec_subtract( &current_time, abstime, &difference );
- ticks = _POSIX_Timespec_to_interval( &difference );
- blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
+ if ( !do_wait && (lock_status == EBUSY) ) {
+ switch (lock_status) {
+ case POSIX_ABSOLUTE_TIMEOUT_INVALID:
+ return EINVAL;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
+ case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
+ return ETIMEDOUT;
+ case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
+ break;
}
- }
+ }
- return _POSIX_Semaphore_Wait_support( sem, blocking, ticks );
+ return lock_status;
}
diff --git a/cpukit/posix/src/semtrywait.c b/cpukit/posix/src/semtrywait.c
index 2aecde9425..17a7dd41ca 100644
--- a/cpukit/posix/src/semtrywait.c
+++ b/cpukit/posix/src/semtrywait.c
@@ -31,5 +31,5 @@ int sem_trywait(
sem_t *sem
)
{
- return _POSIX_Semaphore_Wait_support( sem, FALSE, THREAD_QUEUE_WAIT_FOREVER );
+ return _POSIX_Semaphore_Wait_support(sem, FALSE, THREAD_QUEUE_WAIT_FOREVER);
}
diff --git a/cpukit/posix/src/semwait.c b/cpukit/posix/src/semwait.c
index b43a1e47b4..9ef787c727 100644
--- a/cpukit/posix/src/semwait.c
+++ b/cpukit/posix/src/semwait.c
@@ -31,9 +31,5 @@ int sem_wait(
sem_t *sem
)
{
- return _POSIX_Semaphore_Wait_support(
- sem,
- CORE_SEMAPHORE_BLOCK_FOREVER,
- THREAD_QUEUE_WAIT_FOREVER
- );
+ return _POSIX_Semaphore_Wait_support( sem, TRUE, THREAD_QUEUE_WAIT_FOREVER );
}
diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c
index bfa8831f6a..db99b85073 100644
--- a/cpukit/rtems/src/semobtain.c
+++ b/cpukit/rtems/src/semobtain.c
@@ -107,8 +107,7 @@ rtems_status_code rtems_semaphore_obtain(
_CORE_semaphore_Seize_isr_disable(
&the_semaphore->Core_control.semaphore,
id,
- ((_Options_Is_no_wait( option_set )) ?
- CORE_SEMAPHORE_NO_WAIT : CORE_SEMAPHORE_BLOCK_FOREVER),
+ ((_Options_Is_no_wait( option_set )) ? FALSE : TRUE),
timeout,
&level
);
diff --git a/cpukit/rtems/src/semtranslatereturncode.c b/cpukit/rtems/src/semtranslatereturncode.c
index d7d2d306ac..87999d3cc9 100644
--- a/cpukit/rtems/src/semtranslatereturncode.c
+++ b/cpukit/rtems/src/semtranslatereturncode.c
@@ -103,7 +103,6 @@ rtems_status_code _Semaphore_Translate_core_semaphore_return_code_[] = {
RTEMS_OBJECT_WAS_DELETED, /* CORE_SEMAPHORE_WAS_DELETED */
RTEMS_TIMEOUT, /* CORE_SEMAPHORE_TIMEOUT */
RTEMS_INTERNAL_ERROR, /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
- RTEMS_INTERNAL_ERROR /* CORE_SEMAPHORE_BAD_TIMEOUT_VALUE */
};
rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
@@ -114,7 +113,7 @@ rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
if ( status == THREAD_STATUS_PROXY_BLOCKING )
return RTEMS_PROXY_BLOCKING;
#endif
- if ( status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
+ if ( status > CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED )
return RTEMS_INTERNAL_ERROR;
return _Semaphore_Translate_core_semaphore_return_code_[status];
}
diff --git a/cpukit/score/include/rtems/score/coresem.h b/cpukit/score/include/rtems/score/coresem.h
index f508d9f00c..6db409ebe4 100644
--- a/cpukit/score/include/rtems/score/coresem.h
+++ b/cpukit/score/include/rtems/score/coresem.h
@@ -82,14 +82,7 @@ typedef enum {
/** This status indicates that an attempt was made to unlock the semaphore
* and this would have made its count greater than that allowed.
*/
- CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED,
- /** This status indicates that the semaphore was not immediately
- * available and the caller passed a bad timeout value to the API
- * routine. In this case, the API required that the validity check
- * for the timeout occur after the check that the semaphore was immediately
- * available.
- */
- CORE_SEMAPHORE_BAD_TIMEOUT_VALUE
+ CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
} CORE_semaphore_Status;
/**
@@ -123,25 +116,6 @@ typedef struct {
} CORE_semaphore_Control;
/**
- * The following enumerated type is the set of blocking options
- * available to seize operation.
- */
-typedef enum {
- /** This value indicates that the caller does not wish to block. */
- CORE_SEMAPHORE_NO_WAIT,
- /** This value indicates that the caller is willing to block forever. */
- CORE_SEMAPHORE_BLOCK_FOREVER,
- /** This value indicates that the caller is blocking with a timeout. */
- CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT,
- /** This value indicates that the caller wanted to block but passed in
- * a bad timeout value to the API. Unfortunately, this is a weird case
- * where the timeout bad error is required to be generated only if
- * the semaphore is not available.
- */
- CORE_SEMAPHORE_BAD_TIMEOUT
-} Core_semaphore_Blocking_option;
-
-/**
* This routine initializes the semaphore based on the parameters passed.
*
* @param[in] the_semaphore is the semaphore to initialize
@@ -163,15 +137,15 @@ void _CORE_semaphore_Initialize(
* @param[in] the_semaphore is the semaphore to seize
* @param[in] id is the Id of the API level Semaphore object associated
* with this instance of a SuperCore Semaphore
- * @param[in] wait is the blocking mode
+ * @param[in] wait indicates if the caller is willing to block
* @param[in] timeout is the number of ticks the calling thread is willing
* to wait if @a wait is TRUE.
*/
void _CORE_semaphore_Seize(
- CORE_semaphore_Control *the_semaphore,
- Objects_Id id,
- Core_semaphore_Blocking_option wait,
- Watchdog_Interval timeout
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ boolean wait,
+ Watchdog_Interval timeout
);
/**
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
index a71f1de794..e049b6e114 100644
--- a/cpukit/score/src/coremsgseize.c
+++ b/cpukit/score/src/coremsgseize.c
@@ -84,7 +84,7 @@ void _CORE_message_queue_Seize(
*size = the_message->Contents.size;
_Thread_Executing->Wait.count = the_message->priority;
- _CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size);
+ _CORE_message_queue_Copy_buffer(the_message->Contents.buffer, buffer,*size);
/*
* There could be a thread waiting to send a message. If there
@@ -107,7 +107,7 @@ void _CORE_message_queue_Seize(
*/
the_message->priority = the_thread->Wait.count;
- the_message->Contents.size = (uint32_t )the_thread->Wait.return_argument_1;
+ the_message->Contents.size = (uint32_t)the_thread->Wait.option;
_CORE_message_queue_Copy_buffer(
the_thread->Wait.return_argument,
the_message->Contents.buffer,
diff --git a/cpukit/score/src/coresemseize.c b/cpukit/score/src/coresemseize.c
index 693a19a713..779b24ca6a 100644
--- a/cpukit/score/src/coresemseize.c
+++ b/cpukit/score/src/coresemseize.c
@@ -51,10 +51,10 @@
*/
void _CORE_semaphore_Seize(
- CORE_semaphore_Control *the_semaphore,
- Objects_Id id,
- Core_semaphore_Blocking_option wait,
- Watchdog_Interval timeout
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ boolean wait,
+ Watchdog_Interval timeout
)
{
Thread_Control *executing;
@@ -69,23 +69,20 @@ void _CORE_semaphore_Seize(
return;
}
- switch ( wait ) {
- case CORE_SEMAPHORE_NO_WAIT:
- _ISR_Enable( level );
- executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
- return;
- case CORE_SEMAPHORE_BAD_TIMEOUT:
- _ISR_Enable( level );
- executing->Wait.return_code = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
- return;
- case CORE_SEMAPHORE_BLOCK_FOREVER:
- case CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT:
- _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
- executing->Wait.queue = &the_semaphore->Wait_queue;
- executing->Wait.id = id;
- _ISR_Enable( level );
- _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
- break;
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
+ return;
}
+ /*
+ * If the semaphore is not available and the caller is willing to
+ * block, then we now block the caller with optional timeout.
+ */
+ _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
+ executing->Wait.queue = &the_semaphore->Wait_queue;
+ executing->Wait.id = id;
+ _ISR_Enable( level );
+ _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
+
}