You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/07/27 23:40:07 UTC

[incubator-nuttx] branch master updated: Implement proposed POSIX _clockwait variants of existing _timedwait functions

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 33ec242  Implement proposed POSIX _clockwait variants of existing _timedwait functions
33ec242 is described below

commit 33ec242caf325f22421c956f8e8b1c2ef97077c9
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Mon Jul 27 13:46:03 2020 +0800

    Implement proposed POSIX _clockwait variants of existing _timedwait functions
    
    Here is the related glibc patchset:
    https://patchwork.ozlabs.org/project/glibc/cover/cover.b0c66849a87ca79889a49f2f1f2563b1a8a15d8b.1551291557.git-series.mac@mcrowe.com/
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
    Change-Id: I0095cb34cef3d0d88a100255053da79266b73ff2
---
 include/nuttx/semaphore.h                          |  84 ++++++++++-
 include/pthread.h                                  |  11 ++
 include/semaphore.h                                |   7 +-
 include/sys/syscall_lookup.h                       |   3 +-
 libs/libc/pthread/Make.defs                        |   2 +-
 libs/libc/pthread/pthread_condtimedwait.c          |  57 ++++++++
 libs/libc/pthread/pthread_rwlock_rdlock.c          |  13 +-
 libs/libc/pthread/pthread_rwlock_wrlock.c          |  13 +-
 sched/pthread/Make.defs                            |   2 +-
 ...ead_condtimedwait.c => pthread_condclockwait.c} |  14 +-
 sched/semaphore/Make.defs                          |   4 +-
 .../semaphore/{sem_timedwait.c => sem_clockwait.c} |  23 +--
 sched/semaphore/sem_timedwait.c                    | 155 +--------------------
 syscall/syscall.csv                                |   3 +-
 14 files changed, 211 insertions(+), 180 deletions(-)

diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h
index 70b76e4..53c2783 100644
--- a/include/nuttx/semaphore.h
+++ b/include/nuttx/semaphore.h
@@ -65,6 +65,7 @@
 #  define _SEM_WAIT(s)          nxsem_wait(s)
 #  define _SEM_TRYWAIT(s)       nxsem_trywait(s)
 #  define _SEM_TIMEDWAIT(s,t)   nxsem_timedwait(s,t)
+#  define _SEM_CLOCKWAIT(s,c,t) nxsem_clockwait(s,c,t)
 #  define _SEM_POST(s)          nxsem_post(s)
 #  define _SEM_GETVALUE(s)      nxsem_get_value(s)
 #  define _SEM_GETPROTOCOL(s,p) nxsem_get_protocol(s,p)
@@ -77,6 +78,7 @@
 #  define _SEM_WAIT(s)          sem_wait(s)
 #  define _SEM_TRYWAIT(s)       sem_trywait(s)
 #  define _SEM_TIMEDWAIT(s,t)   sem_timedwait(s,t)
+#  define _SEM_CLOCKWAIT(s,c,t) sem_clockwait(s,c,t)
 #  define _SEM_GETVALUE(s,v)    sem_getvalue(s,v)
 #  define _SEM_POST(s)          sem_post(s)
 #  define _SEM_GETPROTOCOL(s,p) sem_getprotocol(s,p)
@@ -278,10 +280,57 @@ int nxsem_trywait(FAR sem_t *sem);
  *
  ****************************************************************************/
 
