summaryrefslogtreecommitdiff
path: root/ptw32_MCS_lock.c
diff options
context:
space:
mode:
authorrpj <rpj>2010-06-20 03:31:18 +0000
committerrpj <rpj>2010-06-20 03:31:18 +0000
commita3ea0b24409b89bd08c0a2268dbae834724734df (patch)
tree4629fd085756226f0cee8beba4faf66466ef0410 /ptw32_MCS_lock.c
parent135d6f060c5e5232311af77bd0d0f500e861290c (diff)
See ChangeLogs: preparing for new release.
Diffstat (limited to 'ptw32_MCS_lock.c')
-rw-r--r--ptw32_MCS_lock.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/ptw32_MCS_lock.c b/ptw32_MCS_lock.c
index 6b797c5..80e0f5a 100644
--- a/ptw32_MCS_lock.c
+++ b/ptw32_MCS_lock.c
@@ -89,8 +89,8 @@
* }
*/
-#include "pthread.h"
#include "implement.h"
+#include "pthread.h"
/*
* ptw32_mcs_flag_set -- notify another thread about an event.
@@ -159,8 +159,8 @@ ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
node->next = 0; /* initially, no successor */
/* queue for the lock */
- pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((LPLONG)lock,
- (LONG)node);
+ pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((PTW32_INTERLOCKED_LPLONG)lock,
+ (PTW32_INTERLOCKED_LONG)node);
if (0 != pred)
{
@@ -184,7 +184,8 @@ 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 *)
- InterlockedExchangeAdd((LPLONG)&node->next, 0); /* MBR fence */
+ InterlockedExchangeAdd((LPLONG)&node->next,
+ (LONG)0); /* MBR fence */
if (0 == next)
{
@@ -208,3 +209,55 @@ ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node)
/* pass the lock */
ptw32_mcs_flag_set(&next->readyFlag);
}
+
+/*
+ * ptw32_mcs_lock_try_acquire
+ */
+INLINE 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_LPLONG)PTW32_INTERLOCKED_COMPARE_EXCHANGE(
+ (PTW32_INTERLOCKED_LPLONG)lock,
+ (PTW32_INTERLOCKED_LONG)node,
+ (PTW32_INTERLOCKED_LONG)0)
+ == (PTW32_INTERLOCKED_LPLONG)0) ? 0 : EBUSY;
+}
+
+/*
+ * ptw32_mcs_node_substitute -- move an MCS lock local node, usually from thread
+ * space to, for example, global space so that another thread can release
+ * the lock on behalf of the current lock owner.
+ *
+ * Example: used in pthread_barrier_wait where we want the last thread out of
+ * the barrier to release the lock owned by the last thread to enter the barrier
+ * (the one that releases all threads but not necessarily the last to leave).
+ *
+ * Should only be called by the thread that has the lock.
+ */
+INLINE void
+ptw32_mcs_node_substitute (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((PTW32_INTERLOCKED_LPLONG)new_node->lock,
+ (PTW32_INTERLOCKED_LONG)new_node,
+ (PTW32_INTERLOCKED_LONG)old_node) != old_node)
+ {
+ /*
+ * A successor has queued after us, so wait for them to link to us
+ */
+ while (old_node->next == 0)
+ {
+ Sleep(0);
+ }
+ new_node->next = old_node->next;
+ }
+}