INLINE #endif /* PTW32_BUILD_INLINED */ void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node) { new_node->lock = old_node->lock; new_node->nextFlag = 0; /* Not needed - used only in initial Acquire */ new_node->readyFlag = 0; /* Not needed - we were waiting on this */ new_node->next = 0; if ((ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)new_node->lock, (PTW32_INTERLOCKED_PVOID)new_node, (PTW32_INTERLOCKED_PVOID)old_node) != old_node) { /* * A successor has queued after us, so wait for them to link to us */ while (old_node->next == 0) { sched_yield(); } new_node->next = old_node->next; } }
INLINE #endif /* PTW32_BUILD_INLINED */ void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node) { ptw32_mcs_lock_t *lock = node->lock; ptw32_mcs_local_node_t *next = (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */ if (0 == next) { /* no known successor */ if (node == (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, (PTW32_INTERLOCKED_PVOID)0, (PTW32_INTERLOCKED_PVOID)node)) { /* no successor, lock is free now */ return; } /* wait for successor */ ptw32_mcs_flag_wait(&node->nextFlag); next = (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */ } /* pass the lock */ ptw32_mcs_flag_set(&next->readyFlag); }
INLINE #endif void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node) { ptw32_mcs_lock_t *lock = node->lock; ptw32_mcs_local_node_t *next = (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); if (0 == next) { if (node == (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, (PTW32_INTERLOCKED_PVOID)0, (PTW32_INTERLOCKED_PVOID)node)) { return; } ptw32_mcs_flag_wait(&node->nextFlag); next = (ptw32_mcs_local_node_t *) PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); } ptw32_mcs_flag_set(&next->readyFlag); }
INLINE #endif /* PTW32_BUILD_INLINED */ int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) { node->lock = lock; node->nextFlag = 0; node->readyFlag = 0; node->next = 0; /* initially, no successor */ return ((PTW32_INTERLOCKED_PVOID)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, (PTW32_INTERLOCKED_PVOID)node, (PTW32_INTERLOCKED_PVOID)0) == (PTW32_INTERLOCKED_PVOID)0) ? 0 : EBUSY; }
INLINE #endif int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) { node->lock = lock; node->nextFlag = 0; node->readyFlag = 0; node->next = 0; return ((PTW32_INTERLOCKED_PVOID)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock, (PTW32_INTERLOCKED_PVOID)node, (PTW32_INTERLOCKED_PVOID)0) == (PTW32_INTERLOCKED_PVOID)0) ? 0 : EBUSY; }
INLINE #endif void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node) { new_node->lock = old_node->lock; new_node->nextFlag = 0; new_node->readyFlag = 0; new_node->next = 0; if ((ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)new_node->lock, (PTW32_INTERLOCKED_PVOID)new_node, (PTW32_INTERLOCKED_PVOID)old_node) != old_node) { while (old_node->next == 0) { sched_yield(); } new_node->next = old_node->next; } }