-struct timespec; /* Forward reference */
 int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime);
 
 /****************************************************************************
+ * Name: nxsem_clockwait
+ *
+ * Description:
+ *   This function will lock the semaphore referenced by sem as in the
+ *   sem_wait() function. However, if the semaphore cannot be locked without
+ *   waiting for another process or thread to unlock the semaphore by
+ *   performing a sem_post() function, this wait will be terminated when the
+ *   specified timeout expires.
+ *
+ *   The timeout will expire when the absolute time specified by abstime
+ *   passes, as measured by the clock on which timeouts are based (that is,
+ *   when the value of that clock equals or exceeds abstime), or if the
+ *   absolute time specified by abstime has already been passed at the
+ *   time of the call.
+ *
+ *   This is an internal OS interface.  It is functionally equivalent to
+ *   sem_wait except that:
+ *
+ *   - It is not a cancellation point, and
+ *   - It does not modify the errno value.
+ *
+ * Input Parameters:
+ *   sem     - Semaphore object
+ *   clockid - The timing source to use in the conversion
+ *   abstime - The absolute time to wait until a timeout is declared.
+ *
+ * Returned Value:
+ *   This is an internal OS interface and should not be used by applications.
+ *   It follows the NuttX internal error return policy:  Zero (OK) is
+ *   returned on success.  A negated errno value is returned on failure.
+ *   That may be one of:
+ *
+ *   EINVAL    The sem argument does not refer to a valid semaphore.  Or the
+ *             thread would have blocked, and the abstime parameter specified
+ *             a nanoseconds field value less than zero or greater than or
+ *             equal to 1000 million.
+ *   ETIMEDOUT The semaphore could not be locked before the specified timeout
+ *             expired.
+ *   EDEADLK   A deadlock condition was detected.
+ *   EINTR     A signal interrupted this function.
+ *   ECANCELED May be returned if the thread is canceled while waiting.
+ *
+ ****************************************************************************/
+
+int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
+                    FAR const struct timespec *abstime);
+
+/****************************************************************************
  * Name: nxsem_tickwait
  *
  * Description:
@@ -569,6 +618,39 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
                                     FAR const struct timespec *abstime);
 
 /****************************************************************************
+ * Name: nxsem_clockwait_uninterruptible
+ *
+ * Description:
+ *   This function is wrapped version of nxsem_timedwait(), which is
+ *   uninterruptible and convenient for use.
+ *
+ * Input Parameters:
+ *   sem     - Semaphore object
+ *   clockid - The timing source to use in the conversion
+ *   abstime - The absolute time to wait until a timeout is declared.
+ *
+ * Returned Value:
+ *   EINVAL    The sem argument does not refer to a valid semaphore.  Or the
+ *             thread would have blocked, and the abstime parameter specified
+ *             a nanoseconds field value less than zero or greater than or
+ *             equal to 1000 million.
+ *   ETIMEDOUT The semaphore could not be locked before the specified timeout
+ *             expired.
+ *   EDEADLK   A deadlock condition was detected.
+ *   ECANCELED May be returned if the thread is canceled while waiting.
+ *
+ * NOTE:  It is essential that callers of this function handle the
+ * ECANCELED error.  Correct handling is that the function should return the
+ * error and the error should propagate back up the calling tree to the
+ * cancellation point interface function where the thread termination will
+ * be handled gracefully
+ *
+ ****************************************************************************/
+
+int nxsem_clockwait_uninterruptible(FAR sem_t *sem, clockid_t clockid,
+                                    FAR const struct timespec *abstime);
+
+/****************************************************************************
  * Name: nxsem_tickwait_uninterruptible
  *
  * Description:
diff --git a/include/pthread.h b/include/pthread.h
index 6ff5cd8..ccc6ade 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -629,6 +629,11 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
                            FAR pthread_mutex_t *mutex,
                            FAR const struct timespec *abstime);
 
+int pthread_cond_clockwait(FAR pthread_cond_t *cond,
+                           FAR pthread_mutex_t *mutex,
+                           clockid_t clockid,
+                           FAR const struct timespec *abstime);
+
 /* Barrier attributes */
 
 int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
@@ -659,10 +664,16 @@ int pthread_rwlock_init(FAR pthread_rwlock_t *rw_lock,
 int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
 int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *lock,
                                FAR const struct timespec *abstime);
+int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t *lock,
+                               clockid_t clockid,
+                               FAR const struct timespec *abstime);
 int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *lock);
 int pthread_rwlock_wrlock(FAR pthread_rwlock_t *lock);
 int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *lock,
                                FAR const struct timespec *abstime);
+int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t *lock,
+                               clockid_t clockid,
+                               FAR const struct timespec *abstime);
 int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *lock);
 int pthread_rwlock_unlock(FAR pthread_rwlock_t *lock);
 
