From 58e387fc6f74b0bcebf2d7f0a649c57ec916c770 Mon Sep 17 00:00:00 2001 From: Leif Jakob Date: Sun, 24 Feb 2019 20:04:24 +0000 Subject: [PATCH] Merged in leif_jakob/nuttx/pthread_mutex_timedlock (pull request #830) support for pthread_mutex_timedlock Approved-by: Gregory Nutt --- include/pthread.h | 2 ++ sched/pthread/pthread.h | 10 +++--- sched/pthread/pthread_completejoin.c | 4 +-- sched/pthread/pthread_condtimedwait.c | 2 +- sched/pthread/pthread_condwait.c | 4 +-- sched/pthread/pthread_create.c | 4 +-- sched/pthread/pthread_detach.c | 2 +- sched/pthread/pthread_initialize.c | 14 +++++++-- sched/pthread/pthread_join.c | 6 ++-- sched/pthread/pthread_mutex.c | 4 +-- sched/pthread/pthread_mutexlock.c | 44 +++++++++++++++++++++++++-- 11 files changed, 73 insertions(+), 23 deletions(-) diff --git a/include/pthread.h b/include/pthread.h index 855784e5d6..2c8ba39e9c 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -539,6 +539,8 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR const pthread_mutexattr_t *attr); int pthread_mutex_destroy(FAR pthread_mutex_t *mutex); int pthread_mutex_lock(FAR pthread_mutex_t *mutex); +int pthread_mutex_timedlock(FAR pthread_mutex_t *mutex, + FAR const struct timespec *abs_timeout); int pthread_mutex_trylock(FAR pthread_mutex_t *mutex); int pthread_mutex_unlock(FAR pthread_mutex_t *mutex); diff --git a/sched/pthread/pthread.h b/sched/pthread/pthread.h index b4d1ece0d8..0e71fd6d6e 100644 --- a/sched/pthread/pthread.h +++ b/sched/pthread/pthread.h @@ -108,21 +108,21 @@ FAR struct join_s *pthread_findjoininfo(FAR struct task_group_s *group, pid_t pid); void pthread_release(FAR struct task_group_s *group); -int pthread_sem_take(sem_t *sem, bool intr); +int pthread_sem_take(sem_t *sem, FAR const struct timespec *abs_timeout, bool intr); #ifdef CONFIG_PTHREAD_MUTEX_UNSAFE int pthread_sem_trytake(sem_t *sem); #endif int pthread_sem_give(sem_t *sem); #ifndef CONFIG_PTHREAD_MUTEX_UNSAFE -int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, bool intr); +int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, FAR const struct timespec *abs_timeout, bool intr); int pthread_mutex_trytake(FAR struct pthread_mutex_s *mutex); int pthread_mutex_give(FAR struct pthread_mutex_s *mutex); void pthread_mutex_inconsistent(FAR struct pthread_tcb_s *tcb); #else -# define pthread_mutex_take(m,i) pthread_sem_take(&(m)->sem,(i)) -# define pthread_mutex_trytake(m) pthread_sem_trytake(&(m)->sem) -# define pthread_mutex_give(m) pthread_sem_give(&(m)->sem) +# define pthread_mutex_take(m,abs_timeout,i) pthread_sem_take(&(m)->sem,(abs_timeout),(i)) +# define pthread_mutex_trytake(m) pthread_sem_trytake(&(m)->sem) +# define pthread_mutex_give(m) pthread_sem_give(&(m)->sem) #endif #ifdef CONFIG_PTHREAD_MUTEX_TYPES diff --git a/sched/pthread/pthread_completejoin.c b/sched/pthread/pthread_completejoin.c index 315f26d2f5..92fa5b7603 100644 --- a/sched/pthread/pthread_completejoin.c +++ b/sched/pthread/pthread_completejoin.c @@ -99,7 +99,7 @@ static bool pthread_notifywaiters(FAR struct join_s *pjoin) * value. */ - (void)pthread_sem_take(&pjoin->data_sem, false); + (void)pthread_sem_take(&pjoin->data_sem, NULL, false); return true; } @@ -210,7 +210,7 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value) /* First, find thread's structure in the private data set. */ - (void)pthread_sem_take(&group->tg_joinsem, false); + (void)pthread_sem_take(&group->tg_joinsem, NULL, false); pjoin = pthread_findjoininfo(group, pid); if (!pjoin) { diff --git a/sched/pthread/pthread_condtimedwait.c b/sched/pthread/pthread_condtimedwait.c index e95b8907d5..3f7db6b624 100644 --- a/sched/pthread/pthread_condtimedwait.c +++ b/sched/pthread/pthread_condtimedwait.c @@ -320,7 +320,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, sinfo("Re-locking...\n"); - status = pthread_mutex_take(mutex, false); + status = pthread_mutex_take(mutex, NULL, false); if (status == OK) { mutex->pid = mypid; diff --git a/sched/pthread/pthread_condwait.c b/sched/pthread/pthread_condwait.c index b8dcf8bf61..6807879f58 100644 --- a/sched/pthread/pthread_condwait.c +++ b/sched/pthread/pthread_condwait.c @@ -105,7 +105,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) /* Take the semaphore */ - status = pthread_sem_take((FAR sem_t *)&cond->sem, false); + status = pthread_sem_take((FAR sem_t *)&cond->sem, NULL, false); if (ret == OK) { /* Report the first failure that occurs */ @@ -124,7 +124,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) sinfo("Reacquire mutex...\n"); - status = pthread_mutex_take(mutex, false); + status = pthread_mutex_take(mutex, NULL, false); if (ret == OK) { /* Report the first failure that occurs */ diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 1be784f69d..a4bcb68971 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -179,7 +179,7 @@ static void pthread_start(void) /* Successfully spawned, add the pjoin to our data set. */ - (void)pthread_sem_take(&group->tg_joinsem, false); + (void)pthread_sem_take(&group->tg_joinsem, NULL, false); pthread_addjoininfo(group, pjoin); (void)pthread_sem_give(&group->tg_joinsem); @@ -580,7 +580,7 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr, * its join structure. */ - (void)pthread_sem_take(&pjoin->data_sem, false); + (void)pthread_sem_take(&pjoin->data_sem, NULL, false); /* Return the thread information to the caller */ diff --git a/sched/pthread/pthread_detach.c b/sched/pthread/pthread_detach.c index 70488cac8d..c6a1192651 100644 --- a/sched/pthread/pthread_detach.c +++ b/sched/pthread/pthread_detach.c @@ -87,7 +87,7 @@ int pthread_detach(pthread_t thread) /* Find the entry associated with this pthread. */ - (void)pthread_sem_take(&group->tg_joinsem, false); + (void)pthread_sem_take(&group->tg_joinsem, NULL, false); pjoin = pthread_findjoininfo(group, (pid_t)thread); if (!pjoin) { diff --git a/sched/pthread/pthread_initialize.c b/sched/pthread/pthread_initialize.c index 95cf18700a..84f641d4bb 100644 --- a/sched/pthread/pthread_initialize.c +++ b/sched/pthread/pthread_initialize.c @@ -97,7 +97,7 @@ void pthread_initialize(void) * ****************************************************************************/ -int pthread_sem_take(sem_t *sem, bool intr) +int pthread_sem_take(sem_t *sem, FAR const struct timespec *abs_timeout, bool intr) { int ret; @@ -110,7 +110,15 @@ int pthread_sem_take(sem_t *sem, bool intr) { /* Take the semaphore (perhaps waiting) */ - ret = nxsem_wait(sem); + if ( abs_timeout == NULL ) + { + ret = nxsem_wait(sem); + } + else + { + ret = nxsem_timedwait(sem, abs_timeout); + } + if (ret < 0) { /* The only cases that an error should occur here is if the wait @@ -118,7 +126,7 @@ int pthread_sem_take(sem_t *sem, bool intr) * the wait. */ - DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED || ret == -ETIMEDOUT); /* When the error occurs in this case, should we errout? Or * should we just continue waiting until we have the diff --git a/sched/pthread/pthread_join.c b/sched/pthread/pthread_join.c index 0527dd19be..27876565a8 100644 --- a/sched/pthread/pthread_join.c +++ b/sched/pthread/pthread_join.c @@ -114,7 +114,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) * because it will also attempt to get this semaphore. */ - (void)pthread_sem_take(&group->tg_joinsem, false); + (void)pthread_sem_take(&group->tg_joinsem, NULL, false); /* Find the join information associated with this thread. * This can fail for one of three reasons: (1) There is no @@ -197,7 +197,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) * pthread to exit. */ - (void)pthread_sem_take(&pjoin->exit_sem, false); + (void)pthread_sem_take(&pjoin->exit_sem, NULL, false); /* The thread has exited! Get the thread exit value */ @@ -217,7 +217,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) * pthread_destroyjoin is called. */ - (void)pthread_sem_take(&group->tg_joinsem, false); + (void)pthread_sem_take(&group->tg_joinsem, NULL, false); } /* Pre-emption is okay now. The logic still cannot be re-entered diff --git a/sched/pthread/pthread_mutex.c b/sched/pthread/pthread_mutex.c index e320638401..420d0b1a7b 100644 --- a/sched/pthread/pthread_mutex.c +++ b/sched/pthread/pthread_mutex.c @@ -177,7 +177,7 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) * ****************************************************************************/ -int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, bool intr) +int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, FAR const struct timespec *abs_timeout, bool intr) { int ret = EINVAL; @@ -202,7 +202,7 @@ int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, bool intr) * returns zero on success and a positive errno value on failure. */ - ret = pthread_sem_take(&mutex->sem, intr); + ret = pthread_sem_take(&mutex->sem, abs_timeout, intr); if (ret == OK) { /* Check if the holder of the mutex has terminated without diff --git a/sched/pthread/pthread_mutexlock.c b/sched/pthread/pthread_mutexlock.c index 098529f8f9..af107fbf01 100644 --- a/sched/pthread/pthread_mutexlock.c +++ b/sched/pthread/pthread_mutexlock.c @@ -103,8 +103,48 @@ * been exceeded. * ****************************************************************************/ - int pthread_mutex_lock(FAR pthread_mutex_t *mutex) +{ + return pthread_mutex_timedlock(mutex, NULL); +} + + /**************************************************************************** + * Name: pthread_mutex_timedlock + * + * Description: + * The pthread_mutex_timedlock() function shall lock the mutex object + * referenced by mutex. If the mutex is already locked, the calling + * thread shall block until the mutex becomes available as in the + * pthread_mutex_lock() function. If the mutex cannot be locked without + * waiting for another thread to unlock the mutex, this wait shall be + * terminated when the specified timeout expires. + * + * The timeout shall expire when the absolute time specified by + * abs_timeout passes, as measured by the clock on which timeouts are + * based (that is, when the value of that clock equals or exceeds + * abs_timeout), or if the absolute time specified by abs_timeout + * has already been passed at the time of the call. + * + * Input Parameters: + * mutex - A reference to the mutex to be locked. + * abs_timeout - max wait time (NULL wait forever) + * + * Returned Value: + * 0 on success or an errno value on failure. Note that the errno EINTR + * is never returned by pthread_mutex_lock(). + * errno is ETIMEDOUT if mutex could not be locked before the specified + * timeout expired + * + * Assumptions: + * + * POSIX Compatibility: + * - This implementation does not return EAGAIN when the mutex could not be + * acquired because the maximum number of recursive locks for mutex has + * been exceeded. + * + ****************************************************************************/ +int pthread_mutex_timedlock(FAR pthread_mutex_t *restrict mutex, + FAR const struct timespec *abs_timeout) { int mypid = (int)getpid(); int ret = EINVAL; @@ -215,7 +255,7 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) * default mutex. */ - ret = pthread_mutex_take(mutex, true); + ret = pthread_mutex_take(mutex, NULL, true); /* If we successfully obtained the semaphore, then indicate * that we own it.