pthread_trylock: Fixes a problem in pthread_trylock() noted by initialkjc@yahoo.com. When CONFIG_PTHREAD_MUTEX_UNSAFE=y, the special return value EAGAIN was not being detected due to differences in reporting of returned values.

This commit is contained in:
Gregory Nutt 2017-05-29 07:05:06 -06:00
parent f86287fd43
commit a8708424c2
11 changed files with 64 additions and 34 deletions

View file

@ -107,8 +107,12 @@ void pthread_destroyjoin(FAR struct task_group_s *group,
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_takesemaphore(sem_t *sem, bool intr);
int pthread_givesemaphore(sem_t *sem);
int pthread_sem_take(sem_t *sem, 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);
@ -116,9 +120,9 @@ 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_takesemaphore(&(m)->sem,(i))
# define pthread_mutex_trytake(m) sem_trywait(&(m)->sem)
# define pthread_mutex_give(m) pthread_givesemaphore(&(m)->sem)
# 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)
#endif
#if defined(CONFIG_CANCELLATION_POINTS) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE)

View file

@ -87,7 +87,7 @@ static bool pthread_notifywaiters(FAR struct join_s *pjoin)
do
{
status = pthread_givesemaphore(&pjoin->exit_sem);
status = pthread_sem_give(&pjoin->exit_sem);
if (status == OK)
{
status = sem_getvalue(&pjoin->exit_sem, &ntasks_waiting);
@ -99,7 +99,7 @@ static bool pthread_notifywaiters(FAR struct join_s *pjoin)
* value.
*/
(void)pthread_takesemaphore(&pjoin->data_sem, false);
(void)pthread_sem_take(&pjoin->data_sem, false);
return true;
}
@ -210,12 +210,12 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value)
/* First, find thread's structure in the private data set. */
(void)pthread_takesemaphore(&group->tg_joinsem, false);
(void)pthread_sem_take(&group->tg_joinsem, false);
pjoin = pthread_findjoininfo(group, pid);
if (!pjoin)
{
serr("ERROR: Could not find join info, pid=%d\n", pid);
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
return ERROR;
}
else
@ -246,7 +246,7 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value)
* to call pthread_destroyjoin.
*/
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
}
return OK;

View file

@ -103,7 +103,7 @@ int pthread_cond_broadcast(FAR pthread_cond_t *cond)
* Only the highest priority waiting thread will get to execute
*/
ret = pthread_givesemaphore((FAR sem_t *)&cond->sem);
ret = pthread_sem_give((FAR sem_t *)&cond->sem);
/* Increment the semaphore count (as was done by the
* above post).

View file

@ -105,7 +105,7 @@ int pthread_cond_signal(FAR pthread_cond_t *cond)
if (sval < 0)
{
sinfo("Signalling...\n");
ret = pthread_givesemaphore((FAR sem_t *)&cond->sem);
ret = pthread_sem_give((FAR sem_t *)&cond->sem);
}
}
}

View file

@ -107,7 +107,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
/* Take the semaphore */
status = pthread_takesemaphore((FAR sem_t *)&cond->sem, false);
status = pthread_sem_take((FAR sem_t *)&cond->sem, false);
if (ret == OK)
{
/* Report the first failure that occurs */

View file

@ -177,14 +177,14 @@ static void pthread_start(void)
/* Sucessfully spawned, add the pjoin to our data set. */
(void)pthread_takesemaphore(&group->tg_joinsem, false);
(void)pthread_sem_take(&group->tg_joinsem, false);
pthread_addjoininfo(group, pjoin);
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
/* Report to the spawner that we successfully started. */
pjoin->started = true;
(void)pthread_givesemaphore(&pjoin->data_sem);
(void)pthread_sem_give(&pjoin->data_sem);
/* The priority of this thread may have been boosted to avoid priority
* inversion problems. If that is the case, then drop to the correct
@ -555,7 +555,7 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
* its join structure.
*/
(void)pthread_takesemaphore(&pjoin->data_sem, false);
(void)pthread_sem_take(&pjoin->data_sem, false);
/* Return the thread information to the caller */

View file

@ -87,7 +87,7 @@ int pthread_detach(pthread_t thread)
/* Find the entry associated with this pthread. */
(void)pthread_takesemaphore(&group->tg_joinsem, false);
(void)pthread_sem_take(&group->tg_joinsem, false);
pjoin = pthread_findjoininfo(group, (pid_t)thread);
if (!pjoin)
{
@ -119,7 +119,7 @@ int pthread_detach(pthread_t thread)
ret = OK;
}
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
sinfo("Returning %d\n", ret);
return ret;

View file

@ -72,11 +72,18 @@ void pthread_initialize(void)
}
/****************************************************************************
* Name: pthread_takesemaphore and pthread_givesemaphore
* Name: pthread_sem_take, pthread_sem_trytake, and
* pthread_sem_give
*
* Description:
* Support managed access to the private data sets.
*
* REVISIT: These functions really do nothing more than match the return
* value of the semaphore functions (0 or -1 with errno set) to the
* return value of more pthread functions (0 or errno). A better solution
* would be to use an internal version of the semaphore functions that
* return the error value in the correct form.
*
* Parameters:
* sem - The semaphore to lock or unlock
* intr - false: ignore EINTR errors when locking; true tread EINTR as
@ -87,7 +94,7 @@ void pthread_initialize(void)
*
****************************************************************************/
int pthread_takesemaphore(sem_t *sem, bool intr)
int pthread_sem_take(sem_t *sem, bool intr)
{
/* Verify input parameters */
@ -120,7 +127,27 @@ int pthread_takesemaphore(sem_t *sem, bool intr)
}
}
int pthread_givesemaphore(sem_t *sem)
#ifdef CONFIG_PTHREAD_MUTEX_UNSAFE
int pthread_sem_trytake(sem_t *sem)
{
int ret = EINVAL;
/* Verify input parameters */
DEBUGASSERT(sem != NULL);
if (sem != NULL)
{
/* Try to take the semaphore */
int status = sem_trywait(sem);
ret = status < 0 ? get_errno() : OK;
}
return ret;
}
#endif
int pthread_sem_give(sem_t *sem)
{
/* Verify input parameters */
@ -148,4 +175,3 @@ int pthread_givesemaphore(sem_t *sem)
return EINVAL;
}
}