diff --git a/include/semaphore.h b/include/semaphore.h
index 9a87461..4ac0627 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -44,6 +44,7 @@
 
 #include <stdint.h>
 #include <limits.h>
+#include <time.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -88,6 +89,7 @@ struct sem_s
 {
   volatile int16_t semcount;     /* >0 -> Num counts available */
                                  /* <0 -> Num tasks waiting for semaphore */
+
   /* If priority inheritance is enabled, then we have to keep track of which
    * tasks hold references to the semaphore.
    */
@@ -134,9 +136,6 @@ extern "C"
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
-/* Forward references needed by some prototypes */
-
-struct timespec; /* Defined in time.h */
 
 /* Counting Semaphore Interfaces (based on POSIX APIs) */
 
@@ -144,6 +143,8 @@ int        sem_init(FAR sem_t *sem, int pshared, unsigned int value);
 int        sem_destroy(FAR sem_t *sem);
 int        sem_wait(FAR sem_t *sem);
 int        sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime);
+int        sem_clockwait(FAR sem_t *sem, clockid_t clockid,
+                         FAR const struct timespec *abstime);
 int        sem_trywait(FAR sem_t *sem);
 int        sem_post(FAR sem_t *sem);
 int        sem_getvalue(FAR sem_t *sem, FAR int *sval);
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index 91027c8..a5f1d0e 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -61,6 +61,7 @@ SYSCALL_LOOKUP(sethostname,                2)
 
 SYSCALL_LOOKUP(sem_destroy,                1)
 SYSCALL_LOOKUP(sem_post,                   1)
+SYSCALL_LOOKUP(sem_clockwait,              3)
 SYSCALL_LOOKUP(sem_timedwait,              2)
 SYSCALL_LOOKUP(sem_trywait,                1)
 SYSCALL_LOOKUP(sem_wait,                   1)
@@ -315,7 +316,7 @@ SYSCALL_LOOKUP(telldir,                    1)
   SYSCALL_LOOKUP(pthread_setaffinity_np,   3)
   SYSCALL_LOOKUP(pthread_getaffinity_np,   3)
 #endif
-  SYSCALL_LOOKUP(pthread_cond_timedwait,   3)
+  SYSCALL_LOOKUP(pthread_cond_clockwait,   4)
   SYSCALL_LOOKUP(pthread_kill,             2)
   SYSCALL_LOOKUP(pthread_sigmask,          3)
 #ifdef CONFIG_PTHREAD_CLEANUP
diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs
index 3c03ae0..63a5b2d 100644
--- a/libs/libc/pthread/Make.defs
+++ b/libs/libc/pthread/Make.defs
@@ -37,7 +37,7 @@ CSRCS += pthread_barrierattr_init.c pthread_barrierattr_destroy.c
 CSRCS += pthread_barrierattr_getpshared.c pthread_barrierattr_setpshared.c
 CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
 CSRCS += pthread_condattr_init.c pthread_condattr_destroy.c
-CSRCS += pthread_condinit.c pthread_conddestroy.c
+CSRCS += pthread_condinit.c pthread_conddestroy.c pthread_condtimedwait.c
 CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c
 CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
 CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.c
diff --git a/libs/libc/pthread/pthread_condtimedwait.c b/libs/libc/pthread/pthread_condtimedwait.c
new file mode 100644
index 0000000..9a7dffa
--- /dev/null
+++ b/libs/libc/pthread/pthread_condtimedwait.c
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * libs/libc/pthread/pthread_condtimedwait.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <pthread.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_cond_timedwait
+ *
+ * Description:
+ *   A thread can perform a timed wait on a condition variable.
+ *
+ * Input Parameters:
+ *   cond    - the condition variable to wait on
+ *   mutex   - the mutex that protects the condition variable
+ *   abstime - wait until this absolute time
+ *
+ * Returned Value:
+ *   OK (0) on success; A non-zero errno value is returned on failure.
+ *
+ * Assumptions:
+ *   Timing is of resolution 1 msec, with +/-1 millisecond accuracy.
+ *
+ ****************************************************************************/
+
+int pthread_cond_timedwait(FAR pthread_cond_t *cond,
+                           FAR pthread_mutex_t *mutex,
+                           FAR const struct timespec *abstime)
+{
+  return pthread_cond_clockwait(cond, mutex, CLOCK_REALTIME, abstime);
+}
diff --git a/libs/libc/pthread/pthread_rwlock_rdlock.c b/libs/libc/pthread/pthread_rwlock_rdlock.c
index 48fe5c6..f9ba767 100644
--- a/libs/libc/pthread/pthread_rwlock_rdlock.c
+++ b/libs/libc/pthread/pthread_rwlock_rdlock.c
@@ -113,7 +113,8 @@ int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *rw_lock)
   return err;
 }
 
