]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 5 Apr 2003 05:21:15 +0000 (05:21 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 5 Apr 2003 05:21:15 +0000 (05:21 +0000)
2003-04-04  Ulrich Drepper  <drepper@redhat.com>

* sysdeps/pthread/createthread.c (create_thread): Add some more
comments explaining when to set multiple_threads and when not.

* pthreadP.h: Define THREAD_ATOMIC_CMPXCHG_VAL and
THREAD_ATOMIC_BIT_SET if not already defined.
* sysdeps/i386/tls.h: Define THREAD_ATOMIC_CMPXCHG_VAL and
THREAD_ATOMIC_BIT_SET:
* sysdeps/x86_64/tls.h: Likewise.
* cleanup_defer.c (_pthread_cleanup_push_defer): Rewrite to use
THREAD_ATOMIC_CMPXCHG_VAL.
(_pthread_cleanup_pop_restore): Likewise.
* cancellation.c (__pthread_enable_asynccancel): Likewise.
(__pthread_enable_asynccancel_2): Likewise.
(__pthread_disable_asynccancel): Likewise.
* libc-cancellation.c (__libc_enable_asynccancel): Likewise.
(__libc_disable_asynccancel): Likewise.
* init.c (sigcancel_handler): Likewise.
* pthread_setcancelstate.c (__pthread_setcancelstate): Likewise.
* pthread_setcanceltype.c (__pthread_setcanceltype): Likewise.

nptl/ChangeLog
nptl/cancellation.c
nptl/cleanup_defer.c
nptl/init.c
nptl/libc-cancellation.c
nptl/pthread_setcancelstate.c
nptl/pthread_setcanceltype.c
nptl/sysdeps/i386/tls.h
nptl/sysdeps/pthread/createthread.c
nptl/sysdeps/x86_64/tls.h

index d8467e8cda7359828d0b1388dc96cc76a9ffc7b0..7273ece303cc4f106d8bc59a8470b3b67735e4a5 100644 (file)
@@ -1,3 +1,25 @@
+2003-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/pthread/createthread.c (create_thread): Add some more
+       comments explaining when to set multiple_threads and when not.
+
+       * pthreadP.h: Define THREAD_ATOMIC_CMPXCHG_VAL and
+       THREAD_ATOMIC_BIT_SET if not already defined.
+       * sysdeps/i386/tls.h: Define THREAD_ATOMIC_CMPXCHG_VAL and
+       THREAD_ATOMIC_BIT_SET:
+       * sysdeps/x86_64/tls.h: Likewise.
+       * cleanup_defer.c (_pthread_cleanup_push_defer): Rewrite to use
+       THREAD_ATOMIC_CMPXCHG_VAL.
+       (_pthread_cleanup_pop_restore): Likewise.
+       * cancellation.c (__pthread_enable_asynccancel): Likewise.
+       (__pthread_enable_asynccancel_2): Likewise.
+       (__pthread_disable_asynccancel): Likewise.
+       * libc-cancellation.c (__libc_enable_asynccancel): Likewise.
+       (__libc_disable_asynccancel): Likewise.
+       * init.c (sigcancel_handler): Likewise.
+       * pthread_setcancelstate.c (__pthread_setcancelstate): Likewise.
+       * pthread_setcanceltype.c (__pthread_setcanceltype): Likewise.
+
 2003-04-03  Ulrich Drepper  <drepper@redhat.com>
 
        * init.c (sigcancel_handler): Don't set EXITING_BIT here.
index d88cae3aa7e25b1dcf4bebc9312408e3d8b61a00..c7477d87df29b80df0e676070125bca5aad24c19 100644 (file)
@@ -20,7 +20,6 @@
 #include <setjmp.h>
 #include <stdlib.h>
 #include "pthreadP.h"
-#include "atomic.h"
 
 
 /* The next two functions are similar to pthread_setcanceltype() but
@@ -31,18 +30,18 @@ attribute_hidden
 __pthread_enable_asynccancel (void)
 {
   struct pthread *self = THREAD_SELF;
-  int oldval;
+  int oldval = THREAD_GETMEM (self, cancelhandling);
 
   while (1)
     {
-      oldval = THREAD_GETMEM (self, cancelhandling);
       int newval = oldval | CANCELTYPE_BITMASK;
 
       if (newval == oldval)
        break;
 
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
        {
          if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
            {
@@ -52,6 +51,9 @@ __pthread_enable_asynccancel (void)
 
          break;
        }
+
+      /* Prepare the next round.  */
+      oldval = curval;
     }
 
   return oldval;
