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;
|
RWLOCK_READER *rd = new RWLOCK_READER;
|
||||||
if (rd)
|
if (rd)
|
||||||
List_insert (readers, rd);
|
List_insert_nolock (readers, rd);
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2165,7 +2165,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
|
||||||
if (prepcb)
|
if (prepcb)
|
||||||
{
|
{
|
||||||
prepcb->cb = prepare;
|
prepcb->cb = prepare;
|
||||||
List_insert (MT_INTERFACE->pthread_prepare, prepcb);
|
List_insert_nolock (MT_INTERFACE->pthread_prepare, prepcb);
|
||||||
}
|
}
|
||||||
if (parentcb)
|
if (parentcb)
|
||||||
{
|
{
|
||||||
|
@ -2174,7 +2174,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
|
||||||
while (*t)
|
while (*t)
|
||||||
t = &(*t)->next;
|
t = &(*t)->next;
|
||||||
/* t = pointer to last next in the list */
|
/* t = pointer to last next in the list */
|
||||||
List_insert (*t, parentcb);
|
List_insert_nolock (*t, parentcb);
|
||||||
}
|
}
|
||||||
if (childcb)
|
if (childcb)
|
||||||
{
|
{
|
||||||
|
@ -2183,7 +2183,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
|
||||||
while (*t)
|
while (*t)
|
||||||
t = &(*t)->next;
|
t = &(*t)->next;
|
||||||
/* t = pointer to last next in the list */
|
/* t = pointer to last next in the list */
|
||||||
List_insert (*t, childcb);
|
List_insert_nolock (*t, childcb);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,20 @@ typedef enum
|
||||||
} verifyable_object_state;
|
} verifyable_object_state;
|
||||||
|
|
||||||
template <class list_node> inline void
|
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)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
@ -163,7 +176,7 @@ template <class list_node> class List
|
||||||
|
|
||||||
void insert (list_node *node)
|
void insert (list_node *node)
|
||||||
{
|
{
|
||||||
List_insert (head, node);
|
List_insert (mx, head, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove (list_node *node)
|
void remove (list_node *node)
|
||||||
|
|
Loading…
Reference in New Issue