-int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
+int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t *rw_lock,
+                               clockid_t clockid,
                                FAR const struct timespec *ts)
 {
   int err = pthread_mutex_lock(&rw_lock->lock);
@@ -130,7 +131,8 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
     {
       if (ts != NULL)
         {
-          err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
+          err = pthread_cond_clockwait(&rw_lock->cv, &rw_lock->lock,
+                                       clockid, ts);
         }
       else
         {
@@ -142,6 +144,7 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
           break;
         }
     }
+
 #ifdef CONFIG_PTHREAD_CLEANUP
   pthread_cleanup_pop(0);
 #endif
@@ -150,6 +153,12 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
   return err;
 }
 
+int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
+                               FAR const struct timespec *ts)
+{
+  return pthread_rwlock_clockrdlock(rw_lock, CLOCK_REALTIME, ts);
+}
+
 int pthread_rwlock_rdlock(FAR pthread_rwlock_t * rw_lock)
 {
   return pthread_rwlock_timedrdlock(rw_lock, NULL);
diff --git a/libs/libc/pthread/pthread_rwlock_wrlock.c b/libs/libc/pthread/pthread_rwlock_wrlock.c
index 520ded4..ff67fe5 100644
--- a/libs/libc/pthread/pthread_rwlock_wrlock.c
+++ b/libs/libc/pthread/pthread_rwlock_wrlock.c
@@ -100,7 +100,8 @@ int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *rw_lock)
   return err;
 }
 
-int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
+int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t *rw_lock,
+                               clockid_t clockid,
                                FAR const struct timespec *ts)
 {
   int err = pthread_mutex_lock(&rw_lock->lock);
@@ -125,7 +126,8 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
     {
       if (ts != NULL)
         {
-          err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
+          err = pthread_cond_clockwait(&rw_lock->cv, &rw_lock->lock,
+                                       clockid, ts);
         }
       else
         {
@@ -137,6 +139,7 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
           break;
         }
     }
+
 #ifdef CONFIG_PTHREAD_CLEANUP
   pthread_cleanup_pop(0);
 #endif
@@ -159,6 +162,12 @@ exit_with_mutex:
   return err;
 }
 
