mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-27 19:17:18 +08:00
fix race condition in List_insert
Revert mx parameter and mutex lock while operating the list. Mutex was removed with 94d24160 informing that: 'Use InterlockedCompareExchangePointer to ensure race safeness without using a mutex.' But it does not. Calling pthread_mutex_init and pthread_mutex_destroy from two or more threads occasionally leads to hang in pthread_mutex_destroy. To not change the behaviour of other cases where List_insert was called, List_insert_nolock is added.
This commit is contained in:
parent
bc0e8a9961
commit
1a821390d1
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user