@@ -63,17 +65,22 @@ internal_function attribute_hidden
 __pthread_enable_asynccancel_2 (int *oldvalp)
 {
   struct pthread *self = THREAD_SELF;
+  int oldval = THREAD_GETMEM (self, cancelhandling);
 
   while (1)
     {
-      int oldval = *oldvalp = THREAD_GETMEM (self, cancelhandling);
       int newval = oldval | CANCELTYPE_BITMASK;
 
       if (newval == oldval)
        break;
 
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      /* We have to store the value before enablying asynchronous
+        cancellation.  */
+      *oldvalp = oldval;
+
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
        {
          if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
            {
@@ -97,17 +104,21 @@ __pthread_disable_asynccancel (int oldtype)
     return;
 
   struct pthread *self = THREAD_SELF;
+  int oldval = THREAD_GETMEM (self, cancelhandling);
 
   while (1)
     {
-      int oldval = THREAD_GETMEM (self, cancelhandling);
       int newval = oldval & ~CANCELTYPE_BITMASK;
 
       if (newval == oldval)
        break;
 
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
        break;
+
+      /* Prepare the next round.  */
+      oldval = curval;
     }
 }
index 5d6ed0360b7877f95a775a1da8e9797b39d3f8a9..7945a0ddbb9c01f7259bd4dd668fcfe2180cc409 100644 (file)
@@ -18,7 +18,6 @@
    02111-1307 USA.  */
 
 #include "pthreadP.h"
-#include <atomic.h>
 
 
 void
@@ -37,13 +36,19 @@ _pthread_cleanup_push_defer (buffer, routine, arg)
 
   /* Disable asynchronous cancellation for now.  */
   if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0))
-    {
-      while (atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                  cancelhandling
-                                                  & ~CANCELTYPE_BITMASK,
-                                                  cancelhandling))
-       cancelhandling = self->cancelhandling;
-    }
+    while (1)
+      {
+       int newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+                                               cancelhandling
+                                               & ~CANCELTYPE_BITMASK,
+                                               cancelhandling);
+       if (__builtin_expect (newval == cancelhandling, 1))
+         /* Successfully replaced the value.  */
+         break;
+
+       /* Prepare for the next round.  */
+       cancelhandling = newval;
+      }
 
   buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
                          ? PTHREAD_CANCEL_ASYNCHRONOUS
@@ -53,6 +58,7 @@ _pthread_cleanup_push_defer (buffer, routine, arg)
 }
 strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer)
 
+
 void
 _pthread_cleanup_pop_restore (buffer, execute)
      struct _pthread_cleanup_buffer *buffer;
@@ -67,11 +73,19 @@ _pthread_cleanup_pop_restore (buffer, execute)
       && ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
          & CANCELTYPE_BITMASK) == 0)
     {
-      while (atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                  cancelhandling
-                                                  | CANCELTYPE_BITMASK,
-                                                  cancelhandling))
-       cancelhandling = self->cancelhandling;
+      while (1)
+       {
+         int newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+                                                 cancelhandling
+                                                 | CANCELTYPE_BITMASK,
+                                                 cancelhandling);
+         if (__builtin_expect (newval == cancelhandling, 1))
+           /* Successfully replaced the value.  */
+           break;
+
+         /* Prepare for the next round.  */
+         cancelhandling = newval;
+       }
 
       CANCELLATION_P (self);
     }
index 9d557cc938c081dfd2b815c67af7c19e094cf4ff..7a6883f4cb2435601f1b6ad843271b71fc984465 100644 (file)
@@ -135,20 +135,21 @@ sigcancel_handler (int sig __attribute ((unused)))
 {
   struct pthread *self = THREAD_SELF;
 
+  int oldval = THREAD_GETMEM (self, cancelhandling);
   while (1)
     {
       /* We are canceled now.  When canceled by another thread this flag
         is already set but if the signal is directly send (internally or
         from another process) is has to be done here.  */
-      int oldval = THREAD_GETMEM (self, cancelhandling);
       int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
 
       if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
        /* Already canceled or exiting.  */
        break;
 
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (curval == oldval)
        {
          /* Set the return value.  */
          THREAD_SETMEM (self, result, PTHREAD_CANCELED);
@@ -160,6 +161,8 @@ sigcancel_handler (int sig __attribute ((unused)))
 
          break;
        }
+
+      oldval = curval;
     }
 }
 
