[PATCH 16/16] score: Move thread queue timeout handling

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Oct 23 14:04:16 UTC 2017


Update #3117.
Update #3182.
---
 cpukit/libnetworking/rtems/rtems_glue.c         |    2 +-
 cpukit/posix/include/rtems/posix/mqueueimpl.h   |   25 +-
 cpukit/posix/include/rtems/posix/muteximpl.h    |   32 +-
 cpukit/posix/src/condwaitsupp.c                 |  126 +-
 cpukit/posix/src/mqueuereceive.c                |   15 +-
 cpukit/posix/src/mqueuerecvsupp.c               |   29 +-
 cpukit/posix/src/mqueuesend.c                   |    4 +-
 cpukit/posix/src/mqueuesendsupp.c               |   26 +-
 cpukit/posix/src/mqueuetimedreceive.c           |   36 +-
 cpukit/posix/src/mqueuetimedsend.c              |   36 +-
 cpukit/posix/src/mutexlock.c                    |   13 +-
 cpukit/posix/src/mutexlocksupp.c                |   20 +-
 cpukit/posix/src/mutextimedlock.c               |   50 +-
 cpukit/posix/src/mutextrylock.c                 |   24 +-
 cpukit/posix/src/nanosleep.c                    |  255 +-
 cpukit/posix/src/pbarrierwait.c                 |    1 -
 cpukit/posix/src/prwlockrdlock.c                |    2 +-
 cpukit/posix/src/prwlocktimedrdlock.c           |   47 +-
 cpukit/posix/src/prwlocktimedwrlock.c           |   47 +-
 cpukit/posix/src/prwlockwrlock.c                |    2 +-
 cpukit/posix/src/pthreadjoin.c                  |    1 -
 cpukit/posix/src/semtimedwait.c                 |   23 +-
 cpukit/posix/src/sigtimedwait.c                 |   25 +-
 cpukit/rtems/src/barrierwait.c                  |    2 +-
 cpukit/rtems/src/msgqreceive.c                  |    2 +-
 cpukit/rtems/src/regiongetsegment.c             |   10 +-
 cpukit/rtems/src/semobtain.c                    |    6 +-
 cpukit/score/Makefile.am                        |    2 +-
 cpukit/score/include/rtems/score/coresemimpl.h  |    1 -
 cpukit/score/include/rtems/score/threadq.h      |   33 +-
 cpukit/score/include/rtems/score/threadqimpl.h  |  110 +-
 cpukit/score/include/rtems/score/todimpl.h      |   40 -
 cpukit/score/include/rtems/score/watchdog.h     |   31 +-
 cpukit/score/include/rtems/score/watchdogimpl.h |    5 +
 cpukit/score/src/apimutexlock.c                 |    2 +-
 cpukit/score/src/condition.c                    |   88 +-
 cpukit/score/src/corebarrierwait.c              |    1 -
 cpukit/score/src/coremsgseize.c                 |    1 -
 cpukit/score/src/coremsgsubmit.c                |    1 -
 cpukit/score/src/coremutexseize.c               |    1 -
 cpukit/score/src/corerwlockobtainread.c         |    1 -
 cpukit/score/src/corerwlockobtainwrite.c        |    1 -
 cpukit/score/src/coretodabsolutetimeout.c       |   82 -
 cpukit/score/src/futex.c                        |    1 -
 cpukit/score/src/mutex.c                        |   43 +-
 cpukit/score/src/semaphore.c                    |    1 -
 cpukit/score/src/threadqenqueue.c               |   54 +-
 cpukit/score/src/threadqtimeout.c               |  154 +
 cpukit/score/src/threadrestart.c                |    2 +-
 testsuites/tmtests/tmfine01/tmfine01.scn        | 7200 +++++++++++------------
 50 files changed, 4239 insertions(+), 4477 deletions(-)
 delete mode 100644 cpukit/score/src/coretodabsolutetimeout.c
 create mode 100644 cpukit/score/src/threadqtimeout.c

diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
index 939b858dc7..785f841fba 100644
--- a/cpukit/libnetworking/rtems/rtems_glue.c
+++ b/cpukit/libnetworking/rtems/rtems_glue.c
@@ -376,7 +376,7 @@ rtems_bsdnet_semaphore_obtain (void)
 		rtems_panic ("rtems-net: network sema obtain: network not initialised\n");
 	_Thread_queue_Context_initialize(&queue_context);
 	_ISR_lock_ISR_disable(&queue_context.Lock_context.Lock_context);
