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 <xiaoxi...@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....@mcrowe.com/ Signed-off-by: Xiang Xiao <xiaoxi...@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"