index 344a2181c840d3c0ecb7e84373dd6abbbb890229..72a6d108fddb5261c870be9c0c48cefdbca48ae3 100644 (file)
@@ -33,13 +33,11 @@ attribute_hidden
 __libc_enable_asynccancel (void)
 {
   struct pthread *self = THREAD_SELF;
-  int oldval;
-  int newval;
+  int oldval = THREAD_GETMEM (self, cancelhandling);
 
-  do
+  while (1)
     {
-      oldval = THREAD_GETMEM (self, cancelhandling);
-      newval = oldval | CANCELTYPE_BITMASK;
+      int newval = oldval | CANCELTYPE_BITMASK;
 
       if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0))
        {
@@ -47,10 +45,14 @@ __libc_enable_asynccancel (void)
          if ((oldval & EXITING_BITMASK) != 0)
            break;
 
-         if (atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                   newval, oldval))
-           /* Somebody else modified the word, try again.  */
-           continue;
+         int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+                                                 newval, oldval);
+         if (__builtin_expect (curval != oldval, 0))
+           {
+             /* Somebody else modified the word, try again.  */
+             oldval = curval;
+             continue;
+           }
 
          THREAD_SETMEM (self, result, PTHREAD_CANCELED);
 
@@ -58,9 +60,15 @@ __libc_enable_asynccancel (void)
 
          /* NOTREACHED */
        }
+
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
+       break;
+
+      /* Prepare the next round.  */
+      oldval = curval;
     }
-  while (atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                              newval, oldval));
 
   return oldval;
 }
@@ -76,19 +84,23 @@ __libc_disable_asynccancel (int oldtype)
     return;
 
   struct pthread *self = THREAD_SELF;
-  int oldval;
-  int newval;
+  int oldval = THREAD_GETMEM (self, cancelhandling);
 
-  do
+  while (1)
     {
-      oldval = THREAD_GETMEM (self, cancelhandling);
-      newval = oldval & ~CANCELTYPE_BITMASK;
+      int newval = oldval & ~CANCELTYPE_BITMASK;
 
       if (newval == oldval)
        break;
+
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
+       break;
+
+      /* Prepare the next round.  */
+      oldval = curval;
     }
-  while (atomic_compare_and_exchange_bool_acq (&self->cancelhandling, newval,
-                                              oldval));
 }
 
 #endif
index a6af063d679e54990e2835500366e35ccf1bf635..a452c2ec4612e8153c02290aebdd641cfbc68517 100644 (file)
@@ -34,9 +34,9 @@ __pthread_setcancelstate (state, oldstate)
 
   self = THREAD_SELF;
 
+  int oldval = THREAD_GETMEM (self, cancelhandling);
   while (1)
     {
-      int oldval = THREAD_GETMEM (self, cancelhandling);
       int newval = (state == PTHREAD_CANCEL_DISABLE
                    ? oldval | CANCELSTATE_BITMASK
                    : oldval & ~CANCELSTATE_BITMASK);
@@ -54,14 +54,18 @@ __pthread_setcancelstate (state, oldstate)
 
       /* Update the cancel handling word.  This has to be done
         atomically since other bits could be modified as well.  */
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
        {
          if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
            __do_cancel ();
 
          break;
        }
+
+      /* Prepare for the next round.  */
+      oldval = curval;
     }
 
   return 0;
index 5a046351b906245ff5d97b2a3000553a1885df89..bbe87ba64bb1b4eff079a60348faf0a79817faf8 100644 (file)
@@ -34,9 +34,9 @@ __pthread_setcanceltype (type, oldtype)
 
   self = THREAD_SELF;
 
+  int oldval = THREAD_GETMEM (self, cancelhandling);
   while (1)
     {
-      int oldval = THREAD_GETMEM (self, cancelhandling);
       int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
                    ? oldval | CANCELTYPE_BITMASK
                    : oldval & ~CANCELTYPE_BITMASK);
@@ -54,8 +54,9 @@ __pthread_setcanceltype (type, oldtype)
 
       /* Update the cancel handling word.  This has to be done
         atomically since other bits could be modified as well.  */
-      if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
-                                                 newval, oldval))
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+                                             oldval);
+      if (__builtin_expect (curval == oldval, 1))
        {
          if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
            {
@@ -65,6 +66,9 @@ __pthread_setcanceltype (type, oldtype)
 
          break;
        }
+
+      /* Prepare for the next round.  */
+      oldval = curval;
     }
 
   return 0;