+int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
+                               FAR const struct timespec *ts)
+{
+  return pthread_rwlock_clockwrlock(rw_lock, CLOCK_REALTIME, ts);
+}
+
 int pthread_rwlock_wrlock(FAR pthread_rwlock_t *rw_lock)
 {
   return pthread_rwlock_timedwrlock(rw_lock, NULL);
diff --git a/sched/pthread/Make.defs b/sched/pthread/Make.defs
index cf9a10a..2a3b58d 100644
--- a/sched/pthread/Make.defs
+++ b/sched/pthread/Make.defs
@@ -25,7 +25,7 @@ CSRCS += pthread_getschedparam.c pthread_setschedparam.c
 CSRCS += pthread_mutexinit.c pthread_mutexdestroy.c
 CSRCS += pthread_mutextimedlock.c pthread_mutextrylock.c pthread_mutexunlock.c
 CSRCS += pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c
-CSRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c
+CSRCS += pthread_condclockwait.c pthread_kill.c pthread_sigmask.c
 CSRCS += pthread_cancel.c
 CSRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
 CSRCS += pthread_release.c pthread_setschedprio.c
diff --git a/sched/pthread/pthread_condtimedwait.c b/sched/pthread/pthread_condclockwait.c
similarity index 96%
rename from sched/pthread/pthread_condtimedwait.c
rename to sched/pthread/pthread_condclockwait.c
index cb1a42e..c14a109 100644
--- a/sched/pthread/pthread_condtimedwait.c
+++ b/sched/pthread/pthread_condclockwait.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/pthread/pthread_condtimedwait.c
+ * sched/pthread/pthread_condclockwait.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -140,14 +140,15 @@ static void pthread_condtimedout(int argc, wdparm_t arg1, ...)
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_cond_timedwait
+ * Name: pthread_cond_clockwait
  *
  * Description:
  *   A thread can perform a timed wait on a condition variable.
  *
  * Input Parameters:
- *   cond   - the condition variable to wait on
+ *   cond    - the condition variable to wait on
  *   mutex   - the mutex that protects the condition variable
+ *   clockid - The timing source to use in the conversion
  *   abstime - wait until this absolute time
  *
  * Returned Value:
@@ -158,8 +159,9 @@ static void pthread_condtimedout(int argc, wdparm_t arg1, ...)
  *
  ****************************************************************************/
 
-int pthread_cond_timedwait(FAR pthread_cond_t *cond,
+int pthread_cond_clockwait(FAR pthread_cond_t *cond,
                            FAR pthread_mutex_t *mutex,
+                           clockid_t clockid,
                            FAR const struct timespec *abstime)
 {
   FAR struct tcb_s *rtcb = this_task();
@@ -173,7 +175,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
 
   DEBUGASSERT(rtcb->waitdog == NULL);
 
-  /* pthread_cond_timedwait() is a cancellation point */
+  /* pthread_cond_clockwait() is a cancellation point */
 
   enter_cancellation_point();
 
@@ -227,7 +229,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
            * begins.
            */
 
-          ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
+          ret = clock_abstime2ticks(clockid, abstime, &ticks);
           if (ret)
             {
               /* Restore interrupts  (pre-emption will be enabled when
diff --git a/sched/semaphore/Make.defs b/sched/semaphore/Make.defs
index 7eb1740..7b1a522 100644
--- a/sched/semaphore/Make.defs
+++ b/sched/semaphore/Make.defs
@@ -36,8 +36,8 @@
 # Add semaphore-related files to the build
 
 CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_tickwait.c
-CSRCS += sem_timedwait.c sem_timeout.c sem_post.c sem_recover.c
-CSRCS += sem_reset.c sem_waitirq.c
+CSRCS += sem_timedwait.c sem_clockwait.c sem_timeout.c sem_post.c
+CSRCS += sem_recover.c sem_reset.c sem_waitirq.c
 
 ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
 CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c
diff --git a/sched/semaphore/sem_timedwait.c b/sched/semaphore/sem_clockwait.c
similarity index 92%
copy from sched/semaphore/sem_timedwait.c
copy to sched/semaphore/sem_clockwait.c
index da7294f..58d2bca 100644
--- a/sched/semaphore/sem_timedwait.c
+++ b/sched/semaphore/sem_clockwait.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/semaphore/sem_timedwait.c
+ * sched/semaphore/sem_clockwait.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -44,7 +44,7 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: nxsem_timedwait
+ * Name: nxsem_clockwait
  *
  * Description:
  *   This function will lock the semaphore referenced by sem as in the
@@ -67,6 +67,7 @@
  *
  * Input Parameters:
  *   sem     - Semaphore object
+ *   clockid - The timing source to use in the conversion
  *   abstime - The absolute time to wait until a timeout is declared.
  *
  * Returned Value:
@@ -86,7 +87,8 @@
  *
  ****************************************************************************/
 
-int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
+int nxsem_clockwait(FAR sem_t *sem, clockid_t clockid,
+                    FAR const struct timespec *abstime)
 {
   FAR struct tcb_s *rtcb = this_task();
   irqstate_t flags;
@@ -155,7 +157,7 @@ int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
    * value on failure.
    */
 
-  status = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
+  status = clock_abstime2ticks(clockid, abstime, &ticks);
 
   /* If the time has already expired return immediately. */
 
@@ -206,6 +208,7 @@ errout_with_irqdisabled:
  *
  * Input Parameters:
  *   sem     - Semaphore object
+ *   clockid - The timing source to use in the conversion
  *   abstime - The absolute time to wait until a timeout is declared.
  *
  * Returned Value:
@@ -220,7 +223,7 @@ errout_with_irqdisabled:
  *
  ****************************************************************************/
 
-int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
+int nxsem_clockwait_uninterruptible(FAR sem_t *sem, clockid_t clockid,
                                     FAR const struct timespec *abstime)
 {
   int ret;
@@ -229,7 +232,7 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
     {
       /* Take the semaphore (perhaps waiting) */
 
-      ret = nxsem_timedwait(sem, abstime);
+      ret = nxsem_clockwait(sem, clockid, abstime);
     }
   while (ret == -EINTR);
 
@@ -237,7 +240,7 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
 }
 
 /****************************************************************************
- * Name: sem_timedwait
+ * Name: sem_clockwait
  *
  * Description:
  *   This function will lock the semaphore referenced by sem as in the
@@ -254,6 +257,7 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
  *
  * Input Parameters:
  *   sem     - Semaphore object
+ *   clockid - The timing source to use in the conversion
  *   abstime - The absolute time to wait until a timeout is declared.
  *
  * Returned Value:
@@ -272,7 +276,8 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
  *
  ****************************************************************************/
 
-int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
+int sem_clockwait(FAR sem_t *sem, clockid_t clockid,
+                  FAR const struct timespec *abstime)
 {
   int ret;
 
@@ -282,7 +287,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
 
   /* Let nxsem_timedout() do the work */
 
-  ret = nxsem_timedwait(sem, abstime);
+  ret = nxsem_clockwait(sem, clockid, abstime);
   if (ret < 0)
     {
       set_errno(-ret);
diff --git a/sched/semaphore/sem_timedwait.c b/sched/semaphore/sem_timedwait.c
index da7294f..c072fc8 100644
--- a/sched/semaphore/sem_timedwait.c
+++ b/sched/semaphore/sem_timedwait.c
@@ -22,22 +22,7 @@
  * Included Files
  ****************************************************************************/
 
-#include <nuttx/config.h>
-
-#include <stdint.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <debug.h>
-
-#include <nuttx/irq.h>
-#include <nuttx/arch.h>
-#include <nuttx/wdog.h>
-#include <nuttx/cancelpt.h>
-
-#include "sched/sched.h"
-#include "clock/clock.h"
-#include "semaphore/semaphore.h"
+#include <nuttx/semaphore.h>
 
 /****************************************************************************
  * Public Functions
@@ -88,113 +73,7 @@
 
 int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
 {
-  FAR struct tcb_s *rtcb = this_task();
-  irqstate_t flags;
-  sclock_t ticks;
-  int status;
-  int ret = ERROR;
-
-  DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
-
-  /* Verify the input parameters and, in case of an error, set
-   * errno appropriately.
-   */
-
-#ifdef CONFIG_DEBUG_FEATURES
-  if (!abstime || !sem)
-    {
-      return -EINVAL;
-    }
-#endif
-
-  /* Create a watchdog.  We will not actually need this watchdog
-   * unless the semaphore is unavailable, but we will reserve it up
-   * front before we enter the following critical section.
-   */
-
-  rtcb->waitdog = wd_create();
-  if (!rtcb->waitdog)
-    {
-      return -ENOMEM;
-    }
-
-  /* We will disable interrupts until we have completed the semaphore
-   * wait.  We need to do this (as opposed to just disabling pre-emption)
-   * because there could be interrupt handlers that are asynchronously
-   * posting semaphores and to prevent race conditions with watchdog
-   * timeout.  This is not too bad because interrupts will be re-
-   * enabled while we are blocked waiting for the semaphore.
-   */
-
-  flags = enter_critical_section();
-
-  /* Try to take the semaphore without waiting. */
-
-  ret = nxsem_trywait(sem);
-  if (ret == OK)
-    {
-      /* We got it! */
-
-      goto success_with_irqdisabled;
-    }
-
-  /* We will have to wait for the semaphore.  Make sure that we were provided
-   * with a valid timeout.
-   */
-
-  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
-    {
-      ret = -EINVAL;
-      goto errout_with_irqdisabled;
-    }
-
-  /* Convert the timespec to clock ticks.  We must have interrupts
-   * disabled here so that this time stays valid until the wait begins.
-   *
-   * clock_abstime2ticks() returns zero on success or a POSITIVE errno
-   * value on failure.
-   */
-
-  status = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
-
-  /* If the time has already expired return immediately. */
-
-  if (status == OK && ticks <= 0)
-    {
-      ret = -ETIMEDOUT;
-      goto errout_with_irqdisabled;
-    }
-
-  /* Handle any time-related errors */
-
-  if (status != OK)
-    {
-      ret = -status;
-      goto errout_with_irqdisabled;
-    }
-
-  /* Start the watchdog */
-
-  wd_start(rtcb->waitdog, ticks, nxsem_timeout, 1, getpid());
-
-  /* Now perform the blocking wait.  If nxsem_wait() fails, the
-   * negated errno value will be returned below.
-   */
-
-  ret = nxsem_wait(sem);
-
-  /* Stop the watchdog timer */
-
-  wd_cancel(rtcb->waitdog);
-
-  /* We can now restore interrupts and delete the watchdog */
-
-success_with_irqdisabled:
-errout_with_irqdisabled:
-  leave_critical_section(flags);
-  wd_delete(rtcb->waitdog);
-  rtcb->waitdog = NULL;
-  return ret;
+  return nxsem_clockwait(sem, CLOCK_REALTIME, abstime);
 }
 
 /****************************************************************************
@@ -223,17 +102,7 @@ errout_with_irqdisabled:
 int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
                                     FAR const struct timespec *abstime)
 {
-  int ret;
-
-  do
-    {
-      /* Take the semaphore (perhaps waiting) */
-
-      ret = nxsem_timedwait(sem, abstime);
-    }
-  while (ret == -EINTR);
-
-  return ret;
+  return nxsem_clockwait_uninterruptible(sem, CLOCK_REALTIME, abstime);
 }
 
 /****************************************************************************
@@ -274,21 +143,5 @@ int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
 
 int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
 {
-  int ret;
-
-  /* sem_timedwait() is a cancellation point */
-
-  enter_cancellation_point();
-
-  /* Let nxsem_timedout() do the work */
-
-  ret = nxsem_timedwait(sem, abstime);
-  if (ret < 0)
-    {
-      set_errno(-ret);
-      ret = ERROR;
-    }
-
-  leave_cancellation_point();
-  return ret;
+  return sem_clockwait(sem, CLOCK_REALTIME, abstime);
 }
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index 931eca9..475d287 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -80,8 +80,8 @@
 "pthread_cleanup_pop","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","int"
 "pthread_cleanup_push","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","pthread_cleanup_t","FAR void *"
 "pthread_cond_broadcast","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
+"pthread_cond_clockwait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *","clockid_t","FAR const struct timespec *"
 "pthread_cond_signal","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
-"pthread_cond_timedwait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *","FAR const struct timespec *"
 "pthread_cond_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *"
 "pthread_create","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_t *","FAR const pthread_attr_t *","pthread_startroutine_t","pthread_addr_t"
 "pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
@@ -127,6 +127,7 @@
 "sched_yield","sched.h","","int"
 "seekdir","dirent.h","","void","FAR DIR *","off_t"
 "select","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR struct timeval *"
+"sem_clockwait","semaphore.h","","int","FAR sem_t *","clockid_t","FAR const struct timespec *"
 "sem_close","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR sem_t *"
 "sem_destroy","semaphore.h","","int","FAR sem_t *"
 "sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t *","FAR const char *","int","...","mode_t","unsigned int"