-	_Thread_queue_Context_set_no_timeout( &queue_context );
+	_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
 	status = _CORE_recursive_mutex_Seize (
 		&the_networkSemaphore->Core_control.Mutex.Recursive,
 		CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
diff --git a/cpukit/posix/include/rtems/posix/mqueueimpl.h b/cpukit/posix/include/rtems/posix/mqueueimpl.h
index 5888800ca1..6813a3ef88 100644
--- a/cpukit/posix/include/rtems/posix/mqueueimpl.h
+++ b/cpukit/posix/include/rtems/posix/mqueueimpl.h
@@ -22,6 +22,7 @@
 #include <rtems/posix/mqueue.h>
 #include <rtems/posix/posixapi.h>
 #include <rtems/score/coremsgimpl.h>
+#include <rtems/score/threadqimpl.h>
 
 #include <rtems/seterr.h>
 
@@ -63,12 +64,12 @@ void _POSIX_Message_queue_Delete(
  * @note This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open time.
  */
 ssize_t _POSIX_Message_queue_Receive_support(
-  mqd_t               mqdes,
-  char               *msg_ptr,
-  size_t              msg_len,
-  unsigned int       *msg_prio,
-  bool                wait,
-  Watchdog_Interval   timeout
+  mqd_t                         mqdes,
+  char                         *msg_ptr,
+  size_t                        msg_len,
+  unsigned int                 *msg_prio,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 );
 
 /**
@@ -77,12 +78,12 @@ ssize_t _POSIX_Message_queue_Receive_support(
  *  This routine posts a message to a specified message queue.
  */
 int _POSIX_Message_queue_Send_support(
-  mqd_t               mqdes,
-  const char         *msg_ptr,
-  size_t              msg_len,
-  unsigned int        msg_prio,
-  bool                wait,
-  Watchdog_Interval   timeout
+  mqd_t                         mqdes,
+  const char                   *msg_ptr,
+  size_t                        msg_len,
+  unsigned int                  msg_prio,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 );
 
 RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control *
diff --git a/cpukit/posix/include/rtems/posix/muteximpl.h b/cpukit/posix/include/rtems/posix/muteximpl.h
index f146e0d9db..435b43634d 100644
--- a/cpukit/posix/include/rtems/posix/muteximpl.h
+++ b/cpukit/posix/include/rtems/posix/muteximpl.h
@@ -132,7 +132,7 @@ Status_Control _POSIX_Mutex_Seize_slow(
   POSIX_Mutex_Control           *the_mutex,
   const Thread_queue_Operations *operations,
   Thread_Control                *executing,
-  bool                           wait,
+  const struct timespec         *abstime,
   Thread_queue_Context          *queue_context
 );
 
@@ -171,7 +171,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize(
   unsigned long                  flags,
   const Thread_queue_Operations *operations,
   Thread_Control                *executing,
-  bool                           wait,
+  const struct timespec         *abstime,
   Thread_queue_Context          *queue_context
 )
 {
@@ -198,7 +198,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize(
     the_mutex,
     operations,
     executing,
-    wait,
+    abstime,
     queue_context
   );
 }
@@ -329,11 +329,11 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_set_owner(
 }
 
 RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize(
-  POSIX_Mutex_Control  *the_mutex,
-  unsigned long         flags,
-  Thread_Control       *executing,
-  bool                  wait,
-  Thread_queue_Context *queue_context
+  POSIX_Mutex_Control   *the_mutex,
+  unsigned long          flags,
+  Thread_Control        *executing,
+  const struct timespec *abstime,
+  Thread_queue_Context  *queue_context
 )
 {
   Thread_Control *owner;
@@ -371,7 +371,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize(
     the_mutex,
     POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS,
     executing,
-    wait,
+    abstime,
     queue_context
   );
 }
@@ -444,16 +444,12 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_surrender(
   return STATUS_SUCCESSFUL;
 }
 
-/**
- *  @brief POSIX Mutex Lock Support Method
- *
- *  A support routine which implements guts of the blocking, non-blocking, and
- *  timed wait version of mutex lock.
- */
+#define POSIX_MUTEX_ABSTIME_TRY_LOCK ((uintptr_t) 1)
+
 int _POSIX_Mutex_Lock_support(
-  pthread_mutex_t           *mutex,
-  bool                       blocking,
-  Watchdog_Interval          timeout
+  pthread_mutex_t              *mutex,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 );
 
 static inline POSIX_Mutex_Control *_POSIX_Mutex_Get(
diff --git a/cpukit/posix/src/condwaitsupp.c b/cpukit/posix/src/condwaitsupp.c
index ceaa6eb1af..32c1eab629 100644
--- a/cpukit/posix/src/condwaitsupp.c
+++ b/cpukit/posix/src/condwaitsupp.c
@@ -25,7 +25,7 @@
 #include <rtems/score/status.h>
 #include <rtems/score/threaddispatch.h>
 
-static void _POSIX_Condition_variables_Enqueue_callout(
+static void _POSIX_Condition_variables_Mutex_unlock(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
   Thread_queue_Context *queue_context
@@ -44,11 +44,52 @@ static void _POSIX_Condition_variables_Enqueue_callout(
      *  case, so we follow their lead.
      */
     _Assert( mutex_error == EINVAL || mutex_error == EPERM );
-    _Thread_queue_Extract( the_thread );
-    the_thread->Wait.return_code= STATUS_NOT_OWNER;
+    _Thread_Continue( the_thread, STATUS_NOT_OWNER );
   }
 }
 
+static void _POSIX_Condition_variables_Enqueue_no_timeout(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  _POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
+}
+
+static void _POSIX_Condition_variables_Enqueue_with_timeout_monotonic(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  _Thread_queue_Add_timeout_monotonic_timespec(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
+  _POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
+}
+
+static void _POSIX_Condition_variables_Enqueue_with_timeout_realtime(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  _Thread_queue_Add_timeout_realtime_timespec(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
+  _POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
+}
+
 int _POSIX_Condition_variables_Wait_support(
   pthread_cond_t            *cond,
   pthread_mutex_t           *mutex,
@@ -59,44 +100,32 @@ int _POSIX_Condition_variables_Wait_support(
   unsigned long                      flags;
   Thread_queue_Context               queue_context;
   int                                error;
-  int                                mutex_error;
   Thread_Control                    *executing;
-  Watchdog_Interval                  timeout;
-  bool                               already_timedout;
-  TOD_Absolute_timeout_conversion_results  status;
 
   the_cond = _POSIX_Condition_variables_Get( cond );
   POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
 
   _Thread_queue_Context_initialize( &queue_context );
-  already_timedout = false;
 
   if ( abstime != NULL ) {
-    /*
-     *  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 = _TOD_Absolute_timeout_to_ticks(
-      abstime,
-      _POSIX_Condition_variables_Get_clock( flags ),
-      &timeout
-    );
-    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
-      return EINVAL;
+    _Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
 
-    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
-        status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) {
-      already_timedout = true;
+    if ( _POSIX_Condition_variables_Get_clock( flags ) == CLOCK_MONOTONIC ) {
+      _Thread_queue_Context_set_enqueue_callout(
+        &queue_context,
+        _POSIX_Condition_variables_Enqueue_with_timeout_monotonic
+      );
     } else {
-      _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
+      _Thread_queue_Context_set_enqueue_callout(
+        &queue_context,
+        _POSIX_Condition_variables_Enqueue_with_timeout_realtime
+      );
     }
   } else {
-    _Thread_queue_Context_set_no_timeout( &queue_context );
+    _Thread_queue_Context_set_enqueue_callout(
+      &queue_context,
+      _POSIX_Condition_variables_Enqueue_no_timeout
+    );
   }
 
   executing = _POSIX_Condition_variables_Acquire( the_cond, &queue_context );
@@ -111,32 +140,17 @@ int _POSIX_Condition_variables_Wait_support(
 
   the_cond->mutex = mutex;
 
-  if ( !already_timedout ) {
-    _Thread_queue_Context_set_thread_state(
-      &queue_context,
-      STATES_WAITING_FOR_CONDITION_VARIABLE
-    );
-    _Thread_queue_Context_set_enqueue_callout(
-      &queue_context,
-      _POSIX_Condition_variables_Enqueue_callout
-    );
-    _Thread_queue_Enqueue(
-      &the_cond->Queue.Queue,
-      POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
-      executing,
-      &queue_context
-    );
-    error = _POSIX_Get_error_after_wait( executing );
-  } else {
-    _POSIX_Condition_variables_Release( the_cond, &queue_context );
-
-    mutex_error = pthread_mutex_unlock( the_cond->mutex );
-    if ( mutex_error != 0 ) {
-      error = EPERM;
-    } else {
-      error = ETIMEDOUT;
-    }
-  }
+  _Thread_queue_Context_set_thread_state(
+    &queue_context,
+    STATES_WAITING_FOR_CONDITION_VARIABLE
+  );
+  _Thread_queue_Enqueue(
+    &the_cond->Queue.Queue,
+    POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
+    executing,
+    &queue_context
+  );
+  error = _POSIX_Get_error_after_wait( executing );
 
   /*
    *  If the thread is interrupted, while in the thread queue, by
@@ -155,6 +169,8 @@ int _POSIX_Condition_variables_Wait_support(
    */
 
   if ( error != EPERM ) {
+    int mutex_error;
+
     mutex_error = pthread_mutex_lock( mutex );
     if ( mutex_error != 0 ) {
       _Assert( mutex_error == EINVAL );
diff --git a/cpukit/posix/src/mqueuereceive.c b/cpukit/posix/src/mqueuereceive.c
index 465cd79cec..c160634dc5 100644
--- a/cpukit/posix/src/mqueuereceive.c
+++ b/cpukit/posix/src/mqueuereceive.c
@@ -18,17 +18,6 @@
 #include "config.h"
 #endif
 
-#include <stdarg.h>
-
-#include <pthread.h>
-#include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <mqueue.h>
-
-#include <rtems/system.h>
-#include <rtems/score/watchdog.h>
-#include <rtems/seterr.h>
 #include <rtems/posix/mqueueimpl.h>
 
 ssize_t mq_receive(
@@ -43,7 +32,7 @@ ssize_t mq_receive(
     msg_ptr,
     msg_len,
     msg_prio,
-    true,
-    WATCHDOG_NO_TIMEOUT
+    NULL,
+    _Thread_queue_Enqueue_do_nothing_extra
   );
 }
diff --git a/cpukit/posix/src/mqueuerecvsupp.c b/cpukit/posix/src/mqueuerecvsupp.c
index 416e7989fd..c6d1805214 100644
--- a/cpukit/posix/src/mqueuerecvsupp.c
+++ b/cpukit/posix/src/mqueuerecvsupp.c
@@ -36,18 +36,17 @@ THREAD_QUEUE_OBJECT_ASSERT(
  */
 
 ssize_t _POSIX_Message_queue_Receive_support(
-  mqd_t               mqdes,
-  char               *msg_ptr,
-  size_t              msg_len,
-  unsigned int       *msg_prio,
-  bool                wait,
-  Watchdog_Interval   timeout
+  mqd_t                         mqdes,
+  char                         *msg_ptr,
+  size_t                        msg_len,
+  unsigned int                 *msg_prio,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 )
 {
   POSIX_Message_queue_Control *the_mq;
   Thread_queue_Context         queue_context;
   size_t                       length_out;
-  bool                         do_wait;
   Thread_Control              *executing;
   Status_Control               status;
 
@@ -67,22 +66,15 @@ ssize_t _POSIX_Message_queue_Receive_support(
     rtems_set_errno_and_return_minus_one( EMSGSIZE );
   }
 
+  _Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout );
+  _Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
+
   /*
    *  Now if something goes wrong, we return a "length" of -1
    *  to indicate an error.
    */
-
   length_out = -1;
 
-  /*
-   *  A timed receive with a bad time will do a poll regardless.
-   */
-  if ( wait ) {
-    do_wait = ( the_mq->oflag & O_NONBLOCK ) == 0;
-  } else {
-    do_wait = wait;
-  }
-
   _CORE_message_queue_Acquire_critical(
     &the_mq->Message_queue,
     &queue_context
@@ -97,13 +89,12 @@ ssize_t _POSIX_Message_queue_Receive_support(
    *  Now perform the actual message receive
    */
   executing = _Thread_Executing;
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
   status = _CORE_message_queue_Seize(
     &the_mq->Message_queue,
     executing,
     msg_ptr,
     &length_out,
-    do_wait,
+    ( the_mq->oflag & O_NONBLOCK ) == 0,
     &queue_context
   );
 
diff --git a/cpukit/posix/src/mqueuesend.c b/cpukit/posix/src/mqueuesend.c
index 6cf67cd3bb..4843ae073d 100644
--- a/cpukit/posix/src/mqueuesend.c
+++ b/cpukit/posix/src/mqueuesend.c
@@ -61,7 +61,7 @@ int mq_send(
     msg_ptr,
     msg_len,
     msg_prio,
-    true,
-    WATCHDOG_NO_TIMEOUT
+    NULL,
+    _Thread_queue_Enqueue_do_nothing_extra
   );
 }
diff --git a/cpukit/posix/src/mqueuesendsupp.c b/cpukit/posix/src/mqueuesendsupp.c
index c975a95505..a238991af5 100644
--- a/cpukit/posix/src/mqueuesendsupp.c
+++ b/cpukit/posix/src/mqueuesendsupp.c
@@ -35,18 +35,17 @@
 #include <fcntl.h>
 
 int _POSIX_Message_queue_Send_support(
-  mqd_t               mqdes,
-  const char         *msg_ptr,
-  size_t              msg_len,
-  unsigned int        msg_prio,
-  bool                wait,
-  Watchdog_Interval   timeout
+  mqd_t                         mqdes,
+  const char                   *msg_ptr,
+  size_t                        msg_len,
+  unsigned int                  msg_prio,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 )
 {
   POSIX_Message_queue_Control *the_mq;
   Thread_queue_Context         queue_context;
   Status_Control               status;
-  bool                         do_wait;
   Thread_Control              *executing;
 
   /*
@@ -69,14 +68,8 @@ int _POSIX_Message_queue_Send_support(
     rtems_set_errno_and_return_minus_one( EBADF );
   }
 
-  /*
-   *  A timed receive with a bad time will do a poll regardless.
-   */
-  if ( wait ) {
-    do_wait = ( the_mq->oflag & O_NONBLOCK ) == 0;
-  } else {
-    do_wait = wait;
-  }
+  _Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout );
+  _Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
 
   _CORE_message_queue_Acquire_critical(
     &the_mq->Message_queue,
@@ -92,14 +85,13 @@ int _POSIX_Message_queue_Send_support(
    *  Now perform the actual message receive
    */
   executing = _Thread_Executing;
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
   status = _CORE_message_queue_Submit(
     &the_mq->Message_queue,
     executing,
     msg_ptr,
     msg_len,
     _POSIX_Message_queue_Priority_to_core( msg_prio ),
-    do_wait,
+    ( the_mq->oflag & O_NONBLOCK ) == 0,
     &queue_context
   );
   return _POSIX_Zero_or_minus_one_plus_errno( status );
diff --git a/cpukit/posix/src/mqueuetimedreceive.c b/cpukit/posix/src/mqueuetimedreceive.c
index f9b2730baa..fe9fc75053 100644
--- a/cpukit/posix/src/mqueuetimedreceive.c
+++ b/cpukit/posix/src/mqueuetimedreceive.c
@@ -32,17 +32,6 @@
 #include "config.h"
 #endif
 
-#include <stdarg.h>
-
-#include <pthread.h>
-#include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <mqueue.h>
-
-#include <rtems/system.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/seterr.h>
 #include <rtems/posix/mqueueimpl.h>
 
 /*
@@ -59,33 +48,12 @@ ssize_t mq_timedreceive(
   const struct timespec *__restrict abstime
 )
 {
-  Watchdog_Interval                            ticks;
-  bool                                         do_wait = true;
-  TOD_Absolute_timeout_conversion_results  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.
-   *
-   *  If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
-   *  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-   *  then we should not wait.
-   */
-  status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
-  if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
-    do_wait = false;
-
   return _POSIX_Message_queue_Receive_support(
     mqdes,
     msg_ptr,
     msg_len,
     msg_prio,
-    do_wait,
-    ticks
+    abstime,
+    _Thread_queue_Add_timeout_realtime_timespec
   );
 }
diff --git a/cpukit/posix/src/mqueuetimedsend.c b/cpukit/posix/src/mqueuetimedsend.c
index 3920a3fcc1..5596517c78 100644
--- a/cpukit/posix/src/mqueuetimedsend.c
+++ b/cpukit/posix/src/mqueuetimedsend.c
@@ -18,17 +18,6 @@
 #include "config.h"
 #endif
 
-#include <stdarg.h>
-
-#include <pthread.h>
-#include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <mqueue.h>
-
-#include <rtems/system.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/seterr.h>
 #include <rtems/posix/mqueueimpl.h>
 
 int mq_timedsend(
@@ -39,33 +28,12 @@ int mq_timedsend(
   const struct timespec *abstime
 )
 {
-  Watchdog_Interval                            ticks;
-  bool                                         do_wait = true;
-  TOD_Absolute_timeout_conversion_results  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.
-   *
-   *  If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
-   *  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-   *  then we should not wait.
-   */
-  status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
-  if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
-    do_wait = false;
-
   return _POSIX_Message_queue_Send_support(
     mqdes,
     msg_ptr,
     msg_len,
     msg_prio,
-    do_wait,
-    ticks
+    abstime,
+    _Thread_queue_Add_timeout_realtime_timespec
   );
 }
diff --git a/cpukit/posix/src/mutexlock.c b/cpukit/posix/src/mutexlock.c
index d4cf4b74bd..35722fe96f 100644
--- a/cpukit/posix/src/mutexlock.c
+++ b/cpukit/posix/src/mutexlock.c
@@ -18,14 +18,7 @@
 #include "config.h"
 #endif
 
-#include <errno.h>
-#include <pthread.h>
-
-#include <rtems/system.h>
-#include <rtems/score/coremuteximpl.h>
-#include <rtems/score/watchdog.h>
 #include <rtems/posix/muteximpl.h>
-#include <rtems/posix/priorityimpl.h>
 
 /*
  *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
@@ -37,5 +30,9 @@ int pthread_mutex_lock(
   pthread_mutex_t           *mutex
 )
 {
-  return _POSIX_Mutex_Lock_support( mutex, true, WATCHDOG_NO_TIMEOUT );
+  return _POSIX_Mutex_Lock_support(
+    mutex,
+    NULL,
+    _Thread_queue_Enqueue_do_nothing_extra
+  );
 }
diff --git a/cpukit/posix/src/mutexlocksupp.c b/cpukit/posix/src/mutexlocksupp.c
index 4b0f366629..4530a6bea2 100644
--- a/cpukit/posix/src/mutexlocksupp.c
+++ b/cpukit/posix/src/mutexlocksupp.c
@@ -25,16 +25,15 @@ Status_Control _POSIX_Mutex_Seize_slow(
   POSIX_Mutex_Control           *the_mutex,
   const Thread_queue_Operations *operations,
   Thread_Control                *executing,
-  bool                           wait,
+  const struct timespec         *abstime,
   Thread_queue_Context          *queue_context
 )
 {
-  if ( wait ) {
+  if ( (uintptr_t) abstime != POSIX_MUTEX_ABSTIME_TRY_LOCK ) {
     _Thread_queue_Context_set_thread_state(
       queue_context,
       STATES_WAITING_FOR_MUTEX
     );
-    _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
     _Thread_queue_Context_set_deadlock_callout(
       queue_context,
       _Thread_queue_Deadlock_status
@@ -53,9 +52,9 @@ Status_Control _POSIX_Mutex_Seize_slow(
 }
 
 int _POSIX_Mutex_Lock_support(
-  pthread_mutex_t   *mutex,
-  bool               wait,
-  Watchdog_Interval  timeout
+  pthread_mutex_t              *mutex,
+  const struct timespec        *abstime,
+  Thread_queue_Enqueue_callout  enqueue_callout
 )
 {
   POSIX_Mutex_Control  *the_mutex;
@@ -68,7 +67,8 @@ int _POSIX_Mutex_Lock_support(
   POSIX_MUTEX_VALIDATE_OBJECT( the_mutex, flags );
 
   executing = _POSIX_Mutex_Acquire( the_mutex, &queue_context );
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
+  _Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout);
+  _Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
 
   switch ( _POSIX_Mutex_Get_protocol( flags ) ) {
     case POSIX_MUTEX_PRIORITY_CEILING:
@@ -76,7 +76,7 @@ int _POSIX_Mutex_Lock_support(
         the_mutex,
         flags,
         executing,
-        wait,
+        abstime,
         &queue_context
       );
       break;
@@ -86,7 +86,7 @@ int _POSIX_Mutex_Lock_support(
         flags,
         POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS,
         executing,
-        wait,
+        abstime,
         &queue_context
       );
       break;
@@ -99,7 +99,7 @@ int _POSIX_Mutex_Lock_support(
         flags,
         POSIX_MUTEX_PRIORITY_INHERIT_TQ_OPERATIONS,
         executing,
-        wait,
+        abstime,
         &queue_context
       );
       break;
diff --git a/cpukit/posix/src/mutextimedlock.c b/cpukit/posix/src/mutextimedlock.c
index cfc1827ae8..075417a3dd 100644
--- a/cpukit/posix/src/mutextimedlock.c
+++ b/cpukit/posix/src/mutextimedlock.c
@@ -18,14 +18,7 @@
 #include "config.h"
 #endif
 
-#include <errno.h>
-#include <pthread.h>
-
-#include <rtems/system.h>
-#include <rtems/score/coremuteximpl.h>
-#include <rtems/score/todimpl.h>
 #include <rtems/posix/muteximpl.h>
-#include <rtems/posix/priorityimpl.h>
 
 /**
  * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
@@ -37,42 +30,9 @@ int pthread_mutex_timedlock(
   const struct timespec *abstime
 )
 {
-  Watchdog_Interval                            ticks;
-  bool                                         do_wait = true;
-  TOD_Absolute_timeout_conversion_results  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.
-   *
-   *  If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
-   *  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-   *  then we should not wait.
-   */
-  status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
-  if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
-    do_wait = false;
-
-  lock_status = _POSIX_Mutex_Lock_support( mutex, 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) ) {
-    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
-      return EINVAL;
-    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
-         status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
-      return ETIMEDOUT;
-  }
-
-  return lock_status;
+  return _POSIX_Mutex_Lock_support(
+    mutex,
+    abstime,
+    _Thread_queue_Add_timeout_realtime_timespec
+  );
 }
diff --git a/cpukit/posix/src/mutextrylock.c b/cpukit/posix/src/mutextrylock.c
index d029ae5de6..895f38fa44 100644
--- a/cpukit/posix/src/mutextrylock.c
+++ b/cpukit/posix/src/mutextrylock.c
@@ -18,14 +18,7 @@
 #include "config.h"
 #endif
 
-#include <errno.h>
-#include <pthread.h>
-
-#include <rtems/system.h>
-#include <rtems/score/coremuteximpl.h>
-#include <rtems/score/watchdog.h>
 #include <rtems/posix/muteximpl.h>
-#include <rtems/posix/priorityimpl.h>
 
 /**
  * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
@@ -36,8 +29,17 @@ int pthread_mutex_trylock(
   pthread_mutex_t           *mutex
 )
 {
-  int r = _POSIX_Mutex_Lock_support( mutex, false, WATCHDOG_NO_TIMEOUT );
-  if ( r == EDEADLK )
-    r = EBUSY;
-  return r;
+  int eno;
+
+  eno = _POSIX_Mutex_Lock_support(
+    mutex,
+    (const struct timespec *) POSIX_MUTEX_ABSTIME_TRY_LOCK,
+    NULL
+  );
+
+  if ( eno == EDEADLK ) {
+    eno = EBUSY;
+  }
+
+  return eno;
 }
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index e8a7fe14c1..f65c91bc17 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -21,100 +21,18 @@
 #endif
 
 #include <time.h>
-#include <errno.h>
 
-#include <rtems/seterr.h>
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/threadqimpl.h>
 #include <rtems/score/timespec.h>
+#include <rtems/score/todimpl.h>
 #include <rtems/score/watchdogimpl.h>
+#include <rtems/posix/posixapi.h>
+#include <rtems/seterr.h>
 
 static Thread_queue_Control _Nanosleep_Pseudo_queue =
   THREAD_QUEUE_INITIALIZER( "Nanosleep" );
 
-static inline int nanosleep_helper(
-  clockid_t             clock_id,
-  uint64_t              ticks,
-  struct timespec      *timeout,
-  struct timespec      *rmtp,
-  Watchdog_Discipline   discipline
-)
-{
-  Thread_queue_Context queue_context;
-  struct timespec      stop;
-  int                  err;
-
-  err = 0;
-
-  _Thread_queue_Context_initialize( &queue_context );
-  _Thread_queue_Context_set_thread_state(
-    &queue_context,
-    STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
-  );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-
-  if ( discipline == WATCHDOG_ABSOLUTE ) {
-    _Thread_queue_Context_set_absolute_timeout( &queue_context, ticks );
-  } else {
-    _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
-  }
-
-  /*
-   *  Block for the desired amount of time
-   */
-  _Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
-  _Thread_queue_Enqueue(
-    &_Nanosleep_Pseudo_queue.Queue,
-    &_Thread_queue_Operations_FIFO,
-    _Thread_Executing,
-    &queue_context
-  );
-
-  clock_gettime( clock_id, &stop );
-  /*
-   * If the user wants the time remaining, do the conversion.
-   */
-  if ( _Timespec_Less_than( &stop, timeout ) ) {
-    /*
-     *  If there is time remaining, then we were interrupted by a signal.
-     */
-    err = EINTR;
-    if ( rmtp != NULL ) {
-      _Timespec_Subtract( &stop, timeout, rmtp );
-    }
-  } else if ( rmtp != NULL ) {
-    /* no time remaining */
-    _Timespec_Set_to_zero( rmtp );
-  }
-
-  return err;
-}
-
-/*
- * A nanosleep for zero time is implemented as a yield.
- * This behavior is also beyond the POSIX specification but is
- * consistent with the RTEMS API and yields desirable behavior.
- */
-static inline int nanosleep_yield( struct timespec *rmtp )
-{
-  /*
-   * It is critical to obtain the executing thread after thread dispatching is
-   * disabled on SMP configurations.
-   */
-  Thread_Control  *executing;
-  Per_CPU_Control *cpu_self;
-
-  executing = _Thread_Get_executing();
-  cpu_self = _Thread_Dispatch_disable();
-  _Thread_Yield( executing );
-  _Thread_Dispatch_direct( cpu_self );
-  if ( rmtp ) {
-    rmtp->tv_sec = 0;
-    rmtp->tv_nsec = 0;
-  }
-  return 0;
-}
-
 /*
  *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
  */
@@ -123,43 +41,15 @@ int nanosleep(
   struct timespec        *rmtp
 )
 {
-  int err;
-  struct timespec now;
-  uint64_t ticks;
-  Watchdog_Interval relative_interval;
-
-  /*
-   *  Return EINVAL if the delay interval is negative.
-   *
-   *  NOTE:  This behavior is beyond the POSIX specification.
-   *         FSU and GNU/Linux pthreads shares this behavior.
-   */
-  if ( !_Timespec_Is_valid( rqtp ) ) {
-    rtems_set_errno_and_return_minus_one( EINVAL );
-  }
+  int eno;
 
-  relative_interval = _Timespec_To_ticks( rqtp );
-  if ( relative_interval == 0 )
-    return nanosleep_yield( rmtp );
-
- /* CLOCK_REALTIME can be adjusted during the timeout,
-  * so convert to an absolute timeout value and put the
-  * thread on the WATCHDOG_ABSOLUTE threadq. */
-  err = clock_gettime( CLOCK_REALTIME, &now );
-  if ( err != 0 )
-    return -1;
-  _Timespec_Add_to( &now, rqtp );
-  ticks = _Watchdog_Realtime_from_timespec( &now );
-  err = nanosleep_helper( CLOCK_REALTIME,
-      ticks,
-      &now,
-      rmtp,
-      WATCHDOG_ABSOLUTE
-  );
-  if ( err != 0 ) {
-    rtems_set_errno_and_return_minus_one( err );
+  eno = clock_nanosleep( CLOCK_REALTIME, 0, rqtp, rmtp );
+
+  if ( eno != 0 ) {
+    rtems_set_errno_and_return_minus_one( eno );
   }
-  return 0;
+
+  return eno;
 }
 
 /*
@@ -172,59 +62,82 @@ int clock_nanosleep(
   struct timespec        *rmtp
 )
 {
-  int err = 0;
-  struct timespec timeout;
-  uint64_t ticks;
-  Watchdog_Interval relative_interval;
-  TOD_Absolute_timeout_conversion_results status;
-
-  if ( !_Timespec_Is_valid( rqtp ) )
-    return EINVAL;
-
-  /* get relative ticks of the requested timeout */
-  if ( flags & TIMER_ABSTIME ) {
-    /* See if absolute time already passed */
-    status = _TOD_Absolute_timeout_to_ticks(rqtp, clock_id, &relative_interval);
-    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
-      return EINVAL;
-    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST )
-      return 0;
-    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
-      return nanosleep_yield( NULL );
-    rmtp = NULL; /* Do not touch rmtp when using absolute time */
-    timeout.tv_sec = 0;
-    timeout.tv_nsec = 0;
+  Thread_queue_Context   queue_context;
+  struct timespec        spare_end;
+  const struct timespec *end;
+  Thread_Control        *executing;
+  int                    eno;
+
+  if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
+    return ENOTSUP;
+  }
+
+  _Thread_queue_Context_initialize( &queue_context );
+  _Thread_queue_Context_set_thread_state(
+    &queue_context,
+    STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
+  );
+
+  if ( ( flags & TIMER_ABSTIME ) != 0 ) {
+    end = rqtp;
+
+    if ( clock_id == CLOCK_REALTIME ) {
+      _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+        &queue_context,
+        end
+      );
+    } else {
+      _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
+        &queue_context,
+        end
+      );
+    }
   } else {
-    /* prepare to convert relative ticks to absolute timeout */
-    err = clock_gettime( clock_id, &timeout );
-    if ( err != 0 )
+    if ( !_Watchdog_Is_valid_interval_timespec( rqtp ) ) {
       return EINVAL;
-    relative_interval = _Timespec_To_ticks( rqtp );
-  }
-  if ( relative_interval == 0 )
-    return nanosleep_yield( rmtp );
-
-  _Timespec_Add_to( &timeout, rqtp );
-  if ( clock_id == CLOCK_REALTIME ) {
-    ticks = _Watchdog_Realtime_from_timespec( &timeout );
-    err = nanosleep_helper(
-        clock_id,
-        ticks,
-        &timeout,
-        rmtp,
-        WATCHDOG_ABSOLUTE
-    );
-  } else if ( clock_id == CLOCK_MONOTONIC ) {
-    /* use the WATCHDOG_RELATIVE to ignore changes in wall time */
-    err = nanosleep_helper(
-        clock_id,
-        relative_interval,
-        &timeout,
-        rmtp,
-        WATCHDOG_RELATIVE
+    }
+
+    _TOD_Get_zero_based_uptime_as_timespec( &spare_end );
+
+    /* In case this overflows, then the enqueue callout will reject it */
+    _Timespec_Add_to( &spare_end, rqtp );
+
+    end = &spare_end;
+    _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
+      &queue_context,
+      end
     );
-  } else {
-    err = ENOTSUP;
   }
-  return err;
+
+  _Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
+  executing = _Thread_Executing;
+  _Thread_queue_Enqueue(
+    &_Nanosleep_Pseudo_queue.Queue,
+    &_Thread_queue_Operations_FIFO,
+    executing,
+    &queue_context
+  );
+  eno = _POSIX_Get_error_after_wait( executing );
+
+  if ( eno == ETIMEDOUT ) {
+    eno = 0;
+  }
+
+  if ( rmtp != NULL && ( flags & TIMER_ABSTIME ) == 0 ) {
+    if ( eno == EINTR ) {
+      struct timespec actual_end;
+
+      _TOD_Get_zero_based_uptime_as_timespec( &actual_end );
+
+      if ( _Timespec_Less_than( &actual_end, end ) ) {
+        _Timespec_Subtract( &actual_end, end, rmtp );
+      } else {
+        _Timespec_Set_to_zero( rmtp );
+      }
+    } else {
+      _Timespec_Set_to_zero( rmtp );
+    }
+  }
+
+  return eno;
 }
diff --git a/cpukit/posix/src/pbarrierwait.c b/cpukit/posix/src/pbarrierwait.c
index b9785216b4..75d9437774 100644
--- a/cpukit/posix/src/pbarrierwait.c
+++ b/cpukit/posix/src/pbarrierwait.c
@@ -54,7 +54,6 @@ int pthread_barrier_wait( pthread_barrier_t *_barrier )
       STATES_WAITING_FOR_BARRIER
     );
     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-    _Thread_queue_Context_set_no_timeout( &queue_context );
     _Thread_queue_Enqueue(
       &barrier->Queue.Queue,
       POSIX_BARRIER_TQ_OPERATIONS,
diff --git a/cpukit/posix/src/prwlockrdlock.c b/cpukit/posix/src/prwlockrdlock.c
index 4019c1fcb2..38c2981076 100644
--- a/cpukit/posix/src/prwlockrdlock.c
+++ b/cpukit/posix/src/prwlockrdlock.c
@@ -33,7 +33,7 @@ int pthread_rwlock_rdlock(
   POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
 
   _Thread_queue_Context_initialize( &queue_context );
-  _Thread_queue_Context_set_no_timeout( &queue_context );
+  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   status = _CORE_RWLock_Seize_for_reading(
     &the_rwlock->RWLock,
     true,                 /* we are willing to wait forever */
diff --git a/cpukit/posix/src/prwlocktimedrdlock.c b/cpukit/posix/src/prwlocktimedrdlock.c
index a9ac13348d..47c76d9136 100644
--- a/cpukit/posix/src/prwlocktimedrdlock.c
+++ b/cpukit/posix/src/prwlocktimedrdlock.c
@@ -20,59 +20,28 @@
 
 #include <rtems/posix/rwlockimpl.h>
 #include <rtems/posix/posixapi.h>
-#include <rtems/score/todimpl.h>
 
 int pthread_rwlock_timedrdlock(
   pthread_rwlock_t      *rwlock,
   const struct timespec *abstime
 )
 {
-  POSIX_RWLock_Control                    *the_rwlock;
-  Thread_queue_Context                     queue_context;
-  Watchdog_Interval                        ticks;
-  bool                                     do_wait;
-  TOD_Absolute_timeout_conversion_results  timeout_status;
-  Status_Control                           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 STATUS_UNAVAILABLE
-   *  status into the appropriate error.
-   *
-   *  If the timeout status is TOD_ABSOLUTE_TIMEOUT_INVALID,
-   *  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-   *  then we should not wait.
-   */
-  timeout_status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
-  do_wait = ( timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
+  POSIX_RWLock_Control *the_rwlock;
+  Thread_queue_Context  queue_context;
+  Status_Control        status;
 
   the_rwlock = _POSIX_RWLock_Get( rwlock );
   POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
 
   _Thread_queue_Context_initialize( &queue_context );
-  _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+  _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+    &queue_context,
+    abstime
+  );
   status = _CORE_RWLock_Seize_for_reading(
     &the_rwlock->RWLock,
-    do_wait,
+    true,
     &queue_context
   );
-
-  if ( !do_wait && status == STATUS_UNAVAILABLE ) {
-    if ( timeout_status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
-      return EINVAL;
-    }
-
-    if (
-      timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
-        || timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
-    ) {
-      return ETIMEDOUT;
-    }
-  }
-
   return _POSIX_Get_error( status );
 }
diff --git a/cpukit/posix/src/prwlocktimedwrlock.c b/cpukit/posix/src/prwlocktimedwrlock.c
index 1f1e654d53..a48f0e665c 100644
--- a/cpukit/posix/src/prwlocktimedwrlock.c
+++ b/cpukit/posix/src/prwlocktimedwrlock.c
@@ -22,59 +22,28 @@
 
 #include <rtems/posix/rwlockimpl.h>
 #include <rtems/posix/posixapi.h>
-#include <rtems/score/todimpl.h>
 
 int pthread_rwlock_timedwrlock(
   pthread_rwlock_t      *rwlock,
   const struct timespec *abstime
 )
 {
-  POSIX_RWLock_Control                    *the_rwlock;
-  Thread_queue_Context                     queue_context;
-  Watchdog_Interval                        ticks;
-  bool                                     do_wait;
-  TOD_Absolute_timeout_conversion_results  timeout_status;
-  Status_Control                           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 STATUS_UNAVAILABLE
-   *  status into the appropriate error.
-   *
-   *  If the timeout status is TOD_ABSOLUTE_TIMEOUT_INVALID,
-   *  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-   *  then we should not wait.
-   */
-  timeout_status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
-  do_wait = ( timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
+  POSIX_RWLock_Control *the_rwlock;
+  Thread_queue_Context  queue_context;
+  Status_Control        status;
 
   the_rwlock = _POSIX_RWLock_Get( rwlock );
   POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
 
   _Thread_queue_Context_initialize( &queue_context );
-  _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+  _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+    &queue_context,
+    abstime
+  );
   status = _CORE_RWLock_Seize_for_writing(
     &the_rwlock->RWLock,
-    do_wait,
+    true,
     &queue_context
   );
-
-  if ( !do_wait && status == STATUS_UNAVAILABLE ) {
-    if ( timeout_status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
-      return EINVAL;
-    }
-
-    if (
-      timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
-        || timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
-    ) {
-      return ETIMEDOUT;
-    }
-  }
-
   return _POSIX_Get_error( status );
 }
diff --git a/cpukit/posix/src/prwlockwrlock.c b/cpukit/posix/src/prwlockwrlock.c
index df4d2685aa..eae10ba375 100644
--- a/cpukit/posix/src/prwlockwrlock.c
+++ b/cpukit/posix/src/prwlockwrlock.c
@@ -35,7 +35,7 @@ int pthread_rwlock_wrlock(
   POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
 
   _Thread_queue_Context_initialize( &queue_context );
-  _Thread_queue_Context_set_no_timeout( &queue_context );
+  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   status = _CORE_RWLock_Seize_for_writing(
     &the_rwlock->RWLock,
     true,          /* do not timeout -- wait forever */
diff --git a/cpukit/posix/src/pthreadjoin.c b/cpukit/posix/src/pthreadjoin.c
index b6981fd9b3..ce4bf0d049 100644
--- a/cpukit/posix/src/pthreadjoin.c
+++ b/cpukit/posix/src/pthreadjoin.c
@@ -40,7 +40,6 @@ static int _POSIX_Threads_Join( pthread_t thread, void **value_ptr )
 
   _Thread_queue_Context_initialize( &queue_context );
   _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-  _Thread_queue_Context_set_no_timeout( &queue_context );
   the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
 
   if ( the_thread == NULL ) {
diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c
index 90e6866341..9e7bb466dd 100644
--- a/cpukit/posix/src/semtimedwait.c
+++ b/cpukit/posix/src/semtimedwait.c
@@ -51,29 +51,16 @@ int sem_timedwait(
     _Sem_Queue_release( sem, level, &queue_context );
     return 0;
   } else {
-    Watchdog_Interval ticks;
-    Status_Control    status;
-
-    switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
-      case TOD_ABSOLUTE_TIMEOUT_INVALID:
-        _Sem_Queue_release( sem, level, &queue_context );
-        rtems_set_errno_and_return_minus_one( EINVAL );
-        break;
-      case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
-      case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
-        _Sem_Queue_release( sem, level, &queue_context );
-        rtems_set_errno_and_return_minus_one( ETIMEDOUT );
-        break;
-      default:
-        break;
-    }
+    Status_Control status;
 
     _Thread_queue_Context_set_thread_state(
       &queue_context,
       STATES_WAITING_FOR_SEMAPHORE
     );
-    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-    _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+    _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+      &queue_context,
+      abstime
+    );
     _Thread_queue_Context_set_ISR_level( &queue_context, level );
     _Thread_queue_Enqueue(
       &sem->Queue.Queue,
diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c
index 70170bf2f7..a0e18adef0 100644
--- a/cpukit/posix/src/sigtimedwait.c
+++ b/cpukit/posix/src/sigtimedwait.c
@@ -24,6 +24,8 @@
 #include <rtems/posix/psignalimpl.h>
 #include <rtems/posix/posixapi.h>
 #include <rtems/score/threadqimpl.h>
+#include <rtems/score/todimpl.h>
+#include <rtems/score/watchdogimpl.h>
 #include <rtems/score/isr.h>
 
 static int _POSIX_signals_Get_lowest(
@@ -89,20 +91,24 @@ int sigtimedwait(
    *        in the Open Group specification.
    */
 
-  if ( timeout ) {
-    Watchdog_Interval interval;
+  if ( timeout != NULL ) {
+    struct timespec end;
 
-    if ( !_Timespec_Is_valid( timeout ) )
-      rtems_set_errno_and_return_minus_one( EINVAL );
+    if ( !_Watchdog_Is_valid_interval_timespec( timeout ) ) {
+      return EINVAL;
+    }
 
-    interval = _Timespec_To_ticks( timeout );
+    _TOD_Get_zero_based_uptime_as_timespec( &end );
 
-    if ( !interval )
-      rtems_set_errno_and_return_minus_one( EINVAL );
+    /* In case this overflows, then the enqueue callout will reject it */
+    _Timespec_Add_to( &end, timeout );
 
-    _Thread_queue_Context_set_relative_timeout( &queue_context, interval );
+    _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
+      &queue_context,
+      &end
+    );
   } else {
-    _Thread_queue_Context_set_no_timeout( &queue_context );
+    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   }
 
   /*
@@ -160,7 +166,6 @@ int sigtimedwait(
     &queue_context,
     STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   _Thread_queue_Enqueue(
     &_POSIX_signals_Wait_queue.Queue,
     POSIX_SIGNALS_TQ_OPERATIONS,
diff --git a/cpukit/rtems/src/barrierwait.c b/cpukit/rtems/src/barrierwait.c
index c0931689c7..4811c218b8 100644
--- a/cpukit/rtems/src/barrierwait.c
+++ b/cpukit/rtems/src/barrierwait.c
@@ -38,7 +38,7 @@ rtems_status_code rtems_barrier_wait(
     return RTEMS_INVALID_ID;
   }
 
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
+  _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
   status = _CORE_barrier_Seize(
     &the_barrier->Barrier,
     _Thread_Executing,
diff --git a/cpukit/rtems/src/msgqreceive.c b/cpukit/rtems/src/msgqreceive.c
index d509faf988..2304be735a 100644
--- a/cpukit/rtems/src/msgqreceive.c
+++ b/cpukit/rtems/src/msgqreceive.c
@@ -61,7 +61,7 @@ rtems_status_code rtems_message_queue_receive(
   );
 
   executing = _Thread_Executing;
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
+  _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
   status = _CORE_message_queue_Seize(
     &the_message_queue->message_queue,
     executing,
diff --git a/cpukit/rtems/src/regiongetsegment.c b/cpukit/rtems/src/regiongetsegment.c
index dfd476ccc0..02acefb004 100644
--- a/cpukit/rtems/src/regiongetsegment.c
+++ b/cpukit/rtems/src/regiongetsegment.c
@@ -27,11 +27,19 @@
 static void _Region_Enqueue_callout(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
   Thread_queue_Context *queue_context
 )
 {
   Region_Control *the_region;
 
+  _Thread_queue_Add_timeout_ticks(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
+
   the_region = REGION_OF_THREAD_QUEUE_QUEUE( queue );
   _Region_Unlock( the_region );
 }
@@ -91,11 +99,11 @@ rtems_status_code rtems_region_get_segment(
         &queue_context,
         STATES_WAITING_FOR_SEGMENT
       );
+      _Thread_queue_Context_set_timeout_ticks( &queue_context, timeout );
       _Thread_queue_Context_set_enqueue_callout(
         &queue_context,
         _Region_Enqueue_callout
       );
-      _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
       _Thread_queue_Enqueue(
         &the_region->Wait_queue.Queue,
         the_region->wait_operations,
diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c
index b81612eaae..db0c3f2e0c 100644
--- a/cpukit/rtems/src/semobtain.c
+++ b/cpukit/rtems/src/semobtain.c
@@ -69,7 +69,11 @@ rtems_status_code rtems_semaphore_obtain(
   executing = _Thread_Executing;
   wait = !_Options_Is_no_wait( option_set );
 
-  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
+  if ( wait ) {
+    _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
+  } else {
+    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
+  }
 
   switch ( the_semaphore->variant ) {
     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index f0c927b294..7ff1f41684 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -305,6 +305,7 @@ libscore_a_SOURCES += src/threadq.c \
     src/threadqextractwithproxy.c src/threadqfirst.c \
     src/threadqflush.c
 libscore_a_SOURCES += src/threadqops.c
+libscore_a_SOURCES += src/threadqtimeout.c
 
 ## TIMESPEC_C_FILES
 libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
@@ -316,7 +317,6 @@ libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
 libscore_a_SOURCES += src/coretod.c src/coretodset.c \
     src/coretodtickspersec.c \
     src/coretodadjust.c
-libscore_a_SOURCES += src/coretodabsolutetimeout.c
 
 ## WATCHDOG_C_FILES
 libscore_a_SOURCES += src/watchdoginsert.c
diff --git a/cpukit/score/include/rtems/score/coresemimpl.h b/cpukit/score/include/rtems/score/coresemimpl.h
index aa053d7acd..00f77e61dd 100644
--- a/cpukit/score/include/rtems/score/coresemimpl.h
+++ b/cpukit/score/include/rtems/score/coresemimpl.h
@@ -188,7 +188,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_semaphore_Seize(
     queue_context,
     STATES_WAITING_FOR_SEMAPHORE
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
   _Thread_queue_Enqueue(
     &the_semaphore->Wait_queue.Queue,
     operations,
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index c4742ba05c..3e618bf5af 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -57,14 +57,16 @@ typedef struct Thread_queue_Operations Thread_queue_Operations;
  *
  * @param[in] queue The actual thread queue.
  * @param[in] the_thread The thread to enqueue.
+ * @param[in] cpu_self The current processor.
  * @param[in] queue_context The thread queue context of the lock acquire.
  *
  * @see _Thread_queue_Context_set_enqueue_callout().
  */
 typedef void ( *Thread_queue_Enqueue_callout )(
-  Thread_queue_Queue   *queue,
-  Thread_Control       *the_thread,
-  Thread_queue_Context *queue_context
+  Thread_queue_Queue     *queue,
+  Thread_Control         *the_thread,
+  struct Per_CPU_Control *cpu_self,
+  Thread_queue_Context   *queue_context
 );
 
 /**
@@ -202,22 +204,31 @@ struct Thread_queue_Context {
    * @brief The enqueue callout for _Thread_queue_Enqueue().
    *
    * The callout is invoked after the release of the thread queue lock with
-   * thread dispatching disabled.  Afterwards the thread is blocked.
+   * thread dispatching disabled.  Afterwards the thread is blocked.  This
+   * callout must be used to install the thread watchdog for timeout handling.
    *
    * @see _Thread_queue_Enqueue_do_nothing_extra().
+   *   _Thread_queue_Add_timeout_ticks(), and
+   *   _Thread_queue_Add_timeout_realtime_timespec().
    */
   Thread_queue_Enqueue_callout enqueue_callout;
 
   /**
-   * @brief The clock discipline for the interval timeout.
-   * Use WATCHDOG_NO_TIMEOUT to block indefinitely.
-   */
-  Watchdog_Discipline timeout_discipline;
-
-  /**
    * @brief Interval to wait.
+   *
+   * May be used by the enqueue callout to register a timeout handler.
    */
-  uint64_t timeout;
+  union {
+    /**
+     * @brief The timeout in ticks.
+     */
+    Watchdog_Interval ticks;
+
+    /**
+     * @brief The timeout argument, e.g. pointer to struct timespec.
+     */
+    const void *arg;
+  } Timeout;
 
 #if defined(RTEMS_SMP)
   /**
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index f74db96129..ecbd8fd42f 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -65,6 +65,28 @@ typedef struct {
 void _Thread_queue_Enqueue_do_nothing_extra(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+);
+
+void _Thread_queue_Add_timeout_ticks(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+);
+
+void _Thread_queue_Add_timeout_monotonic_timespec(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+);
+
+void _Thread_queue_Add_timeout_realtime_timespec(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
   Thread_queue_Context *queue_context
 );
 
@@ -118,6 +140,40 @@ _Thread_queue_Context_set_thread_state(
 }
 
 /**
+ * @brief Sets the timeout ticks in the thread queue context.
+ *
+ * @param queue_context The thread queue context.
+ * @param ticks The timeout in ticks.
+ *
+ * @see _Thread_queue_Enqueue().
+ */
+RTEMS_INLINE_ROUTINE void
+_Thread_queue_Context_set_timeout_ticks(
+  Thread_queue_Context *queue_context,
+  Watchdog_Interval     ticks
+)
+{
+  queue_context->Timeout.ticks = ticks;
+}
+
+/**
+ * @brief Sets the timeout argument in the thread queue context.
+ *
+ * @param queue_context The thread queue context.
+ * @param arg The timeout argument.
+ *
+ * @see _Thread_queue_Enqueue().
+ */
+RTEMS_INLINE_ROUTINE void
+_Thread_queue_Context_set_timeout_argument(
+  Thread_queue_Context *queue_context,
+  const void           *arg
+)
+{
+  queue_context->Timeout.arg = arg;
+}
+
+/**
  * @brief Sets the enqueue callout in the thread queue context.
  *
  * @param queue_context The thread queue context.
@@ -150,55 +206,61 @@ _Thread_queue_Context_set_enqueue_do_nothing_extra(
 }
 
 /**
- * @brief Sets an indefinite timeout interval in the thread queue context.
+ * @brief Sets the enqueue callout to add a relative monotonic timeout in
+ * ticks.
  *
  * @param queue_context The thread queue context.
- * @param timeout The new timeout.
+ * @param ticks The timeout in ticks.
  *
  * @see _Thread_queue_Enqueue().
  */
 RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_no_timeout(
-  Thread_queue_Context *queue_context
+_Thread_queue_Context_set_enqueue_timeout_ticks(
+  Thread_queue_Context *queue_context,
+  Watchdog_Interval     ticks
 )
 {
-  queue_context->timeout_discipline = WATCHDOG_NO_TIMEOUT;
+  queue_context->Timeout.ticks = ticks;
+  queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks;
 }
 
 /**
- * @brief Sets a relative timeout in the thread queue context.
+ * @brief Sets the enqueue callout to add an absolute monotonic timeout in
+ * timespec format.
  *
  * @param queue_context The thread queue context.
- * @param discipline The clock discipline to use for the timeout.
+ * @param abstime The absolute monotonic timeout.
  *
  * @see _Thread_queue_Enqueue().
  */
 RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_relative_timeout(
-  Thread_queue_Context *queue_context,
-  Watchdog_Interval     timeout
+_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
+  Thread_queue_Context  *queue_context,
+  const struct timespec *abstime
 )
 {
-  queue_context->timeout_discipline = WATCHDOG_RELATIVE;
-  queue_context->timeout = timeout;
+  queue_context->Timeout.arg = abstime;
+  queue_context->enqueue_callout =
+    _Thread_queue_Add_timeout_monotonic_timespec;
 }
 
 /**
- * @brief Sets an absolute timeout in the thread queue context.
+ * @brief Sets the enqueue callout to add an absolute realtime timeout in
+ * timespec format.
  *
  * @param queue_context The thread queue context.
- * @param discipline The clock discipline to use for the timeout.
+ * @param abstime The absolute realtime timeout.
  *
  * @see _Thread_queue_Enqueue().
  */
 RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_absolute_timeout(
-  Thread_queue_Context *queue_context,
-  uint64_t              timeout
+_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+  Thread_queue_Context  *queue_context,
+  const struct timespec *abstime
 )
 {
-  queue_context->timeout_discipline = WATCHDOG_ABSOLUTE;
-  queue_context->timeout = timeout;
+  queue_context->Timeout.arg = abstime;
+  queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec;
 }
 
 /**
@@ -615,11 +677,10 @@ Thread_Control *_Thread_queue_Do_dequeue(
  * - _Thread_queue_Context_set_thread_state(),
  *
  * - _Thread_queue_Context_set_enqueue_callout() or
- *   _Thread_queue_Context_set_enqueue_do_nothing_extra(),
- *
- * - _Thread_queue_Context_set_no_timeout() or
- *   _Thread_queue_Context_set_relative_timeout() or
- *   _Thread_queue_Context_set_absolute_timeout(), and
+ *   _Thread_queue_Context_set_enqueue_do_nothing_extra() or
+ *   _Thread_queue_Context_set_enqueue_timeout_ticks() or
+ *   _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or
+ *   _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(),
  *
  * - _Thread_queue_Context_set_deadlock_callout().
  *
@@ -652,7 +713,6 @@ Thread_Control *_Thread_queue_Do_dequeue(
  *       STATES_WAITING_FOR_MUTEX
  *     );
  *     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
- *     _Thread_queue_Context_set_no_timeout( &queue_context );
  *     _Thread_queue_Context_set_deadlock_callout(
  *       queue_context,
  *       _Thread_queue_Deadlock_fatal
diff --git a/cpukit/score/include/rtems/score/todimpl.h b/cpukit/score/include/rtems/score/todimpl.h
index de4dc93430..e3a1a8f58c 100644
--- a/cpukit/score/include/rtems/score/todimpl.h
+++ b/cpukit/score/include/rtems/score/todimpl.h
@@ -298,46 +298,6 @@ RTEMS_INLINE_ROUTINE bool _TOD_Is_set( void )
   return _TOD.is_set;
 }
 
-/**
- * @brief 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 for example.
- */
-typedef enum {
-  /** The timeout is invalid. */
-  TOD_ABSOLUTE_TIMEOUT_INVALID,
-  /** The timeout represents a time that is in the past. */
-  TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST,
-  /** The timeout represents a time that is equal to the current time. */
-  TOD_ABSOLUTE_TIMEOUT_IS_NOW,
-  /** The timeout represents a time that is in the future. */
-  TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
-} TOD_Absolute_timeout_conversion_results;
-
-/**
- * @brief 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.
- *
- * @param[in] abstime is a pointer to the timeout
- * @param[in] clock is the time source to use for the timeout
- * @param[out] ticks_out will contain the number of ticks
- *
- * @return 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.
- */
-TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
-  const struct timespec *abstime,
-  clockid_t              clock,
-  Watchdog_Interval     *ticks_out
-);
-
 /**@}*/
 
 #ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
index a379bf7a23..dbb092bbef 100644
--- a/cpukit/score/include/rtems/score/watchdog.h
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -53,36 +53,9 @@ typedef struct Watchdog_Control Watchdog_Control;
 typedef uint32_t   Watchdog_Interval;
 
 /**
- *  @brief The clock discipline to use for the Watchdog timeout interval.
+ * @brief Special watchdog ticks value to indicate an infinite wait.
  */
-typedef enum {
-
-  /**
-   * @brief Indefinite wait.
-   *
-   * This is to indicate there is no timeout and not to use a watchdog. It
-   * must be equal to 0, which is an illegal relative clock interval, so that
-   * it may be used as a Watchdog_Interval value with WATCHDOG_RELATIVE to
-   * express an indefinite wait.
-   */
-  WATCHDOG_NO_TIMEOUT = 0,
-
-  /**
-   * @brief Relative clock.
-   *
-   * The reference time point for the watchdog is current ticks value
-   * during insert.  Time is measured in clock ticks.
-   */
-  WATCHDOG_RELATIVE,
-
-  /**
-   * @brief Absolute clock.
-   *
-   * The reference time point for this header is the POSIX Epoch.  Time is
-   * measured in nanoseconds since POSIX Epoch.
-   */
-  WATCHDOG_ABSOLUTE
-} Watchdog_Discipline;
+#define WATCHDOG_NO_TIMEOUT 0
 
 /**
  *  @brief Return type from a Watchdog Service Routine.
diff --git a/cpukit/score/include/rtems/score/watchdogimpl.h b/cpukit/score/include/rtems/score/watchdogimpl.h
index 1fa67f3961..7866c0ce44 100644
--- a/cpukit/score/include/rtems/score/watchdogimpl.h
+++ b/cpukit/score/include/rtems/score/watchdogimpl.h
@@ -284,6 +284,11 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
   }
 }
 
+/**
+ * @brief The maximum watchdog ticks value for the far future.
+ */
+#define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
+
 #define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
 
 /**
diff --git a/cpukit/score/src/apimutexlock.c b/cpukit/score/src/apimutexlock.c
index 879562d9f0..312dcc2993 100644
--- a/cpukit/score/src/apimutexlock.c
+++ b/cpukit/score/src/apimutexlock.c
@@ -33,7 +33,7 @@ void _API_Mutex_Lock( API_Mutex_Control *the_mutex )
 
   _Thread_queue_Context_initialize( &queue_context );
   _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
-  _Thread_queue_Context_set_no_timeout( &queue_context );
+  _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   _CORE_recursive_mutex_Seize(
     &the_mutex->Mutex,
     CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
diff --git a/cpukit/score/src/condition.c b/cpukit/score/src/condition.c
index bbbeb901db..9913d86d34 100644
--- a/cpukit/score/src/condition.c
+++ b/cpukit/score/src/condition.c
@@ -84,16 +84,38 @@ typedef struct {
   struct _Mutex_Control *mutex;
 } Condition_Enqueue_context;
 
-static void _Condition_Enqueue_callout(
+static void _Condition_Mutex_release( Thread_queue_Context *queue_context )
+{
+  Condition_Enqueue_context *context;
+
+  context = (Condition_Enqueue_context *) queue_context;
+  _Mutex_Release( context->mutex );
+}
+
+static void _Condition_Enqueue_no_timeout(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
   Thread_queue_Context *queue_context
 )
 {
-  Condition_Enqueue_context *context;
+  _Condition_Mutex_release( queue_context );
+}
 
-  context = (Condition_Enqueue_context *) queue_context;
-  _Mutex_Release( context->mutex );
+static void _Condition_Enqueue_with_timeout(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  _Thread_queue_Add_timeout_realtime_timespec(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
+  _Condition_Mutex_release( queue_context );
 }
 
 static Thread_Control *_Condition_Do_wait(
@@ -107,15 +129,12 @@ static Thread_Control *_Condition_Do_wait(
 
   context->mutex = _mutex;
   condition = _Condition_Get( _condition );
+  _ISR_lock_ISR_disable( &context->Base.Lock_context.Lock_context );
   executing = _Condition_Queue_acquire_critical( condition, &context->Base );
   _Thread_queue_Context_set_thread_state(
     &context->Base,
     STATES_WAITING_FOR_CONDITION_VARIABLE
   );
-  _Thread_queue_Context_set_enqueue_callout(
-    &context->Base,
-    _Condition_Enqueue_callout
-  );
   _Thread_queue_Enqueue(
     &condition->Queue.Queue,
     CONDITION_TQ_OPERATIONS,
@@ -134,8 +153,10 @@ void _Condition_Wait(
   Condition_Enqueue_context context;
 
   _Thread_queue_Context_initialize( &context.Base );
-  _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-  _Thread_queue_Context_set_no_timeout( &context.Base );
+  _Thread_queue_Context_set_enqueue_callout(
+    &context.Base,
+    _Condition_Enqueue_no_timeout
+  );
   _Condition_Do_wait( _condition, _mutex, &context );
   _Mutex_Acquire( _mutex );
 }
@@ -149,24 +170,13 @@ int _Condition_Wait_timed(
   Condition_Enqueue_context  context;
   Thread_Control            *executing;
   int                        eno;
-  Watchdog_Interval          ticks;
 
   _Thread_queue_Context_initialize( &context.Base );
-  _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-
-  switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
-    case TOD_ABSOLUTE_TIMEOUT_INVALID:
-      _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
-      return EINVAL;
-    case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
-    case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
-      _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
-      return ETIMEDOUT;
-    default:
-      break;
-  }
-
-  _Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
+  _Thread_queue_Context_set_enqueue_callout(
+    &context.Base,
+    _Condition_Enqueue_with_timeout
+  );
+  _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
   executing = _Condition_Do_wait( _condition, _mutex, &context );
   eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
   _Mutex_Acquire( _mutex );
@@ -195,8 +205,10 @@ void _Condition_Wait_recursive(
   unsigned int              nest_level;
 
   _Thread_queue_Context_initialize( &context.Base );
-  _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-  _Thread_queue_Context_set_no_timeout( &context.Base );
+  _Thread_queue_Context_set_enqueue_callout(
+    &context.Base,
+    _Condition_Enqueue_no_timeout
+  );
   nest_level = _Condition_Unnest_mutex( _mutex );
   _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
   _Mutex_recursive_Acquire( _mutex );
@@ -213,23 +225,13 @@ int _Condition_Wait_recursive_timed(
   Thread_Control            *executing;
   int                        eno;
   unsigned int               nest_level;
-  Watchdog_Interval          ticks;
 
   _Thread_queue_Context_initialize( &context.Base );
-  _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-
-  switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
-    case TOD_ABSOLUTE_TIMEOUT_INVALID:
-      _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
-      return EINVAL;
-    case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
-    case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
-      _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
-      return ETIMEDOUT;
-    default:
-      break;
-  }
-  _Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
+  _Thread_queue_Context_set_enqueue_callout(
+    &context.Base,
+    _Condition_Enqueue_with_timeout
+  );
+  _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
   nest_level = _Condition_Unnest_mutex( _mutex );
   executing = _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
   eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c
index 5093e02bc0..08acce9d86 100644
--- a/cpukit/score/src/corebarrierwait.c
+++ b/cpukit/score/src/corebarrierwait.c
@@ -48,7 +48,6 @@ Status_Control _CORE_barrier_Seize(
       queue_context,
       STATES_WAITING_FOR_BARRIER
     );
-    _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
     _Thread_queue_Enqueue(
       &the_barrier->Wait_queue.Queue,
       CORE_BARRIER_TQ_OPERATIONS,
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
index 5d0b95b9e5..e3d8842831 100644
--- a/cpukit/score/src/coremsgseize.c
+++ b/cpukit/score/src/coremsgseize.c
@@ -117,7 +117,6 @@ Status_Control _CORE_message_queue_Seize(
     queue_context,
     STATES_WAITING_FOR_MESSAGE
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
   _Thread_queue_Enqueue(
     &the_message_queue->Wait_queue.Queue,
     the_message_queue->operations,
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
index 6040f76eb3..49c90256cd 100644
--- a/cpukit/score/src/coremsgsubmit.c
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -135,7 +135,6 @@ Status_Control _CORE_message_queue_Submit(
       queue_context,
       STATES_WAITING_FOR_MESSAGE
     );
-    _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
     _Thread_queue_Enqueue(
       &the_message_queue->Wait_queue.Queue,
       the_message_queue->operations,
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
index 173c495d3c..e07458573d 100644
--- a/cpukit/score/src/coremutexseize.c
+++ b/cpukit/score/src/coremutexseize.c
@@ -36,7 +36,6 @@ Status_Control _CORE_mutex_Seize_slow(
       queue_context,
       STATES_WAITING_FOR_MUTEX
     );
-    _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
     _Thread_queue_Context_set_deadlock_callout(
       queue_context,
       _Thread_queue_Deadlock_status
diff --git a/cpukit/score/src/corerwlockobtainread.c b/cpukit/score/src/corerwlockobtainread.c
index 88853ebfb3..6969486f28 100644
--- a/cpukit/score/src/corerwlockobtainread.c
+++ b/cpukit/score/src/corerwlockobtainread.c
@@ -77,7 +77,6 @@ Status_Control _CORE_RWLock_Seize_for_reading(
     queue_context,
    STATES_WAITING_FOR_RWLOCK
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
   _Thread_queue_Enqueue(
      &the_rwlock->Queue.Queue,
      CORE_RWLOCK_TQ_OPERATIONS,
diff --git a/cpukit/score/src/corerwlockobtainwrite.c b/cpukit/score/src/corerwlockobtainwrite.c
index 6145fc3c4c..7b296169d9 100644
--- a/cpukit/score/src/corerwlockobtainwrite.c
+++ b/cpukit/score/src/corerwlockobtainwrite.c
@@ -71,7 +71,6 @@ Status_Control _CORE_RWLock_Seize_for_writing(
     queue_context,
     STATES_WAITING_FOR_RWLOCK
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
   _Thread_queue_Enqueue(
      &the_rwlock->Queue.Queue,
      CORE_RWLOCK_TQ_OPERATIONS,
diff --git a/cpukit/score/src/coretodabsolutetimeout.c b/cpukit/score/src/coretodabsolutetimeout.c
deleted file mode 100644
index d67b7c33c7..0000000000
--- a/cpukit/score/src/coretodabsolutetimeout.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file
- *
- * @brief Convert Absolute Timeout to Ticks
- * @ingroup ScoreTOD
- */
-
-/*
- *  COPYRIGHT (c) 1989-2008.
- *  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.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/todimpl.h>
-
-/*
- *  The abstime is a walltime.  We turn it into an interval.
- */
-TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
-  const struct timespec *abstime,
-  clockid_t              clock,
-  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 TOD_ABSOLUTE_TIMEOUT_INVALID;
-
-  /*
-   *  Is the absolute time in the past?
-   */
-  if ( clock == CLOCK_REALTIME ) {
-    _TOD_Get( &current_time );
-  } else {
-    _Assert( clock == CLOCK_MONOTONIC );
-    _TOD_Get_zero_based_uptime_as_timespec( &current_time );
-  }
-
-  if ( _Timespec_Less_than( abstime, &current_time ) )
-    return TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST;
-
-  /*
-   *  How long until the requested absolute time?
-   */
-  _Timespec_Subtract( &current_time, abstime, &difference );
-
-  /*
-   *  Internally the SuperCore uses ticks, so convert to them.
-   */
-  *ticks_out = _Timespec_To_ticks( &difference );
-
-  /*
-   *  If the difference was 0, then the future is now.  It is so bright
-   *  we better wear shades.
-   */
-  if ( !*ticks_out )
-    return TOD_ABSOLUTE_TIMEOUT_IS_NOW;
-
-  /*
-   *  This is the case we were expecting and it took this long to
-   *  get here.
-   */
-  return TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
-}
-
diff --git a/cpukit/score/src/futex.c b/cpukit/score/src/futex.c
index c5b4f197c3..6487882819 100644
--- a/cpukit/score/src/futex.c
+++ b/cpukit/score/src/futex.c
@@ -95,7 +95,6 @@ int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
       STATES_WAITING_FOR_FUTEX
     );
     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-    _Thread_queue_Context_set_no_timeout( &queue_context );
     _Thread_queue_Context_set_ISR_level( &queue_context, level );
     _Thread_queue_Enqueue(
       &futex->Queue.Queue,
diff --git a/cpukit/score/src/mutex.c b/cpukit/score/src/mutex.c
index 1c793ad633..e2f5bb52fc 100644
--- a/cpukit/score/src/mutex.c
+++ b/cpukit/score/src/mutex.c
@@ -102,7 +102,6 @@ static void _Mutex_Acquire_slow(
     queue_context,
     STATES_WAITING_FOR_MUTEX
   );
-  _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
   _Thread_queue_Context_set_deadlock_callout(
     queue_context,
     _Thread_queue_Deadlock_fatal
@@ -163,7 +162,7 @@ void _Mutex_Acquire( struct _Mutex_Control *_mutex )
     _Thread_Resource_count_increment( executing );
     _Mutex_Queue_release( mutex, level, &queue_context );
   } else {
-    _Thread_queue_Context_set_no_timeout( &queue_context );
+    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
     _Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
   }
 }
@@ -193,21 +192,10 @@ int _Mutex_Acquire_timed(
 
     return 0;
   } else {
-    Watchdog_Interval ticks;
-
-    switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
-      case TOD_ABSOLUTE_TIMEOUT_INVALID:
-        _Mutex_Queue_release( mutex, level, &queue_context );
-        return EINVAL;
-      case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
-      case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
-        _Mutex_Queue_release( mutex, level, &queue_context );
-        return ETIMEDOUT;
-      default:
-        break;
-    }
-
-    _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+    _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+      &queue_context,
+      abstime
+    );
     _Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
 
     return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
@@ -290,7 +278,7 @@ void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
     ++mutex->nest_level;
     _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
   } else {
-    _Thread_queue_Context_set_no_timeout( &queue_context );
+    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
     _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
   }
 }
@@ -325,21 +313,10 @@ int _Mutex_recursive_Acquire_timed(
 
     return 0;
   } else {
-    Watchdog_Interval ticks;
-
-    switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
-      case TOD_ABSOLUTE_TIMEOUT_INVALID:
-        _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
-        return EINVAL;
-      case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
-      case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
-        _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
-        return ETIMEDOUT;
-      default:
-        break;
-    }
-
-    _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+    _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+      &queue_context,
+      abstime
+    );
     _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
 
     return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c
index a912fbc4d2..4edd25a387 100644
--- a/cpukit/score/src/semaphore.c
+++ b/cpukit/score/src/semaphore.c
@@ -61,7 +61,6 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem )
       STATES_WAITING_FOR_SEMAPHORE
     );
     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
-    _Thread_queue_Context_set_no_timeout( &queue_context );
     _Thread_queue_Context_set_ISR_level( &queue_context, level );
     _Thread_queue_Enqueue(
       &sem->Queue.Queue,
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 40fb69bbd3..62d3671222 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -359,6 +359,7 @@ bool _Thread_queue_Path_acquire_critical(
 void _Thread_queue_Enqueue_do_nothing_extra(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
   Thread_queue_Context *queue_context
 )
 {
@@ -375,36 +376,6 @@ void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread )
   _Internal_error( INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK );
 }
 
-static void _Thread_queue_Timeout(
-  Thread_Control       *the_thread,
-  Per_CPU_Control      *cpu_self,
-  Thread_queue_Context *queue_context
-)
-{
-  switch ( queue_context->timeout_discipline ) {
-    case WATCHDOG_RELATIVE:
-      /* A relative timeout of 0 is a special case indefinite (no) timeout */
-      if ( queue_context->timeout != 0 ) {
-        _Thread_Add_timeout_ticks(
-          the_thread,
-          cpu_self,
-          (Watchdog_Interval) queue_context->timeout
-        );
-      }
-      break;
-    case WATCHDOG_ABSOLUTE:
-      _Thread_Timer_insert_realtime(
-        the_thread,
-        cpu_self,
-        _Thread_Timeout,
-        queue_context->timeout
-      );
-      break;
-    default:
-      break;
-  }
-}
-
 void _Thread_queue_Enqueue(
   Thread_queue_Queue            *queue,
   const Thread_queue_Operations *operations,
@@ -416,7 +387,6 @@ void _Thread_queue_Enqueue(
   bool             success;
 
   _Assert( queue_context->enqueue_callout != NULL );
-  _Assert( (uint8_t) queue_context->timeout_discipline != 0x7f );
 
 #if defined(RTEMS_MULTIPROCESSING)
   if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
@@ -447,7 +417,12 @@ void _Thread_queue_Enqueue(
   cpu_self = _Thread_queue_Dispatch_disable( queue_context );
   _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
 
-  ( *queue_context->enqueue_callout )( queue, the_thread, queue_context );
+  ( *queue_context->enqueue_callout )(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
 
   /*
    *  Set the blocking state for this thread queue in the thread.
@@ -455,11 +430,6 @@ void _Thread_queue_Enqueue(
   _Thread_Set_state( the_thread, queue_context->thread_state );
 
   /*
-   *  If the thread wants to timeout, then schedule its timer.
-   */
-  _Thread_queue_Timeout( the_thread, cpu_self, queue_context );
-
-  /*
    * At this point thread dispatching is disabled, however, we already released
    * the thread queue lock.  Thus, interrupts or threads on other processors
    * may already changed our state with respect to the thread queue object.
@@ -491,6 +461,8 @@ Status_Control _Thread_queue_Enqueue_sticky(
 {
   Per_CPU_Control *cpu_self;
 
+  _Assert( queue_context->enqueue_callout != NULL );
+
   _Thread_Wait_claim( the_thread, queue );
 
   if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
@@ -519,7 +491,13 @@ Status_Control _Thread_queue_Enqueue_sticky(
     );
   }
 
-  _Thread_queue_Timeout( the_thread, cpu_self, queue_context );
+  ( *queue_context->enqueue_callout )(
+    queue,
+    the_thread,
+    cpu_self,
+    queue_context
+  );
+
   _Thread_Priority_update( queue_context );
   _Thread_Priority_and_sticky_update( the_thread, 1 );
   _Thread_Dispatch_enable( cpu_self );
diff --git a/cpukit/score/src/threadqtimeout.c b/cpukit/score/src/threadqtimeout.c
new file mode 100644
index 0000000000..3f052fcf6f
--- /dev/null
+++ b/cpukit/score/src/threadqtimeout.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016, 2017 embedded brains GmbH
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/threadqimpl.h>
+#include <rtems/score/threadimpl.h>
+#include <rtems/score/watchdogimpl.h>
+
+void _Thread_queue_Add_timeout_ticks(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  Watchdog_Interval ticks;
+
+  ticks = queue_context->Timeout.ticks;
+
+  if ( ticks != WATCHDOG_NO_TIMEOUT ) {
+    _Thread_Add_timeout_ticks(
+      the_thread,
+      cpu_self,
+      queue_context->Timeout.ticks
+    );
+  }
+}
+
+static bool _Thread_queue_Lazy_insert_monotonic_timespec(
+  Thread_Control        *the_thread,
+  Per_CPU_Control       *cpu_self,
+  const struct timespec *abstime
+)
+{
+  uint64_t         expire;
+  ISR_lock_Context lock_context;
+  bool             insert;
+
+  if ( abstime->tv_sec < 0 ) {
+    expire = 0;
+  } else if ( _Watchdog_Is_far_future_monotonic_timespec( abstime ) ) {
+    expire = WATCHDOG_MAXIMUM_TICKS;
+  } else {
+    expire = _Watchdog_Monotonic_from_timespec( abstime );
+  }
+
+  _ISR_lock_ISR_disable_and_acquire(
+    &the_thread->Timer.Lock,
+    &lock_context
+  );
+
+  the_thread->Timer.header =
+    &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ];
+  the_thread->Timer.Watchdog.routine = _Thread_Timeout;
+  insert = _Watchdog_Per_CPU_lazy_insert_monotonic(
+    &the_thread->Timer.Watchdog,
+    cpu_self,
+    expire
+  );
+
+  _ISR_lock_Release_and_ISR_enable(
+    &the_thread->Timer.Lock,
+    &lock_context
+  );
+  return insert;
+}
+
+void _Thread_queue_Add_timeout_monotonic_timespec(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  const struct timespec *abstime;
+
+  abstime = queue_context->Timeout.arg;
+
+  if ( _Watchdog_Is_valid_timespec( abstime ) ) {
+    if (
+      !_Thread_queue_Lazy_insert_monotonic_timespec(
+        the_thread,
+        cpu_self,
+        abstime
+      )
+    ) {
+      _Thread_Continue( the_thread, STATUS_TIMEOUT );
+    }
+  } else {
+    _Thread_Continue( the_thread, STATUS_INVALID_NUMBER );
+  }
+}
+
+void _Thread_queue_Add_timeout_realtime_timespec(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
+  Thread_queue_Context *queue_context
+)
+{
+  const struct timespec *abstime;
+
+  abstime = queue_context->Timeout.arg;
+
+  if ( _Watchdog_Is_valid_timespec( abstime ) ) {
+    uint64_t        expire;
+    struct timespec now;
+
+    if ( abstime->tv_sec < 0 ) {
+      expire = 0;
+    } else if ( _Watchdog_Is_far_future_realtime_timespec( abstime ) ) {
+      expire = WATCHDOG_MAXIMUM_TICKS;
+    } else {
+      expire = _Watchdog_Realtime_from_timespec( abstime );
+    }
+
+    _Timecounter_Getnanotime( &now );
+
+    if ( expire > _Watchdog_Realtime_from_timespec( &now ) ) {
+      ISR_lock_Context lock_context;
+
+      _ISR_lock_ISR_disable_and_acquire(
+        &the_thread->Timer.Lock,
+        &lock_context
+      );
+
+      the_thread->Timer.header =
+        &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
+      the_thread->Timer.Watchdog.routine = _Thread_Timeout;
+      _Watchdog_Per_CPU_insert_realtime(
+        &the_thread->Timer.Watchdog,
+        cpu_self,
+        expire
+      );
+
+      _ISR_lock_Release_and_ISR_enable(
+        &the_thread->Timer.Lock,
+        &lock_context
+      );
+    } else {
+      _Thread_Continue( the_thread, STATUS_TIMEOUT );
+    }
+  } else {
+    _Thread_Continue( the_thread, STATUS_INVALID_NUMBER );
+  }
+}
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 7ee1f880c4..0430ca0407 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -514,6 +514,7 @@ void _Thread_Cancel(
 static void _Thread_Close_enqueue_callout(
   Thread_queue_Queue   *queue,
   Thread_Control       *the_thread,
+  Per_CPU_Control      *cpu_self,
   Thread_queue_Context *queue_context
 )
 {
@@ -534,7 +535,6 @@ void _Thread_Close(
     &context->Base,
     _Thread_Close_enqueue_callout
   );
-  _Thread_queue_Context_set_no_timeout( &context->Base );
   _Thread_State_acquire_critical(
     the_thread,
     &context->Base.Lock_context.Lock_context
-- 
2.12.3




More information about the devel mailing list