index 7fe2222c68bc3911f5495c4bb64815aeff9a5478..4f2e8180d30a0635f50c0aa81544de2fb9b9f408 100644 (file)
@@ -169,6 +169,14 @@ union user_desc_init
 # define INIT_SYSINFO
 #endif
 
+#ifndef LOCK
+# ifdef UP
+#  define LOCK  /* nothing */
+# else
+#  define LOCK "lock;"
+# endif
+#endif
+
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
@@ -352,6 +360,32 @@ union user_desc_init
        }})
 
 
+/* Atomic compare and exchange on TLS, returning old value.  */
+#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \
+  ({ __typeof (descr->member) __ret;                                         \
+     __typeof (oldval) __old = (oldval);                                     \
+     if (sizeof (descr->member) == 4)                                        \
+       asm volatile (LOCK "cmpxchgl %2, %%gs:%P3"                            \
+                    : "=a" (__ret)                                           \
+                    : "0" (__old), "r" (newval),                             \
+                      "i" (offsetof (struct pthread, member)));              \
+     else                                                                    \
+       /* Not necessary for other sizes in the moment.  */                   \
+       abort ();                                                             \
+     __ret; })
+
+
+/* Atomic set bit.  */
+#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
+  (void) ({ if (sizeof ((descr)->member) == 4)                               \
+             asm volatile (LOCK "orl %1, %%gs:%P0"                           \
+                           :: "i" (offsetof (struct pthread, member)),       \
+                              "ir" (1 << (bit)));                            \
+           else                                                              \
+             /* Not necessary for other sizes in the moment.  */             \
+             abort (); })
+
+
 /* Call the user-provided thread function.  */
 #define CALL_THREAD_FCT(descr) \
   ({ void *__res;                                                            \
index fae744f298efb25879dd3c8adae39d9845d73a0b..9d00e4e1355ac77ffafbf18934a6f7e1a17cc011 100644 (file)
@@ -83,11 +83,11 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
            /* Failed.  */
            return errno;
 
+         /* We now have for sure more than one thread.  The main
+            thread might not yet have the flag set.  No need to set
+            the global variable again if this is what we use.  */
 #ifdef TLS_MULTIPLE_THREADS_IN_TCB
-         /* We now have for sure more than one thread.  */
-         pd->header.multiple_threads = 1;
-#else
-         __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
+         THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
 #endif
 
          /* Now fill in the information about the new thread in
@@ -155,8 +155,10 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
     /* Failed.  */
     return errno;
 
+  /* We now have for sure more than one thread.  The main thread might
+     not yet have the flag set.  No need to set the global variable
+     again if this is what we use.  */
 #ifdef TLS_MULTIPLE_THREADS_IN_TCB
-  /* We now have for sure more than one thread.  */
   THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
 #endif
 
index f382db2861e3121a4eba244e86dc5ced03f9c3a5..dec1b5d1b76cedb8ca061b5b49a253c7cbeb5f84 100644 (file)
@@ -253,6 +253,32 @@ typedef struct
        }})
 
 
+/* Atomic compare and exchange on TLS, returning old value.  */
+#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \
+  ({ __typeof (descr->member) __ret;                                         \
+     __typeof (oldval) __old = (oldval);                                     \
+     if (sizeof (descr->member) == 4)                                        \
+       asm volatile (LOCK "cmpxchgl %2, %%fs:%P3"                            \
+                    : "=a" (__ret)                                           \
+                    : "0" (__old), "r" (newval),                             \
+                      "i" (offsetof (struct pthread, member)));              \
+     else                                                                    \
+       /* Not necessary for other sizes in the moment.  */                   \
+       abort ();                                                             \
+     __ret; })
+
+
+/* Atomic set bit.  */
+#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
+  (void) ({ if (sizeof ((descr)->member) == 4)                               \
+             asm volatile (LOCK "orl %1, %%fs:%P0"                           \
+                           :: "i" (offsetof (struct pthread, member)),       \
+                              "ir" (1 << (bit)));                            \
+           else                                                              \
+             /* Not necessary for other sizes in the moment.  */             \
+             abort (); })
+
+
 #define CALL_THREAD_FCT(descr) \
   ({ void *__res;                                                            \
      asm volatile ("movq %%fs:%P2, %%rdi\n\t"                                \