* thread.cc (pthread_rwlock::add_reader): Remove mx parameter for
List_insert call. (pthread::prepare): Ensure race safeness when adding function pointers to atfork lists by using List_insert. * thread.h (List_insert): Use InterlockedCompareExchangePointer to ensure race safeness without using a mutex. (List_remove): Use InterlockedCompareExchangePointer to ensure race safeness with List_insert. (List::insert): Remove mx parameter for List_insert call.
This commit is contained in:
parent
bd16a3a8a8
commit
94d2416049
|
@ -1,3 +1,15 @@
|
||||||
|
2003-12-01 Thomas Pfaff <tpfaff@gmx.net>
|
||||||
|
|
||||||
|
* thread.cc (pthread_rwlock::add_reader): Remove mx parameter for
|
||||||
|
List_insert call.
|
||||||
|
(pthread::prepare): Ensure race safeness when adding function
|
||||||
|
pointers to atfork lists by using List_insert.
|
||||||
|
* thread.h (List_insert): Use InterlockedCompareExchangePointer to
|
||||||
|
ensure race safeness without using a mutex.
|
||||||
|
(List_remove): Use InterlockedCompareExchangePointer to
|
||||||
|
ensure race safeness with List_insert.
|
||||||
|
(List::insert): Remove mx parameter for List_insert call.
|
||||||
|
|
||||||
2003-12-01 Corinna Vinschen <corinna@vinschen.de>
|
2003-12-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* Makefile.in (OBSOLETE_FUNCTIONS): Add fcntl.
|
* Makefile.in (OBSOLETE_FUNCTIONS): Add fcntl.
|
||||||
|
|
|
@ -1259,7 +1259,7 @@ pthread_rwlock::unlock ()
|
||||||
void
|
void
|
||||||
pthread_rwlock::add_reader (struct RWLOCK_READER *rd)
|
pthread_rwlock::add_reader (struct RWLOCK_READER *rd)
|
||||||
{
|
{
|
||||||
List_insert (readers_mx, readers, rd);
|
List_insert (readers, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1998,22 +1998,6 @@ pthread::cancel (pthread_t thread)
|
||||||
return thread->cancel ();
|
return thread->cancel ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Races in pthread_atfork:
|
|
||||||
We are race safe in that any additions to the lists are made via
|
|
||||||
InterlockedExchangePointer.
|
|
||||||
However, if the user application doesn't perform syncronisation of some sort
|
|
||||||
It's not guaranteed that a near simultaneous call to pthread_atfork and fork
|
|
||||||
will result in the new atfork handlers being calls.
|
|
||||||
More rigorous internal syncronisation isn't needed as the user program isn't
|
|
||||||
guaranteeing their own state.
|
|
||||||
|
|
||||||
as far as multiple calls to pthread_atfork, the worst case is simultaneous calls
|
|
||||||
will result in an indeterminate order for parent and child calls (what gets inserted
|
|
||||||
first isn't guaranteed.)
|
|
||||||
|
|
||||||
There is one potential race... Does the result of InterlockedExchangePointer
|
|
||||||
get committed to the return location _before_ any context switches can occur?
|
|
||||||
If yes, we're safe, if no, we're not. */
|
|
||||||
void
|
void
|
||||||
pthread::atforkprepare (void)
|
pthread::atforkprepare (void)
|
||||||
{
|
{
|
||||||
|
@ -2090,7 +2074,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
|
||||||
if (prepcb)
|
if (prepcb)
|
||||||
{
|
{
|
||||||
prepcb->cb = prepare;
|
prepcb->cb = prepare;
|
||||||
prepcb->next = (callback *) InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb);
|
List_insert (MT_INTERFACE->pthread_prepare, prepcb);
|
||||||
}
|
}
|
||||||
if (parentcb)
|
if (parentcb)
|
||||||
{
|
{
|
||||||
|
@ -2099,7 +2083,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 */
|
||||||
parentcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) parentcb);
|
List_insert (*t, parentcb);
|
||||||
}
|
}
|
||||||
if (childcb)
|
if (childcb)
|
||||||
{
|
{
|
||||||
|
@ -2108,7 +2092,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 */
|
||||||
childcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) childcb);
|
List_insert (*t, childcb);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,14 +224,13 @@ verifyable_object_state verifyable_object_isvalid (void const *, long);
|
||||||
verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
|
verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
|
||||||
|
|
||||||
template <class list_node> inline void
|
template <class list_node> inline void
|
||||||
List_insert (fast_mutex &mx, list_node *&head, list_node *node)
|
List_insert (list_node *&head, list_node *node)
|
||||||
{
|
{
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
mx.lock ();
|
do
|
||||||
node->next = head;
|
node->next = head;
|
||||||
head = node;
|
while (InterlockedCompareExchangePointer (&head, node, node->next) != node->next);
|
||||||
mx.unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class list_node> inline void
|
template <class list_node> inline void
|
||||||
|
@ -240,16 +239,17 @@ List_remove (fast_mutex &mx, list_node *&head, list_node *node)
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
mx.lock ();
|
mx.lock ();
|
||||||
if (node == head)
|
if (head)
|
||||||
head = head->next;
|
|
||||||
else if (head)
|
|
||||||
{
|
{
|
||||||
list_node *cur = head;
|
if (InterlockedCompareExchangePointer (&head, node->next, node) != node)
|
||||||
|
{
|
||||||
|
list_node *cur = head;
|
||||||
|
|
||||||
while (cur->next && node != cur->next)
|
while (cur->next && node != cur->next)
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
if (node == cur->next)
|
if (node == cur->next)
|
||||||
cur->next = cur->next->next;
|
cur->next = cur->next->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mx.unlock ();
|
mx.unlock ();
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ template <class list_node> class List
|
||||||
|
|
||||||
void insert (list_node *node)
|
void insert (list_node *node)
|
||||||
{
|
{
|
||||||
List_insert (mx, head, node);
|
List_insert (head, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove (list_node *node)
|
void remove (list_node *node)
|
||||||
|
|
Loading…
Reference in New Issue