included/pthreads, sched/pthreads, and Documetions: Updates after review of last PR.

This commit is contained in:
Gregory Nutt 2019-02-24 14:40:11 -06:00
parent 58e387fc6f
commit c7cc6bab96
6 changed files with 179 additions and 125 deletions

View File

@ -13,7 +13,7 @@
<h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1>
<p><small>by</small></p>
<p>Gregory Nutt<p>
<p>Last Updated: July 15, 2018</p>
<p>Last Updated: February 24, 20189</p>
</td>
</tr>
</table>
@ -5823,8 +5823,9 @@ be sent.
<li><a href="#pthreadmutexinit">2.8.37 pthread_mutex_init</a></li>
<li><a href="#pthreadmutexdestrory">2.8.38 pthread_mutex_destroy</a></li>
<li><a href="#pthreadmutexlock">2.8.39 pthread_mutex_lock</a></li>
<li><a href="#pthreadmutextrylock">2.8.40 pthread_mutex_trylock</a></li>
<li><a href="#pthreadmutexunlock">2.8.41 pthread_mutex_unlock</a></li>
<li><a href="#pthreadmutextimedlock">2.8.40 pthread_mutex_timedlock</a></li>
<li><a href="#pthreadmutextrylock">2.8.41 pthread_mutex_trylock</a></li>
<li><a href="#pthreadmutexunlock">2.8.42 pthread_mutex_unlock</a></li>
</ul>
<p>
<b>Condition Variables</b>.
@ -7432,7 +7433,47 @@ Otherwise, an error number will be returned to indicate the error:
<b>POSIX Compatibility:</b> Comparable to the POSIX
interface of the same name.
<H3><a name="pthreadmutextrylock">2.8.40 pthread_mutex_trylock</a></H3>
<H3><a name="pthreadmutextimedlock">2.8.40 pthread_mutex_timedlock</a></H3>
<p>
<b>Function Prototype:</b>
<p>
<pre>
#include &lt;pthread.h&gt;
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout);
</pre>
<p>
<b>Description:</b>
The <code>pthread_mutex_timedlock()</code> function will lock the mutex object referenced by <code>mutex</code>.
If the mutex is already locked, the calling thread will block until the mutex becomes available as in the <a href="#pthreadmutexlock"><code>pthread_mutex_lock()</code><a> function.
If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait will be terminated when the specified <code>abs_timeout</code> expires.
</p>
<p>
The timeout will expire when the absolute time specified by <code>abs_timeout </code> passes, as measured by the clock on which timeouts are based (that is, when the value of that clock equals or exceeds <code>abs_timeout</code>), or if the absolute time specified by <code>abs_timeout</code> has already been passed at the time of the call.
</p>
<p>
<b>Input Parameters:</b>
<p>
<ul>
<li><code>mutex</code>. A reference to the mutex to be locked.</li>
<li><code>abs_timeout</code>. Maximum wait time (with <code>NULL</code> meaning to wait forever).</li>
</ul>
<p>
<b>Returned Value:</b>
<p>
If successful, the <code>pthread_mutex_trylock()</code> function will return zero (<code>OK</code>).
Otherwise, an error number will be returned to indicate the error.
Note that the errno <code>EINTR</code> is never returned by <code>pthread_mutex_timedlock()</code>.
The returned errno is ETIMEDOUT if the mutex could not be locked before the specified timeout expired
</p>
<p>
<b>Assumptions/Limitations:</b>
<p>
<b>POSIX Compatibility:</b>
Comparable to the POSIX interface of the same name.
This implementation does not return <code>EAGAIN</code> when the mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
</p>
<H3><a name="pthreadmutextrylock">2.8.41 pthread_mutex_trylock</a></H3>
<p>
<b>Function Prototype:</b>
<p>
@ -7442,7 +7483,7 @@ interface of the same name.
</pre>
<p>
<b>Description:</b>
The function pthread_mutex_trylock() is identical to <a href="#pthreadmutexlock"><code>pthread_mutex_lock()</code></a>
The function <code>pthread_mutex_trylock()</code> is identical to <a href="#pthreadmutexlock"><code>pthread_mutex_lock()</code></a>
except that if the mutex object referenced by mutex is currently locked
(by any thread, including the current thread), the call returns immediately
with the <code>errno</code> <code>EBUSY</code>.
@ -7472,7 +7513,7 @@ Otherwise, an error number will be returned to indicate the error:
<b>POSIX Compatibility:</b> Comparable to the POSIX
interface of the same name.
<H3><a name="pthreadmutexunlock">2.8.41 pthread_mutex_unlock</a></H3>
<H3><a name="pthreadmutexunlock">2.8.42 pthread_mutex_unlock</a></H3>
<p>
<b>Function Prototype:</b>
<p>
@ -10581,6 +10622,7 @@ notify a task when a message is available on a queue.
<li><a href="#pthreadmutexdestrory">pthread_mutex_destroy</a></li>
<li><a href="#pthreadmutexinit">pthread_mutex_init</a></li>
<li><a href="#pthreadmutexlock">pthread_mutex_lock</a></li>
<li><a href="#pthreadmutextimedlock">pthread_mutex_timedlock</a></li>
<li><a href="#pthreadmutextrylock">pthread_mutex_trylock</a></li>
<li><a href="#pthreadmutexunlock">pthread_mutex_unlock</a></li>
<li><a href="#pthreadocndattrdestroy">pthread_condattr_destroy</a></li>

