public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads
@ 2003-04-01 15:19 Jakub Jelinek
  2003-04-01 19:50 ` Roland McGrath
  2003-04-02  0:11 ` Roland McGrath
  0 siblings, 2 replies; 5+ messages in thread
From: Jakub Jelinek @ 2003-04-01 15:19 UTC (permalink / raw)
  To: Ulrich Drepper, Roland McGrath; +Cc: Glibc hackers, gjohnson

Hi!

linuxthreads call sigsuspend from pthread_mutex_lock etc., so when sigsuspend
was made cancellation point in December, suddenly all pthread primitives
which wait for restart signals are cancellation points.
Fix below, tested on all the usual arches.

2003-04-01  Jakub Jelinek  <jakub@redhat.com>

linuxthreads/
	* pthread.c (__pthread_wait_for_restart_signal): Use
	__pthread_sigsuspend instead of sigsuspend.
	* internals.h (__pthread_sigsuspend): New prototype.
	* Makefile (libpthread-routines): Add pt-sigsuspend.
	(tests): Add tst-cancel7.
	* sysdeps/unix/sysv/linux/pt-sigsuspend.c: New file.
	* sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S: New file.
	* sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c: New file.
	* sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c: New file.
	* sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c: New file.
	* tst-cancel7.c: New test.
libc/
	* sysdeps/unix/sysv/linux/sparc/sparc64/sigsuspend.c: Use the
	IA-64 version.

--- libc/linuxthreads/Makefile.jj	2003-02-22 17:53:57.000000000 -0500
+++ libc/linuxthreads/Makefile	2003-04-01 05:27:16.000000000 -0500
@@ -36,8 +36,8 @@ extra-libs-others := $(extra-libs)
 install-lib-ldscripts := libpthread.so
 
 libpthread-routines := attr cancel condvar join manager mutex ptfork \
-		       ptlongjmp pthread signals specific errno lockfile \
-		       semaphore spinlock rwlock pt-machine \
+		       ptlongjmp pthread pt-sigsuspend signals specific errno \
+		       lockfile semaphore spinlock rwlock pt-machine \
 		       oldsemaphore events getcpuclockid pspinlock barrier \
 		       ptclock_gettime ptclock_settime sighandler \
 		       pthandles libc-tls-loc pt-allocrtsig \
@@ -89,7 +89,7 @@ tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 
 	tststack $(tests-nodelete-$(have-z-nodelete)) ecmutex ex14 ex15 ex16 \
 	ex17 ex18 tst-cancel tst-context bug-sleep \
 	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
-	tst-cancel6 tst-popen tst-popen2
+	tst-cancel6 tst-cancel7 tst-popen tst-popen2
 test-srcs = tst-signal
 # These tests are linked with libc before libpthread
 tests-reverse += tst-cancel5