View file

@ -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_takesemaphore(&group->tg_joinsem, false);
(void)pthread_sem_take(&group->tg_joinsem, false);
/* Find the join information associated with this thread.
* This can fail for one of three reasons: (1) There is no
@ -148,7 +148,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
ret = EINVAL;
}
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
}
else
{
@ -189,7 +189,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* semaphore.
*/
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
/* Take the thread's thread exit semaphore. We will sleep here
* until the thread exits. We need to exercise caution because
@ -197,7 +197,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* pthread to exit.
*/
(void)pthread_takesemaphore(&pjoin->exit_sem, false);
(void)pthread_sem_take(&pjoin->exit_sem, false);
/* The thread has exited! Get the thread exit value */
@ -211,13 +211,13 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* will know that we have received the data.
*/
(void)pthread_givesemaphore(&pjoin->data_sem);
(void)pthread_sem_give(&pjoin->data_sem);
/* Retake the join semaphore, we need to hold this when
* pthread_destroyjoin is called.
*/
(void)pthread_takesemaphore(&group->tg_joinsem, false);
(void)pthread_sem_take(&group->tg_joinsem, false);
}
/* Pre-emption is okay now. The logic still cannot be re-entered
@ -235,7 +235,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
(void)pthread_destroyjoin(group, pjoin);
}
(void)pthread_givesemaphore(&group->tg_joinsem);
(void)pthread_sem_give(&group->tg_joinsem);
ret = OK;
}

View file

@ -125,11 +125,11 @@ int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, bool intr)
}
else
{
/* Take semaphore underlying the mutex. pthread_takesemaphore
/* Take semaphore underlying the mutex. pthread_sem_take
* returns zero on success and a positive errno value on failure.
*/
ret = pthread_takesemaphore(&mutex->sem, intr);
ret = pthread_sem_take(&mutex->sem, intr);
if (ret == OK)
{
/* Check if the holder of the mutex has terminated without
@ -273,7 +273,7 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex)
/* Now release the underlying semaphore */
ret = pthread_givesemaphore(&mutex->sem);
ret = pthread_sem_give(&mutex->sem);
}
return ret;

View file

@ -95,7 +95,7 @@ void pthread_mutex_inconsistent(FAR struct pthread_tcb_s *tcb)
/* Mark the mutex as INCONSISTENT and wake up any waiting thread */
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
(void)pthread_givesemaphore(&mutex->sem);
(void)pthread_sem_give(&mutex->sem);
}
sched_unlock();