View File

@ -1,7 +1,8 @@
/********************************************************************************
* include/pthread.h
*
* Copyright (C) 2007-2009, 2011-2012, 2015-2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2015-2017, 2019 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -77,23 +78,26 @@
*
* PTHREAD_MUTEX_NORMAL: This type of mutex does not detect deadlock. A thread
* attempting to relock this mutex without first unlocking it will deadlock.
* Attempting to unlock a mutex locked by a different thread results in undefined
* behavior. Attempting to unlock an unlocked mutex results in undefined behavior.
* Attempting to unlock a mutex locked by a different thread results in
* undefined behavior. Attempting to unlock an unlocked mutex results in
* undefined behavior.
* PTHREAD_MUTEX_ERRORCHECK
* This type of mutex provides error checking. A thread attempting to relock this
* mutex without first unlocking it will return with an error. A thread attempting
* to unlock a mutex which another thread has locked will return with an error. A
* thread attempting to unlock an unlocked mutex will return with an error.
* This type of mutex provides error checking. A thread attempting to relock
* this mutex without first unlocking it will return with an error. A thread
* attempting to unlock a mutex which another thread has locked will return
* with an error. A thread attempting to unlock an unlocked mutex will return
* with an error.
* PTHREAD_MUTEX_RECURSIVE
* A thread attempting to relock this mutex without first unlocking it will succeed
* in locking the mutex. The relocking deadlock which can occur with mutexes of type
* PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this
* mutex require the same number of unlocks to release the mutex before another thread
* can acquire the mutex. A thread attempting to unlock a mutex which another thread
* has locked will return with an error. A thread attempting to unlock an unlocked
* mutex will return with an error.
* A thread attempting to relock this mutex without first unlocking it will
* succeed in locking the mutex. The relocking deadlock which can occur with
* mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex.
* Multiple locks of this mutex require the same number of unlocks to release
* the mutex before another thread can acquire the mutex. A thread attempting
* to unlock a mutex which another thread has locked will return with an error.
* A thread attempting to unlock an unlocked mutex will return with an error.
* PTHREAD_MUTEX_DEFAULT
* An implementation is allowed to map this mutex to one of the other mutex types.
* An implementation is allowed to map this mutex to one of the other mutex
* types.
*/
#define PTHREAD_MUTEX_NORMAL 0
@ -509,7 +513,7 @@ int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,
/* Thread-specific Data Interfaces */
int pthread_key_create(FAR pthread_key_t *key,
CODE void (*destructor)(FAR void*));
CODE void (*destructor)(FAR void *));
int pthread_setspecific(pthread_key_t key, FAR const void *value);
FAR void *pthread_getspecific(pthread_key_t key);
int pthread_key_delete(pthread_key_t key);
@ -540,7 +544,7 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex,
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);
FAR const struct timespec *abs_timeout);
int pthread_mutex_trylock(FAR pthread_mutex_t *mutex);
int pthread_mutex_unlock(FAR pthread_mutex_t *mutex);
@ -557,7 +561,8 @@ int pthread_condattr_destroy(FAR pthread_condattr_t *attr);
/* A thread can create and delete condition variables. */
int pthread_cond_init(FAR pthread_cond_t *cond, FAR const pthread_condattr_t *attr);
int pthread_cond_init(FAR pthread_cond_t *cond,
FAR const pthread_condattr_t *attr);
int pthread_cond_destroy(FAR pthread_cond_t *cond);
/* A thread can signal to and broadcast on a condition variable. */

