]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update.
authorUlrich Drepper <drepper@redhat.com>
Fri, 14 Feb 2003 18:33:54 +0000 (18:33 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 14 Feb 2003 18:33:54 +0000 (18:33 +0000)
* descr.h: Define CANCELING_BIT and CANCELING_BITMASK.  Introduce
after CANCELTYPE_BIT, move the other bits up.  Update CANCEL_RESTMASK.
* init.c (sigcancel_handler): Also set CANCELING_BITMASK bit in newval.
* pthread_cancel.c (pthread_cancel): Likewise.  Also set CANCELING_BIT
if asynchronous canceling is enabled.
* pthread_join.c (pthread_join): When recognizing circular joins,
take into account the other thread might be already canceled.
* Makefile (tests): Add tst-join5.
* tst-join5.c: New file.

nptl/ChangeLog
nptl/Makefile
nptl/descr.h
nptl/init.c
nptl/pthread_cancel.c
nptl/pthread_join.c
nptl/tst-cancel4.c
nptl/tst-join5.c [new file with mode: 0644]

index 8e5f206156d8cb77b6051c8592be95bd42c06252..3b02b45b88720929b06c29be5d176d7644daf393 100644 (file)
@@ -1,5 +1,15 @@
 2003-02-14  Ulrich Drepper  <drepper@redhat.com>
 
+       * descr.h: Define CANCELING_BIT and CANCELING_BITMASK.  Introduce
+       after CANCELTYPE_BIT, move the other bits up.  Update CANCEL_RESTMASK.
+       * init.c (sigcancel_handler): Also set CANCELING_BITMASK bit in newval.
+       * pthread_cancel.c (pthread_cancel): Likewise.  Also set CANCELING_BIT
+       if asynchronous canceling is enabled.
+       * pthread_join.c (pthread_join): When recognizing circular joins,
+       take into account the other thread might be already canceled.
+       * Makefile (tests): Add tst-join5.
+       * tst-join5.c: New file.
+
        * Makefile (tests): Add tst-join4.
        * tst-join4.c: New file.
 
index fbd78791ec3059b17b3b769e8d5e8aa7271274f2..65c90c2182db913b76705dbf06285a96bdf322b1 100644 (file)
@@ -137,7 +137,7 @@ tests = tst-attr1 tst-attr2 \
        tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 \
        tst-barrier1 tst-barrier2 tst-barrier3 \
        tst-basic1 tst-basic2 \
-       tst-join1 tst-join2 tst-join3 tst-join4 \
+       tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \
        tst-tsd1 tst-tsd2 \
        tst-fork1 tst-fork2 tst-fork3 \
        tst-atfork1 \
index 3fe04ec2aa2f3e41519bfdc257179d8fe16d2b71..e96f538c68b60d4399a2761d5c2516167ee66c91 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -127,17 +127,20 @@ struct pthread
   /* Bit set if asynchronous cancellation mode is selected.  */
 #define CANCELTYPE_BIT         1
 #define CANCELTYPE_BITMASK     0x02
+  /* Bit set if canceling has been initiated.  */
+#define CANCELING_BIT          2
+#define CANCELING_BITMASK      0x04
   /* Bit set if canceled.  */
-#define CANCELED_BIT           2
-#define CANCELED_BITMASK       0x04
+#define CANCELED_BIT           3
+#define CANCELED_BITMASK       0x08
   /* Bit set if thread is exiting.  */
-#define EXITING_BIT            3
-#define EXITING_BITMASK                0x08
+#define EXITING_BIT            4
+#define EXITING_BITMASK                0x10
   /* Bit set if thread terminated and TCB is freed.  */
-#define TERMINATED_BIT         4
-#define TERMINATED_BITMASK     0x10
+#define TERMINATED_BIT         5
+#define TERMINATED_BITMASK     0x20
   /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK                0xffffffe0
+#define CANCEL_RESTMASK                0xffffffc0
 
 #define CANCEL_ENABLED_AND_CANCELED(value) \
   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK              \
index 92afd09546d4eb7cdc5eb6540bbdacb4d2e93572..4d30084efb2d8eee0a2f1c769a09fafeabbd6b7d 100644 (file)
@@ -130,7 +130,7 @@ sigcancel_handler (int sig __attribute ((unused)))
         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 | CANCELED_BITMASK;
+      int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
 
       if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
        /* Already canceled or exiting.  */
index a189b6eac9156f185f45d42f24170f9cb1a6af2b..0dd97a27e52bd1c36793f856168034ec9c26fc1d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -31,7 +31,7 @@ pthread_cancel (th)
   while (1)
     {
       int oldval = pd->cancelhandling;
-      int newval = oldval | CANCELED_BITMASK;
+      int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
 
       /* Avoid doing unnecessary work.  The atomic operation can
         potentially be expensive if the bug has to be locked and
@@ -44,6 +44,9 @@ pthread_cancel (th)
         expensive.  */
       if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
        {
+         /* Mark the cancellation as "in progress".  */
+         atomic_bit_set (&pd->cancelhandling, CANCELING_BIT);
+
          /* The cancellation handler will take care of marking the
             thread as canceled.  */
          __pthread_kill (th, SIGCANCEL);
index 4edbced2c12bed2764f9b13b2563de95a4f31c71..5954af778db04c9bca3b63afb2ec26d5ca111686 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -50,7 +50,11 @@ pthread_join (threadid, thread_return)
     return EINVAL;
 
   self = THREAD_SELF;
-  if (pd == self || self->joinid == pd)
+  if (pd == self
+      || (self->joinid == pd
+         && (pd->cancelhandling
+             & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+                | TERMINATED_BITMASK)) == 0))
     /* This is a deadlock situation.  The threads are waiting for each
        other to finish.  Note that this is a "may" error.  To be 100%
        sure we catch this error we would have to lock the data
index 7ab7bd60dab56c091db521c423fd14410c279026..eb5eb9e15c64bba752ffa965e70771b586985888 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
      mq_send()             mq_timedreceive()  mq_timedsend()
      msgrcv()              msgsnd()           msync()
                            open()             pause()
-                           pread()            pthread_cond_timedwait()
-     pthread_cond_wait()   pthread_join()     pthread_testcancel()
+                           pread()
+                          pthread_join()     pthread_testcancel()
      putmsg()              putpmsg()          pwrite()
                                               recv()
      recvfrom()            recvmsg()
      sem_timedwait()       sem_wait()         send()
      sendmsg()             sendto()           sigpause()
      sigsuspend()          sigtimedwait()     sigwait()
-     sigwaitinfo()                            system()
+     sigwaitinfo()
      tcdrain()
 
    Since STREAMS are not supported in the standard Linux kernel there
diff --git a/nptl/tst-join5.c b/nptl/tst-join5.c
new file mode 100644 (file)
index 0000000..68c4ac6
--- /dev/null
@@ -0,0 +1,141 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static void *
+tf1 (void *arg)
+{
+  pthread_join (arg, NULL);
+
+  puts ("1st join returned");
+
+  return (void *) 1l;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  pthread_join (arg, NULL);
+
+  puts ("2nd join returned");
+
+  return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  int err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("1st circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("1st circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel 1st thread");
+      exit (1);
+    }
+
+  void *r;
+  err = pthread_join (th, &r);
+  if (err != 0)
+    {
+      printf ("cannot join 1st thread: %d\n", err);
+      exit (1);
+    }
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("1st thread not canceled");
+      exit (1);
+    }
+
+  err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("2nd circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("2nd circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
+    {
+      puts ("2nd create failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel 2nd thread");
+      exit (1);
+    }
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("cannot join 2nd thread");
+      exit (1);
+    }
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      exit (1);
+    }
+
+  err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("2nd circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("2nd circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"