--- libc/linuxthreads/tst-cancel7.c.jj	2003-04-01 06:07:27.000000000 -0500
+++ libc/linuxthreads/tst-cancel7.c	2003-04-01 06:41:34.000000000 -0500
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_barrier_t b;
+int value = 0;
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_mutex_lock (&lock);
+  ++value;
+  pthread_testcancel ();
+  ++value;
+  pthread_mutex_unlock (&lock);
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_lock (&lock);
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+                                                                                          
+  if (value == 0)
+    {
+      puts ("thread cancelled in the pthread_mutex_lock call");
+      return 1;
+    }
+
+  if (value != 1)
+    {
+      puts ("thread not cancelled in pthread_testcancel call");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/pthread.c.jj	2003-03-06 12:26:17.000000000 -0500
+++ libc/linuxthreads/pthread.c	2003-04-01 04:56:53.000000000 -0500
@@ -1144,7 +1144,8 @@ void __pthread_wait_for_restart_signal(p
   sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
   THREAD_SETMEM(self, p_signal, 0);
   do {
-    sigsuspend(&mask);                   /* Wait for signal */
+    __pthread_sigsuspend(&mask);	/* Wait for signal.  Must not be a
+					   cancellation point. */
   } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
 
   READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c.jj	2003-04-01 05:09:33.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c	2003-04-01 05:12:37.000000000 -0500
@@ -0,0 +1,32 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 <signal.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <linuxthreads/internals.h>
+
+void
+__pthread_sigsuspend (const sigset_t *set)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+}
--- libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c.jj	2003-04-01 05:16:33.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c	2003-04-01 05:16:48.000000000 -0500
@@ -0,0 +1 @@
+#include "../../ia64/pt-sigsuspend.c"
--- libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c.jj	2003-04-01 05:16:33.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c	2003-04-01 05:16:48.000000000 -0500
@@ -0,0 +1 @@
+#include "../../ia64/pt-sigsuspend.c"
--- libc/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c.jj	2003-04-01 05:16:33.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c	2003-04-01 05:16:29.000000000 -0500
@@ -0,0 +1 @@
+#include "../ia64/pt-sigsuspend.c"
--- libc/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S.jj	2003-04-01 05:05:55.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S	2003-04-01 05:08:30.000000000 -0500
@@ -0,0 +1,27 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 <sysdep.h>
+
+#undef PSEUDO_PREPARE_ARGS
+#define PSEUDO_PREPARE_ARGS	ldq	a0, 0(a0);
+
+	.hidden __pthread_sigsuspend
+PSEUDO_NOERRNO(__pthread_sigsuspend, sigsuspend, 1)
+	ret
+PSEUDO_END_NOERRNO(__pthread_sigsuspend)
--- libc/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c.jj	2003-04-01 04:48:47.000000000 -0500
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c	2003-04-01 05:13:26.000000000 -0500
@@ -0,0 +1,55 @@
+/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 <signal.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <linuxthreads/internals.h>
+
+#include "kernel-features.h"
+
+void
+__pthread_sigsuspend (const sigset_t *set)
+{
+  INTERNAL_SYSCALL_DECL (err);
+#if !__ASSUME_REALTIME_SIGNALS
+  static int __pthread_missing_rt_sigs;
+
+# ifdef __NR_rt_sigsuspend
+  /* First try the RT signals.  */
+  if (!__pthread_missing_rt_sigs)
+    {
+      /* XXX The size argument hopefully will have to be changed to the
+	 real size of the user-level sigset_t.  */
+      int r;
+      r = INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+      if (INTERNAL_SYSCALL_ERRNO (r, err) != ENOSYS)
+	return;
+
+      __pthread_missing_rt_sigs = 1;
+    }
+# endif
+
+  INTERNAL_SYSCALL (sigsuspend, err, 3, 0, 0, set->__val[0]);
+#else
+  INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
+#endif
+}
--- libc/linuxthreads/internals.h.jj	2003-01-07 10:57:55.000000000 -0500
+++ libc/linuxthreads/internals.h	2003-04-01 05:23:33.000000000 -0500
@@ -377,6 +377,8 @@ extern int __pthread_timedsuspend_new(pt
 
 extern void __pthread_wait_for_restart_signal(pthread_descr self);
 
+extern void __pthread_sigsuspend (const sigset_t *mask) attribute_hidden;
+
 extern int __pthread_yield (void);
 
 extern int __pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
--- libc/sysdeps/unix/sysv/linux/sparc/sparc64/sigsuspend.c.jj	2002-12-15 18:21:00.000000000 -0500
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc64/sigsuspend.c	2003-04-01 05:21:01.000000000 -0500
@@ -1,41 +1 @@
-/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   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 <signal.h>
-#include <unistd.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-#include <bp-checks.h>
-
-extern int __syscall_rt_sigsuspend (const sigset_t *__unbounded, size_t);
-
-/* Change the set of blocked signals to SET,
-   wait until a signal arrives, and restore the set of blocked signals.  */
-int
-__sigsuspend (set)
-     const sigset_t *set;
-{
-  /* XXX The size argument hopefully will have to be changed to the
-     real size of the user-level sigset_t.  */
-  return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8);
-}
-libc_hidden_def (__sigsuspend)
-weak_alias (__sigsuspend, sigsuspend)
-strong_alias (__sigsuspend, __libc_sigsuspend)
+#include "../../ia64/sigsuspend.c"

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads
  2003-04-01 15:19 [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads Jakub Jelinek
@ 2003-04-01 19:50 ` Roland McGrath
  2003-04-01 20:17   ` Jakub Jelinek
  2003-04-02  0:11 ` Roland McGrath
  1 sibling, 1 reply; 5+ messages in thread
From: Roland McGrath @ 2003-04-01 19:50 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Glibc hackers

Why __pthread_sigsuspend instead of just using INTERNAL_SYSCALL directly?
kernel-features.h can define something about rt_sigsuspend vs sigsuspend
for each machine.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads
  2003-04-01 19:50 ` Roland McGrath
@ 2003-04-01 20:17   ` Jakub Jelinek
  2003-04-01 20:46     ` Ulrich Drepper
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2003-04-01 20:17 UTC (permalink / raw)
  To: Roland McGrath; +Cc: Glibc hackers

On Tue, Apr 01, 2003 at 11:50:25AM -0800, Roland McGrath wrote:
> Why __pthread_sigsuspend instead of just using INTERNAL_SYSCALL directly?
> kernel-features.h can define something about rt_sigsuspend vs sigsuspend
> for each machine.

It differs between arches.
On most arches it is
INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
on some for compatibility
INTERNAL_SYSCALL (sigsuspend, err, 3, 0, 0, set->__val[0]);
(with possible runtime choice) but on Alpha it is
INTERNAL_SYSCALL (sigsuspend, err, 1, set->__val[0]);
(well, looks like the same on sparc32 for pre-rtsig kernels,
apparently nobody is running < 2.2.x kernels on sparc any more).
I think best would be a special header in
linuxthreads/sysdeps/unix/sysv/linux/*
and inline the call to avoid the call/return overhead.

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads
  2003-04-01 20:17   ` Jakub Jelinek
@ 2003-04-01 20:46     ` Ulrich Drepper
  0 siblings, 0 replies; 5+ messages in thread
From: Ulrich Drepper @ 2003-04-01 20:46 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Roland McGrath, Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jakub Jelinek wrote:

> It differs between arches.

It's not worth adding much cmoplexity.  I think the original patch is fine.

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE+ifp72ijCOnn/RHQRAreBAJkBsME5UcHaG3YjFA41Vvi3t8PV5ACcDsp4
LcBHA+NKhtrhK2cjZPQ/vs4=
=iUfj
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads
  2003-04-01 15:19 [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads Jakub Jelinek
  2003-04-01 19:50 ` Roland McGrath
@ 2003-04-02  0:11 ` Roland McGrath
  1 sibling, 0 replies; 5+ messages in thread
From: Roland McGrath @ 2003-04-02  0:11 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Ulrich Drepper, Glibc hackers, gjohnson

> linuxthreads call sigsuspend from pthread_mutex_lock etc., so when sigsuspend
> was made cancellation point in December, suddenly all pthread primitives
> which wait for restart signals are cancellation points.
> Fix below, tested on all the usual arches.

I put these in.

Thanks,
Roland

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-04-02  0:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-01 15:19 [PATCH] Avoid cancellation point in pthread_mutex_lock etc. in linuxthreads Jakub Jelinek
2003-04-01 19:50 ` Roland McGrath
2003-04-01 20:17   ` Jakub Jelinek
2003-04-01 20:46     ` Ulrich Drepper
2003-04-02  0:11 ` Roland McGrath

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).