View File

@ -1,7 +1,8 @@
/****************************************************************************
* sched/pthread/pthread.h
*
* Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011, 2013-2014, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -94,8 +95,8 @@ struct pthread_tcb_s; /* Forward reference */
struct task_group_s; /* Forward reference */
void weak_function pthread_initialize(void);
int pthread_schedsetup(FAR struct pthread_tcb_s *tcb, int priority, start_t start,
pthread_startroutine_t entry);
int pthread_schedsetup(FAR struct pthread_tcb_s *tcb, int priority,
start_t start, pthread_startroutine_t entry);
#ifdef CONFIG_PTHREAD_CLEANUP
void pthread_cleanup_popall(FAR struct pthread_tcb_s *tcb);
@ -108,14 +109,16 @@ 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, FAR const struct timespec *abs_timeout, bool intr);
int pthread_sem_take(FAR 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, FAR const struct timespec *abs_timeout, 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);
@ -135,4 +138,3 @@ int pthread_mutexattr_verifytype(int type);
#endif
#endif /* __SCHED_PTHREAD_PTHREAD_H */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_initialize.c
*
* Copyright (C) 2007-2010, 2013, 2017-2018 Gregory Nutt. All rights
* Copyright (C) 2007-2010, 2013, 2017-2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
@ -97,7 +97,8 @@ void pthread_initialize(void)
*
****************************************************************************/
int pthread_sem_take(sem_t *sem, FAR const struct timespec *abs_timeout, bool intr)
int pthread_sem_take(FAR sem_t *sem, FAR const struct timespec *abs_timeout,
bool intr)
{
int ret;
@ -110,14 +111,14 @@ int pthread_sem_take(sem_t *sem, FAR const struct timespec *abs_timeout, bool in
{
/* Take the semaphore (perhaps waiting) */
if ( abs_timeout == NULL )
{
ret = nxsem_wait(sem);
}
else
{
ret = nxsem_timedwait(sem, abs_timeout);
}
if (abs_timeout == NULL)
{
ret = nxsem_wait(sem);
}
else
{
ret = nxsem_timedwait(sem, abs_timeout);
}
if (ret < 0)
{
@ -126,7 +127,8 @@ int pthread_sem_take(sem_t *sem, FAR const struct timespec *abs_timeout, bool in
* the wait.
*/
DEBUGASSERT(ret == -EINTR || ret == -ECANCELED || ret == -ETIMEDOUT);
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

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_mutex.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -177,7 +177,8 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex)
*
****************************************************************************/
int pthread_mutex_take(FAR struct pthread_mutex_s *mutex, FAR const struct timespec *abs_timeout, bool intr)
int pthread_mutex_take(FAR struct pthread_mutex_s *mutex,
FAR const struct timespec *abs_timeout, bool intr)
{
int ret = EINVAL;

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_mutexlock.c
*
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2017, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -103,48 +103,50 @@
* been exceeded.
*
****************************************************************************/
int pthread_mutex_lock(FAR pthread_mutex_t *mutex)
{
return pthread_mutex_timedlock(mutex, NULL);
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)
/****************************************************************************
* Name: pthread_mutex_timedlock
*
* Description:
* The pthread_mutex_timedlock() function will lock the mutex object
* referenced by mutex. If the mutex is already locked, the calling
* thread will 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 will be
* terminated when the specified timeout expires.
*
* The timeout will 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_timedlock().
* 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 *mutex,
FAR const struct timespec *abs_timeout)
{
int mypid = (int)getpid();
int ret = EINVAL;
@ -205,70 +207,70 @@ int pthread_mutex_timedlock(FAR pthread_mutex_t *restrict mutex,
#endif /* CONFIG_PTHREAD_MUTEX_TYPES */
#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE
/* The calling thread does not hold the semaphore. The correct
* behavior for the 'robust' mutex is to verify that the holder of the
* mutex is still valid. This is protection from the case
* where the holder of the mutex has exitted without unlocking it.
*/
/* The calling thread does not hold the semaphore. The correct
* behavior for the 'robust' mutex is to verify that the holder of the
* mutex is still valid. This is protection from the case
* where the holder of the mutex has exitted without unlocking it.
*/
#ifdef CONFIG_PTHREAD_MUTEX_BOTH
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
/* Include check if this is a NORMAL mutex and that it is robust */
/* Include check if this is a NORMAL mutex and that it is robust */
if (mutex->pid > 0 &&
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
sched_gettcb(mutex->pid) == NULL)
if (mutex->pid > 0 &&
((mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 ||
mutex->type != PTHREAD_MUTEX_NORMAL) &&
sched_gettcb(mutex->pid) == NULL)
#else /* CONFIG_PTHREAD_MUTEX_TYPES */
/* This can only be a NORMAL mutex. Include check if it is robust */
/* This can only be a NORMAL mutex. Include check if it is robust */
if (mutex->pid > 0 &&
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
sched_gettcb(mutex->pid) == NULL)
if (mutex->pid > 0 &&
(mutex->flags & _PTHREAD_MFLAGS_ROBUST) != 0 &&
sched_gettcb(mutex->pid) == NULL)
#endif /* CONFIG_PTHREAD_MUTEX_TYPES */
#else /* CONFIG_PTHREAD_MUTEX_ROBUST */
/* This mutex is always robust, whatever type it is. */
/* This mutex is always robust, whatever type it is. */
if (mutex->pid > 0 && sched_gettcb(mutex->pid) == NULL)
if (mutex->pid > 0 && sched_gettcb(mutex->pid) == NULL)
#endif
{
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0);
{
DEBUGASSERT(mutex->pid != 0); /* < 0: available, >0 owned, ==0 error */
DEBUGASSERT((mutex->flags & _PTHREAD_MFLAGS_INCONSISTENT) != 0);
/* A thread holds the mutex, but there is no such thread. POSIX
* requires that the 'robust' mutex return EOWNERDEAD in this case.
* It is then the caller's responsibility to call pthread_mutx_consistent()
* fo fix the mutex.
*/
/* A thread holds the mutex, but there is no such thread. POSIX
* requires that the 'robust' mutex return EOWNERDEAD in this
* case. It is then the caller's responsibility to call
* pthread_mutx_consistent() to fix the mutex.
*/
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
ret = EOWNERDEAD;
}
else
mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT;
ret = EOWNERDEAD;
}
else
#endif /* !CONFIG_PTHREAD_MUTEX_UNSAFE */
{
/* Take the underlying semaphore, waiting if necessary. NOTE that
* is required to deadlock for the case of the non-robust NORMAL or
* default mutex.
*/
{
/* Take the underlying semaphore, waiting if necessary. NOTE that
* is required to deadlock for the case of the non-robust NORMAL
* or default mutex.
*/
ret = pthread_mutex_take(mutex, NULL, true);
ret = pthread_mutex_take(mutex, NULL, true);
/* If we successfully obtained the semaphore, then indicate
* that we own it.
*/
/* If we successfully obtained the semaphore, then indicate
* that we own it.
*/
if (ret == OK)
{
mutex->pid = mypid;
if (ret == OK)
{
mutex->pid = mypid;
#ifdef CONFIG_PTHREAD_MUTEX_TYPES
mutex->nlocks = 1;
mutex->nlocks = 1;
#endif
}
}
}
}
sched_unlock();
}