aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog14
-rw-r--r--linuxthreads/internals.h7
-rw-r--r--linuxthreads/pt-system.c5
-rw-r--r--linuxthreads/signals.c3
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h127
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/sigwait.c3
-rw-r--r--linuxthreads/tst-cancel-wrappers.sh8
7 files changed, 159 insertions, 8 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index fc29ca771f..5c7b8181e6 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,17 @@
+2003-01-06 Philip Blundell <philb@gnu.org>
+
+ * sysdeps/unix/sysv/linux/arm/sysdep-cancel.h: New file.
+
+2003-01-06 Jakub Jelinek <jakub@redhat.com>
+
+ * internals.h (LIBC_CANCEL_HANDLED): Define.
+ * sysdeps/unix/sysv/linux/sigwait.c (LIBC_CANCEL_HANDLED): Add.
+ * signals.c (LIBC_CANCEL_HANDLED): Add.
+ * pt-system.c (LIBC_CANCEL_HANDLED): Add.
+ * tst-cancel-wrappers.sh: Remove all exceptions.
+
+ * sysdeps/unix/sysv/linux/alpha/Makefile: New file.
+
2003-01-05 Andreas Schwab <schwab@suse.de>
* sysdeps/m68k/Makefile: New file, use -fPIC for nonshared
diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h
index f4c7653659..36fdfe1bff 100644
--- a/linuxthreads/internals.h
+++ b/linuxthreads/internals.h
@@ -475,14 +475,21 @@ extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden;
__libc_enable_asynccancel ()
# define LIBC_CANCEL_RESET(oldtype) \
__libc_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+ __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
#elif defined NOT_IN_libc && defined IS_IN_libpthread
# define LIBC_CANCEL_ASYNC() \
__pthread_enable_asynccancel ()
# define LIBC_CANCEL_RESET(oldtype) \
__pthread_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
#else
# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */
# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */
+# define LIBC_CANCEL_HANDLED() /* Nothing. */
#endif
/* Data type shared with libc. The libc uses it to pass on calls to
diff --git a/linuxthreads/pt-system.c b/linuxthreads/pt-system.c
index 3a5f46c4f8..c3ed676f51 100644
--- a/linuxthreads/pt-system.c
+++ b/linuxthreads/pt-system.c
@@ -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 Jakub Jelinek <jakub@redhat.com>, 2002.
@@ -27,3 +27,6 @@ system (const char *line)
{
return __libc_system (line);
}
+
+/* __libc_system in libc.so handles cancellation. */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/signals.c b/linuxthreads/signals.c
index d0087d9fab..e1f67ab0e8 100644
--- a/linuxthreads/signals.c
+++ b/linuxthreads/signals.c
@@ -195,3 +195,6 @@ int __pthread_raise (int sig)
#ifdef SHARED
strong_alias (__pthread_raise, raise)
#endif
+
+/* This files handles cancellation internally. */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
new file mode 100644
index 0000000000..5f3709f742
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Phil Blundell <pb@nexus.co.uk>, 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 <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO_RET
+# define PSEUDO_RET \
+ ldrcc pc, [sp], $4; \
+ b PLTJMP(SYSCALL_ERROR)
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .section ".text"; \
+ PSEUDO_PROLOGUE; \
+ ENTRY (name) \
+ SINGLE_THREAD_P; \
+ bne .Lpseudo_cancel; \
+ DO_CALL (syscall_name, args); \
+ cmn r0, $4096; \
+ PSEUDO_RET_MOV; \
+ .Lpseudo_cancel: \
+ MAYBE_SAVE_LR; \
+ DOCARGS_##args; /* save syscall args around CENABLE. */ \
+ CENABLE; \
+ mov ip, r0; /* put mask in safe place. */ \
+ UNDOCARGS_##args; /* restore syscall args. */ \
+ swi SYS_ify (syscall_name); /* do the call. */ \
+ str r0, [sp, $-4]!; /* save syscall return value. */ \
+ mov r0, ip; /* get mask back. */ \
+ CDISABLE; \
+ ldr r0, [sp], $4; /* retrieve return value. */ \
+ UNDOC2ARGS_##args; /* fix register damage. */ \
+ cmn r0, $4096;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+# define UNDOC2ARGS_0
+
+# define DOCARGS_1 str r0, [sp, #-4]!;
+# define UNDOCARGS_1 ldr r0, [sp], #4;
+# define UNDOC2ARGS_1
+
+# define DOCARGS_2 str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_2 ldr r0, [sp], #4; ldr r1, [sp], #4;
+# define UNDOC2ARGS_2
+
+# define DOCARGS_3 str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_3 ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4
+# define UNDOC2ARGS_3
+
+# define DOCARGS_4 stmfd sp!, {r0-r3}
+# define UNDOCARGS_4 ldmfd sp!, {r0-r3}
+# define UNDOC2ARGS_4
+
+# define DOCARGS_5 stmfd sp!, {r0-r3}
+# define UNDOCARGS_5 str r4, [sp, #-4]!; ldmfd sp, {r0-r4}
+# define UNDOC2ARGS_5 ldr r4, [sp], #20
+
+# ifdef IS_IN_libpthread
+# define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
+# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
+# define __local_multiple_threads __pthread_multiple_threads
+# else
+# define CENABLE bl PLTJMP(__libc_enable_asynccancel)
+# define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
+# define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+# if !defined PIC
+# define SINGLE_THREAD_P \
+ ldr ip, =__local_multiple_threads; \
+ ldr ip, [ip]; \
+ teq ip, #0;
+# define MAYBE_SAVE_LR \
+ str lr, [sp, $-4]!;
+# define PSEUDO_RET_MOV \
+ RETINSTR(movcc, pc, lr); \
+ b PLTJMP(SYSCALL_ERROR)
+# define PSEUDO_PROLOGUE
+# else
+# define SINGLE_THREAD_P \
+ str lr, [sp, $-4]!; \
+ ldr ip, 1b; \
+ ldr lr, 2b; \
+3: \
+ add ip, pc, ip; \
+ ldr ip, [ip, lr]; \
+ teq ip, #0;
+# define PSEUDO_PROLOGUE \
+ 1: .word _GLOBAL_OFFSET_TABLE_ - 3f - 8; \
+ 2: .word __local_multiple_threads(GOTOFF);
+# define MAYBE_SAVE_LR /* lr already saved */
+# define PSEUDO_RET_MOV PSEUDO_RET
+# endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow. */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
index 460d3d56a7..c0cfb41753 100644
--- a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
+++ b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
@@ -82,3 +82,6 @@ __sigwait (set, sig)
libc_hidden_def (__sigwait)
weak_alias (__sigwait, sigwait)
strong_alias (__sigwait, __libc_sigwait)
+
+/* Cancellation is handled in __pthread_sigwait. */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/tst-cancel-wrappers.sh b/linuxthreads/tst-cancel-wrappers.sh
index 9b739d2121..c9ed40b722 100644
--- a/linuxthreads/tst-cancel-wrappers.sh
+++ b/linuxthreads/tst-cancel-wrappers.sh
@@ -67,13 +67,7 @@ C["__xpg_sigpause"]=1
/:$/ {
if (seen)
{
- # signals.c and sigwait.c in linuxthreads do the cancellation checks
- # not using *_{enable,disable}_asynccancel.
- # Similarly pt-system.o* is allowed to call __libc_system directly.
- if ((!seen_enable || !seen_disable) \
- && !(object ~ /^signals.o/) \
- && !(object ~ /^sigwait.o/) \
- && !(object ~ /^pt-system.o/))
+ if (!seen_enable || !seen_disable)
{
printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
ret = 1