mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 05:16:47 +08:00
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 <xiaoxiang@xiaomi.com> Change-Id: I0095cb34cef3d0d88a100255053da79266b73ff2
This commit is contained in:
committed by
Alan Carvalho de Assis
parent
78862c51dc
commit
33ec242caf
@@ -65,6 +65,7 @@
|
|||||||
# define _SEM_WAIT(s) nxsem_wait(s)
|
# define _SEM_WAIT(s) nxsem_wait(s)
|
||||||
# define _SEM_TRYWAIT(s) nxsem_trywait(s)
|
# define _SEM_TRYWAIT(s) nxsem_trywait(s)
|
||||||
# define _SEM_TIMEDWAIT(s,t) nxsem_timedwait(s,t)
|
# 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_POST(s) nxsem_post(s)
|
||||||
# define _SEM_GETVALUE(s) nxsem_get_value(s)
|
# define _SEM_GETVALUE(s) nxsem_get_value(s)
|
||||||
# define _SEM_GETPROTOCOL(s,p) nxsem_get_protocol(s,p)
|
# define _SEM_GETPROTOCOL(s,p) nxsem_get_protocol(s,p)
|
||||||
@@ -77,6 +78,7 @@
|
|||||||
# define _SEM_WAIT(s) sem_wait(s)
|
# define _SEM_WAIT(s) sem_wait(s)
|
||||||
# define _SEM_TRYWAIT(s) sem_trywait(s)
|
# define _SEM_TRYWAIT(s) sem_trywait(s)
|
||||||
# define _SEM_TIMEDWAIT(s,t) sem_timedwait(s,t)
|
# 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_GETVALUE(s,v) sem_getvalue(s,v)
|
||||||
# define _SEM_POST(s) sem_post(s)
|
# define _SEM_POST(s) sem_post(s)
|
||||||
# define _SEM_GETPROTOCOL(s,p) sem_getprotocol(s,p)
|
# define _SEM_GETPROTOCOL(s,p) sem_getprotocol(s,p)
|
||||||
@@ -278,9 +280,56 @@ int nxsem_trywait(FAR sem_t *sem);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct timespec; /* Forward reference */
|
|
||||||
int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime);
|
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
|
* Name: nxsem_tickwait
|
||||||
*
|
*
|
||||||
@@ -568,6 +617,39 @@ int nxsem_wait_uninterruptible(FAR sem_t *sem);
|
|||||||
int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
|
int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
|
||||||
FAR const struct timespec *abstime);
|
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
|
* Name: nxsem_tickwait_uninterruptible
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -629,6 +629,11 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
|
|||||||
FAR pthread_mutex_t *mutex,
|
FAR pthread_mutex_t *mutex,
|
||||||
FAR const struct timespec *abstime);
|
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 */
|
/* Barrier attributes */
|
||||||
|
|
||||||
int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
|
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_rdlock(pthread_rwlock_t *lock);
|
||||||
int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *lock,
|
int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *lock,
|
||||||
FAR const struct timespec *abstime);
|
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_tryrdlock(FAR pthread_rwlock_t *lock);
|
||||||
int pthread_rwlock_wrlock(FAR pthread_rwlock_t *lock);
|
int pthread_rwlock_wrlock(FAR pthread_rwlock_t *lock);
|
||||||
int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *lock,
|
int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *lock,
|
||||||
FAR const struct timespec *abstime);
|
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_trywrlock(FAR pthread_rwlock_t *lock);
|
||||||
int pthread_rwlock_unlock(FAR pthread_rwlock_t *lock);
|
int pthread_rwlock_unlock(FAR pthread_rwlock_t *lock);
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
@@ -88,6 +89,7 @@ struct sem_s
|
|||||||
{
|
{
|
||||||
volatile int16_t semcount; /* >0 -> Num counts available */
|
volatile int16_t semcount; /* >0 -> Num counts available */
|
||||||
/* <0 -> Num tasks waiting for semaphore */
|
/* <0 -> Num tasks waiting for semaphore */
|
||||||
|
|
||||||
/* If priority inheritance is enabled, then we have to keep track of which
|
/* If priority inheritance is enabled, then we have to keep track of which
|
||||||
* tasks hold references to the semaphore.
|
* tasks hold references to the semaphore.
|
||||||
*/
|
*/
|
||||||
@@ -134,9 +136,6 @@ extern "C"
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/* Forward references needed by some prototypes */
|
|
||||||
|
|
||||||
struct timespec; /* Defined in time.h */
|
|
||||||
|
|
||||||
/* Counting Semaphore Interfaces (based on POSIX APIs) */
|
/* 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_destroy(FAR sem_t *sem);
|
||||||
int sem_wait(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_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_trywait(FAR sem_t *sem);
|
||||||
int sem_post(FAR sem_t *sem);
|
int sem_post(FAR sem_t *sem);
|
||||||
int sem_getvalue(FAR sem_t *sem, FAR int *sval);
|
int sem_getvalue(FAR sem_t *sem, FAR int *sval);
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ SYSCALL_LOOKUP(sethostname, 2)
|
|||||||
|
|
||||||
SYSCALL_LOOKUP(sem_destroy, 1)
|
SYSCALL_LOOKUP(sem_destroy, 1)
|
||||||
SYSCALL_LOOKUP(sem_post, 1)
|
SYSCALL_LOOKUP(sem_post, 1)
|
||||||
|
SYSCALL_LOOKUP(sem_clockwait, 3)
|
||||||
SYSCALL_LOOKUP(sem_timedwait, 2)
|
SYSCALL_LOOKUP(sem_timedwait, 2)
|
||||||
SYSCALL_LOOKUP(sem_trywait, 1)
|
SYSCALL_LOOKUP(sem_trywait, 1)
|
||||||
SYSCALL_LOOKUP(sem_wait, 1)
|
SYSCALL_LOOKUP(sem_wait, 1)
|
||||||
@@ -315,7 +316,7 @@ SYSCALL_LOOKUP(telldir, 1)
|
|||||||
SYSCALL_LOOKUP(pthread_setaffinity_np, 3)
|
SYSCALL_LOOKUP(pthread_setaffinity_np, 3)
|
||||||
SYSCALL_LOOKUP(pthread_getaffinity_np, 3)
|
SYSCALL_LOOKUP(pthread_getaffinity_np, 3)
|
||||||
#endif
|
#endif
|
||||||
SYSCALL_LOOKUP(pthread_cond_timedwait, 3)
|
SYSCALL_LOOKUP(pthread_cond_clockwait, 4)
|
||||||
SYSCALL_LOOKUP(pthread_kill, 2)
|
SYSCALL_LOOKUP(pthread_kill, 2)
|
||||||
SYSCALL_LOOKUP(pthread_sigmask, 3)
|
SYSCALL_LOOKUP(pthread_sigmask, 3)
|
||||||
#ifdef CONFIG_PTHREAD_CLEANUP
|
#ifdef CONFIG_PTHREAD_CLEANUP
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ CSRCS += pthread_barrierattr_init.c pthread_barrierattr_destroy.c
|
|||||||
CSRCS += pthread_barrierattr_getpshared.c pthread_barrierattr_setpshared.c
|
CSRCS += pthread_barrierattr_getpshared.c pthread_barrierattr_setpshared.c
|
||||||
CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
|
CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
|
||||||
CSRCS += pthread_condattr_init.c pthread_condattr_destroy.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_init.c pthread_mutexattr_destroy.c
|
||||||
CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
|
CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
|
||||||
CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.c
|
CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.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);
|
||||||
|
}
|
||||||
@@ -113,7 +113,8 @@ int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *rw_lock)
|
|||||||
return err;
|
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)
|
FAR const struct timespec *ts)
|
||||||
{
|
{
|
||||||
int err = pthread_mutex_lock(&rw_lock->lock);
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -142,6 +144,7 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PTHREAD_CLEANUP
|
#ifdef CONFIG_PTHREAD_CLEANUP
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
#endif
|
#endif
|
||||||
@@ -150,6 +153,12 @@ int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock,
|
|||||||
return err;
|
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)
|
int pthread_rwlock_rdlock(FAR pthread_rwlock_t * rw_lock)
|
||||||
{
|
{
|
||||||
return pthread_rwlock_timedrdlock(rw_lock, NULL);
|
return pthread_rwlock_timedrdlock(rw_lock, NULL);
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *rw_lock)
|
|||||||
return err;
|
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)
|
FAR const struct timespec *ts)
|
||||||
{
|
{
|
||||||
int err = pthread_mutex_lock(&rw_lock->lock);
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -137,6 +139,7 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PTHREAD_CLEANUP
|
#ifdef CONFIG_PTHREAD_CLEANUP
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
#endif
|
#endif
|
||||||
@@ -159,6 +162,12 @@ exit_with_mutex:
|
|||||||
return err;
|
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)
|
int pthread_rwlock_wrlock(FAR pthread_rwlock_t *rw_lock)
|
||||||
{
|
{
|
||||||
return pthread_rwlock_timedwrlock(rw_lock, NULL);
|
return pthread_rwlock_timedwrlock(rw_lock, NULL);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ CSRCS += pthread_getschedparam.c pthread_setschedparam.c
|
|||||||
CSRCS += pthread_mutexinit.c pthread_mutexdestroy.c
|
CSRCS += pthread_mutexinit.c pthread_mutexdestroy.c
|
||||||
CSRCS += pthread_mutextimedlock.c pthread_mutextrylock.c pthread_mutexunlock.c
|
CSRCS += pthread_mutextimedlock.c pthread_mutextrylock.c pthread_mutexunlock.c
|
||||||
CSRCS += pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.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_cancel.c
|
||||||
CSRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
|
CSRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
|
||||||
CSRCS += pthread_release.c pthread_setschedprio.c
|
CSRCS += pthread_release.c pthread_setschedprio.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
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* 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:
|
* Description:
|
||||||
* A thread can perform a timed wait on a condition variable.
|
* A thread can perform a timed wait on a condition variable.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cond - the condition variable to wait on
|
* cond - the condition variable to wait on
|
||||||
* mutex - the mutex that protects the condition variable
|
* mutex - the mutex that protects the condition variable
|
||||||
|
* clockid - The timing source to use in the conversion
|
||||||
* abstime - wait until this absolute time
|
* abstime - wait until this absolute time
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* 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,
|
FAR pthread_mutex_t *mutex,
|
||||||
|
clockid_t clockid,
|
||||||
FAR const struct timespec *abstime)
|
FAR const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = this_task();
|
FAR struct tcb_s *rtcb = this_task();
|
||||||
@@ -173,7 +175,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
|
|||||||
|
|
||||||
DEBUGASSERT(rtcb->waitdog == NULL);
|
DEBUGASSERT(rtcb->waitdog == NULL);
|
||||||
|
|
||||||
/* pthread_cond_timedwait() is a cancellation point */
|
/* pthread_cond_clockwait() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
enter_cancellation_point();
|
||||||
|
|
||||||
@@ -227,7 +229,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond,
|
|||||||
* begins.
|
* begins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
|
ret = clock_abstime2ticks(clockid, abstime, &ticks);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
/* Restore interrupts (pre-emption will be enabled when
|
/* Restore interrupts (pre-emption will be enabled when
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
# Add semaphore-related files to the build
|
# Add semaphore-related files to the build
|
||||||
|
|
||||||
CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_tickwait.c
|
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_timedwait.c sem_clockwait.c sem_timeout.c sem_post.c
|
||||||
CSRCS += sem_reset.c sem_waitirq.c
|
CSRCS += sem_recover.c sem_reset.c sem_waitirq.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
|
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
|
||||||
CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c
|
CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c
|
||||||
|
|||||||
@@ -0,0 +1,299 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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
|
||||||
|
* 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 <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"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
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;
|
||||||
|
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(clockid, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsem_timedwait_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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsem_clockwait_uninterruptible(FAR sem_t *sem, clockid_t clockid,
|
||||||
|
FAR const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Take the semaphore (perhaps waiting) */
|
||||||
|
|
||||||
|
ret = nxsem_clockwait(sem, clockid, abstime);
|
||||||
|
}
|
||||||
|
while (ret == -EINTR);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sem_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.
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
* Zero (OK) is returned on success. On failure, -1 (ERROR) is returned
|
||||||
|
* and the errno is set appropriately:
|
||||||
|
*
|
||||||
|
* EINVAL The sem argument does not refer to a valid semaphore. Or the
|
||||||
|
* thread would have blocked, and the abstime parameter specified
|
||||||
|
* a nanoseconds field value less than zero or greater than or
|
||||||
|
* equal to 1000 million.
|
||||||
|
* ETIMEDOUT The semaphore could not be locked before the specified timeout
|
||||||
|
* expired.
|
||||||
|
* EDEADLK A deadlock condition was detected.
|
||||||
|
* EINTR A signal interrupted this function.
|
||||||
|
* ECANCELED May be returned if the thread is canceled while waiting.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int sem_clockwait(FAR sem_t *sem, clockid_t clockid,
|
||||||
|
FAR const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* sem_timedwait() is a cancellation point */
|
||||||
|
|
||||||
|
enter_cancellation_point();
|
||||||
|
|
||||||
|
/* Let nxsem_timedout() do the work */
|
||||||
|
|
||||||
|
ret = nxsem_clockwait(sem, clockid, abstime);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
set_errno(-ret);
|
||||||
|
ret = ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_cancellation_point();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -22,22 +22,7 @@
|
|||||||
* Included Files
|
* Included Files
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/semaphore.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"
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@@ -88,113 +73,7 @@
|
|||||||
|
|
||||||
int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
|
int nxsem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = this_task();
|
return nxsem_clockwait(sem, CLOCK_REALTIME, abstime);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -223,17 +102,7 @@ errout_with_irqdisabled:
|
|||||||
int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
|
int nxsem_timedwait_uninterruptible(FAR sem_t *sem,
|
||||||
FAR const struct timespec *abstime)
|
FAR const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
int ret;
|
return nxsem_clockwait_uninterruptible(sem, CLOCK_REALTIME, abstime);
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Take the semaphore (perhaps waiting) */
|
|
||||||
|
|
||||||
ret = nxsem_timedwait(sem, abstime);
|
|
||||||
}
|
|
||||||
while (ret == -EINTR);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -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 sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
int ret;
|
return sem_clockwait(sem, CLOCK_REALTIME, abstime);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -80,8 +80,8 @@
|
|||||||
"pthread_cleanup_pop","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","int"
|
"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_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_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_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_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_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"
|
"pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
|
||||||
@@ -127,6 +127,7 @@
|
|||||||
"sched_yield","sched.h","","int"
|
"sched_yield","sched.h","","int"
|
||||||
"seekdir","dirent.h","","void","FAR DIR *","off_t"
|
"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 *"
|
"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_close","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR sem_t *"
|
||||||
"sem_destroy","semaphore.h","","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"
|
"sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t *","FAR const char *","int","...","mode_t","unsigned int"
|
||||||
|
|||||||
|
Reference in New Issue
Block a user