mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 12:08:36 +08:00
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:
parent
f86287fd43
commit
a8708424c2
11 changed files with 64 additions and 34 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue