/* * ptw32_mcs_lock_acquire -- acquire an MCS lock. * * See: * J. M. Mellor-Crummey and M. L. Scott. * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors. * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991. */ INLINE void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) { ptw32_mcs_local_node_t *pred; node->lock = lock; node->nextFlag = 0; node->readyFlag = 0; node->next = 0; /* initially, no successor */ /* queue for the lock */ pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((LPLONG)lock, (LONG)node); if (0 != pred) { /* the lock was not free. link behind predecessor. */ pred->next = node; ptw32_mcs_flag_set(&pred->nextFlag); ptw32_mcs_flag_wait(&node->readyFlag); } }
INLINE int pthread_mutex_unlock (pthread_mutex_t * mutex) { int result = 0; pthread_mutex_t mx; /* * Let the system deal with invalid pointers. */ mx = *mutex; /* * If the thread calling us holds the mutex then there is no * race condition. If another thread holds the * lock then we shouldn't be in here. */ if (!ptw32_static_mutex_enable || (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)) { if (mx->kind == PTHREAD_MUTEX_NORMAL) { LONG idx; idx = (LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx, (LONG) 0); if (idx != 0) { if (idx < 0) { /* * Someone may be waiting on that mutex. */ if (SetEvent (mx->event) == 0) { result = EINVAL; } } } else { /* * Was not locked (so can't be owned by us). */ result = EPERM; } } else { if (pthread_equal (mx->ownerThread, pthread_self ())) { if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 0 == --mx->recursive_count) { mx->ownerThread.p = NULL; if ((LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx, (LONG) 0) < 0) { /* Someone may be waiting on that mutex */ if (SetEvent (mx->event) == 0) { result = EINVAL; } } } } else { result = EPERM; } } } else { result = EINVAL; } return (result); }
int pthread_mutex_lock (pthread_mutex_t * mutex) { int result = 0; pthread_mutex_t mx; /* * Let the system deal with invalid pointers. */ /* * We do a quick check to see if we need to do more work * to initialise a static mutex. We check * again inside the guarded section of ptw32_mutex_check_need_init() * to avoid race conditions. */ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) { if ((result = ptw32_mutex_check_need_init (mutex)) != 0) { return (result); } } mx = *mutex; if (mx->kind == PTHREAD_MUTEX_NORMAL) { if ((LONG) PTW32_INTERLOCKED_EXCHANGE( (LPLONG) &mx->lock_idx, (LONG) 1) != 0) { while ((LONG) PTW32_INTERLOCKED_EXCHANGE( (LPLONG) &mx->lock_idx, (LONG) -1) != 0) { if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) { result = EINVAL; break; } } } } else { pthread_t self = pthread_self(); if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, (PTW32_INTERLOCKED_LONG) 1, (PTW32_INTERLOCKED_LONG) 0) == 0) { mx->recursive_count = 1; mx->ownerThread = self; } else { if (pthread_equal (mx->ownerThread, self)) { if (mx->kind == PTHREAD_MUTEX_RECURSIVE) { mx->recursive_count++; } else { result = EDEADLK; } } else { while ((LONG) PTW32_INTERLOCKED_EXCHANGE( (LPLONG) &mx->lock_idx, (LONG) -1) != 0) { if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) { result = EINVAL; break; } } if (0 == result) { mx->recursive_count = 1; mx->ownerThread = self; } } } } return (result); }