aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Pfaff <tpfaff@gmx.net>2003-12-01 22:10:57 +0000
committerThomas Pfaff <tpfaff@gmx.net>2003-12-01 22:10:57 +0000
commit94d2416049fd158471da45380df829ffce203671 (patch)
tree21c164059860c586b4a8a72c8d0ecf42f6d40695
parentbd16a3a8a8a1b0f2971e6bac6c896320f02208c2 (diff)
downloadnewlib-94d2416049fd158471da45380df829ffce203671.zip
newlib-94d2416049fd158471da45380df829ffce203671.tar.gz
newlib-94d2416049fd158471da45380df829ffce203671.tar.bz2
* 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.
-rw-r--r--winsup/cygwin/ChangeLog12
-rw-r--r--winsup/cygwin/thread.cc24
-rw-r--r--winsup/cygwin/thread.h30
3 files changed, 31 insertions, 35 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 1030e4b..a4d21b2 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* Makefile.in (OBSOLETE_FUNCTIONS): Add fcntl.
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index db12e5c..cb99be0 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -1259,7 +1259,7 @@ pthread_rwlock::unlock ()
void
pthread_rwlock::add_reader (struct RWLOCK_READER *rd)
{
- List_insert (readers_mx, readers, rd);
+ List_insert (readers, rd);
}
void
@@ -1998,22 +1998,6 @@ pthread::cancel (pthread_t thread)
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
pthread::atforkprepare (void)
{
@@ -2090,7 +2074,7 @@ pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void
if (prepcb)
{
prepcb->cb = prepare;
- prepcb->next = (callback *) InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb);
+ List_insert (MT_INTERFACE->pthread_prepare, prepcb);
}
if (parentcb)
{
@@ -2099,7 +2083,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 */
- parentcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) parentcb);
+ List_insert (*t, parentcb);
}
if (childcb)
{
@@ -2108,7 +2092,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 */
- childcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) childcb);
+ List_insert (*t, childcb);
}
return 0;
}
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 5dd9857..0cba6cd 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -224,14 +224,13 @@ verifyable_object_state verifyable_object_isvalid (void const *, long);
verifyable_object_state verifyable_object_isvalid (void const *, long, 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)
return;
- mx.lock ();
- node->next = head;
- head = node;
- mx.unlock ();
+ do
+ node->next = head;
+ while (InterlockedCompareExchangePointer (&head, node, node->next) != node->next);
}
template <class list_node> inline void
@@ -240,16 +239,17 @@ List_remove (fast_mutex &mx, list_node *&head, list_node *node)
if (!node)
return;
mx.lock ();
- if (node == head)
- head = head->next;
- else if (head)
+ if (head)
{
- list_node *cur = head;
-
- while (cur->next && node != cur->next)
- cur = cur->next;
- if (node == cur->next)
- cur->next = cur->next->next;
+ if (InterlockedCompareExchangePointer (&head, node->next, node) != node)
+ {
+ list_node *cur = head;
+
+ while (cur->next && node != cur->next)
+ cur = cur->next;
+ if (node == cur->next)
+ cur->next = cur->next->next;
+ }
}
mx.unlock ();
}
@@ -274,7 +274,7 @@ template <class list_node> class List
void insert (list_node *node)
{
- List_insert (mx, head, node);
+ List_insert (head, node);
}
void remove (list_node *node)