pthread_mutex_unlock(): Missing check for the case
where pthread_mutex_unlock() is called when the mutex is not locked.
In this case, it would increment the underlying semaphore above 1.
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
+#include <assert.h>
#include <errno.h>
#include <debug.h>
/****************************************************************************
* Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: pthread_mutex_islocked
+ *
+ * Description:
+ * Return true is the mutex is locked.
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * Returns true if the mutex is locked
+ *
+ ****************************************************************************/
+
+static inline bool pthread_mutex_islocked(FAR pthread_mutex_t *mutex)
+{
+ int semcount = mutex->sem.semcount;
+
+ /* The underlying semaphore should have a count less than 2:
+ *
+ * 1 == mutex is unlocked.
+ * 0 == mutex is locked with no waiters
+ * -n == mutex is locked with 'n' waiters.
+ */
+
+ DEBUGASSERT(semcount < 2);
+ return semcount < 1;
+}
/****************************************************************************
* Public Functions
int pthread_mutex_unlock(FAR pthread_mutex_t *mutex)
{
- int ret = EINVAL;
+ int ret = OK;
svdbg("mutex=0x%p\n", mutex);
DEBUGASSERT(mutex != NULL);
+ if (mutex == NULL) {
+ return EINVAL;
+ }
/* Make sure the semaphore is stable while we make the following checks.
* This all needs to be one atomic action.
*/
sched_lock();
- if (mutex != NULL) {
+
+ /* The unlock operation is only performed if the mutex is actually locked.
+ * If the mutex is not locked, then SUCCESS will be returned (there is
+ * no error return value specified for this case).
+ */
+ if (pthread_mutex_islocked(mutex)) {
#if !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) || defined(CONFIG_PTHREAD_MUTEX_TYPES)
/* Does the calling thread own the semaphore? If no, should we return
* an error?
