From 9a197dcc6a93d7938bede6ca85fd1f769424cf17 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 2 Apr 2003 00:11:05 +0000 Subject: [PATCH] * sysdeps/unix/sysv/linux/sparc/sparc64/sigsuspend.c: Use the IA-64 version. --- ChangeLog | 3 + linuxthreads/ChangeLog | 15 +++ linuxthreads/Makefile | 6 +- linuxthreads/internals.h | 2 + linuxthreads/pthread.c | 3 +- .../unix/sysv/linux/alpha/pt-sigsuspend.S | 28 +++++ .../unix/sysv/linux/ia64/pt-sigsuspend.c | 33 ++++++ .../sysdeps/unix/sysv/linux/pt-sigsuspend.c | 56 +++++++++ .../sysv/linux/s390/s390-64/pt-sigsuspend.c | 1 + .../sysv/linux/sparc/sparc64/pt-sigsuspend.c | 1 + .../unix/sysv/linux/x86_64/pt-sigsuspend.c | 1 + linuxthreads/tst-cancel7.c | 111 ++++++++++++++++++ 12 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c create mode 100644 linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c create mode 100644 linuxthreads/tst-cancel7.c diff --git a/ChangeLog b/ChangeLog index bd62a3cb4e..e356e7d925 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2003-04-01 Jakub Jelinek + * sysdeps/unix/sysv/linux/sparc/sparc64/sigsuspend.c: Use the + IA-64 version. + * elf/tls-macros.h [__ia64__] (TLS_IE, TLS_LD, TLS_GD): Add gp register as input to asm. diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index dbdb0d4e8b..6bd20005fd 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,18 @@ +2003-04-01 Jakub Jelinek + + * 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. + 2003-03-31 Alexandre Oliva * alloca_cutoff.c: Include internals.h. diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index 8a6f9bfc91..fd8f92b49c 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -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 ex9 $(librt-tests) ex12 ex13 joinrace \ 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 diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index 36fdfe1bff..eb5ba13e7e 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -377,6 +377,8 @@ extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec 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, diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c index 01be30ba12..f165ab1093 100644 --- a/linuxthreads/pthread.c +++ b/linuxthreads/pthread.c @@ -1144,7 +1144,8 @@ void __pthread_wait_for_restart_signal(pthread_descr self) 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 */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S new file mode 100644 index 0000000000..91e5c86782 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S @@ -0,0 +1,28 @@ +/* Internal sigsuspend system call for LinuxThreads. Alpha version. + 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 + +#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) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c new file mode 100644 index 0000000000..0b96e3d5bd --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. IA64 version. + 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 +#include +#include + +#include +#include +#include + +void +__pthread_sigsuspend (const sigset_t *set) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c new file mode 100644 index 0000000000..5528c55ca5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c @@ -0,0 +1,56 @@ +/* Internal sigsuspend system call for LinuxThreads. Generic Linux version. + 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 +#include +#include + +#include +#include +#include + +#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 +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c new file mode 100644 index 0000000000..d57283ad23 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c new file mode 100644 index 0000000000..d57283ad23 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c new file mode 100644 index 0000000000..3a0c2afc0f --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/tst-cancel7.c b/linuxthreads/tst-cancel7.c new file mode 100644 index 0000000000..11298eae26 --- /dev/null +++ b/linuxthreads/tst-cancel7.c @@ -0,0 +1,111 @@ +/* Test for pthread cancellation of mutex blocks. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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 +#include +#include +#include + +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"