diff options
-rw-r--r-- | winsup/cygwin/thread.cc | 8 | ||||
-rw-r--r-- | winsup/cygwin/thread.h | 17 |
2 files changed, 19 insertions, 6 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 4d0ea274f..7c6a919c0 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1595,7 +1595,7 @@ pthread_rwlock::add_reader () { RWLOCK_READER *rd = new RWLOCK_READER; if (rd) - List_insert (readers, rd); + List_insert_nolock (readers, rd); return rd; } @@ -2165,7 +2165,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void if (prepcb) { prepcb->cb = prepare; - List_insert (MT_INTERFACE->pthread_prepare, prepcb); + List_insert_nolock (MT_INTERFACE->pthread_prepare, prepcb); } if (parentcb) { @@ -2174,7 +2174,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void while (*t) t = &(*t)->next; /* t = pointer to last next in the list */ - List_insert (*t, parentcb); + List_insert_nolock (*t, parentcb); } if (childcb) { @@ -2183,7 +2183,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void while (*t) t = &(*t)->next; /* t = pointer to last next in the list */ - List_insert (*t, childcb); + List_insert_nolock (*t, childcb); } return 0; } diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 6b699ccb6..ddb2d7dbf 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -111,7 +111,20 @@ typedef enum } verifyable_object_state; template <class list_node> inline void -List_insert (list_node *&head, list_node *node) +List_insert (fast_mutex &mx, list_node *&head, list_node *node) +{ + if (!node) + return; + mx.lock (); + do + node->next = head; + while (InterlockedCompareExchangePointer ((PVOID volatile *) &head, + node, node->next) != node->next); + mx.unlock (); +} + +template <class list_node> inline void +List_insert_nolock (list_node *&head, list_node *node) { if (!node) return; @@ -163,7 +176,7 @@ template <class list_node> class List void insert (list_node *node) { - List_insert (head, node); + List_insert (mx, head, node); } void remove (list_node *node) |