summaryrefslogtreecommitdiff
path: root/pthread_mutex_unlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'pthread_mutex_unlock.c')
-rw-r--r--pthread_mutex_unlock.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/pthread_mutex_unlock.c b/pthread_mutex_unlock.c
index 05677c8..7b20d79 100644
--- a/pthread_mutex_unlock.c
+++ b/pthread_mutex_unlock.c
@@ -44,10 +44,9 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
int result = 0;
pthread_mutex_t mx;
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
+ /*
+ * Let the system deal with invalid pointers.
+ */
mx = *mutex;
@@ -58,30 +57,67 @@ pthread_mutex_unlock (pthread_mutex_t * mutex)
*/
if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
{
- if (mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
- || pthread_equal (mx->ownerThread, pthread_self ()))
+ if (mx->kind == PTHREAD_MUTEX_NORMAL)
{
- if (mx->kind != PTHREAD_MUTEX_RECURSIVE_NP
- || 0 == --mx->recursive_count)
- {
- mx->ownerThread = NULL;
- EnterCriticalSection (&mx->wait_cs);
+ LONG idx;
+
+ idx = (LONG) ptw32_interlocked_compare_exchange ((PTW32_INTERLOCKED_LPLONG)
+ &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1,
+ (PTW32_INTERLOCKED_LONG) 0);
- if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ if (idx != 0)
+ {
+ if (idx > 0)
{
- /* Someone is waiting on that mutex */
- if (sem_post (&mx->wait_sema) != 0)
+ EnterCriticalSection (&mx->wait_cs);
+
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
{
- result = errno;
+ /* Someone is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
}
- }
- LeaveCriticalSection (&mx->wait_cs);
+ LeaveCriticalSection (&mx->wait_cs);
+ }
+ else
+ {
+ /*
+ * Was not locked (so can't be owned by us).
+ */
+ result = EPERM;
+ }
}
}
else
{
- result = EPERM;
+ if (pthread_equal (mx->ownerThread, pthread_self ()))
+ {
+ if (mx->kind != PTHREAD_MUTEX_RECURSIVE
+ || 0 == --mx->recursive_count)
+ {
+ mx->ownerThread = NULL;
+ EnterCriticalSection (&mx->wait_cs);
+
+ if (InterlockedDecrement (&mx->lock_idx) >= 0)
+ {
+ /* Someone is waiting on that mutex */
+ if (sem_post (&mx->wait_sema) != 0)
+ {
+ result = errno;
+ }
+ }
+
+ LeaveCriticalSection (&mx->wait_cs);
+ }
+ }
+ else
+ {
+ result = EPERM;
+ }
}
}
else