This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
[PATCH] PPC32 cancellation support
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Sat, 4 Jan 2003 17:06:01 +0100
- Subject: [PATCH] PPC32 cancellation support
Hi,
After fixing my thinko in accessing variables via GOT nearly all is fine now.
The only failing xchecks are test-aio and test-aio64 which I'm still
investigating (does it sound familiar to someone?).
tst-aio: aio_write: wrong size: 269090916, should be 1000
tst-aio: comparison failed for aio_read test
tst-aio: lio_listio (write): wrong size: 269090916, should be 1000
tst-aio: aio_fsync (aio_write): wrong size: 269090916, should be 1000
The rest behaves fine.
Franz.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list: Mark
__syscall_pread64 and __syscall_pwrite64 cancellable.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
(INTERNAL_SYSCALL): New macro.
(LOADARGS_0, LOADARGS_1): Fix.
* linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h:
New file.
* linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile: New
file.
Index: sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list,v
retrieving revision 1.4
diff -u -p -r1.4 syscalls.list
--- sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list 5 Nov 2002 21:05:21 -0000 1.4
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list 4 Jan 2003 15:51:12 -0000
@@ -12,6 +12,6 @@ oldsetrlimit EXTRA setrlimit i:ip __old_
# System calls with 64bit args
s_ftruncate64 ftruncate64 ftruncate64 i:iii __syscall_ftruncate64
-s_pread64 pread64 pread i:ibnii __syscall_pread
-s_pwrite64 pwrite64 pwrite i:ibnii __syscall_pwrite
+s_pread64 pread64 pread Ci:ibnii __syscall_pread
+s_pwrite64 pwrite64 pwrite Ci:ibnii __syscall_pwrite
s_truncate64 truncate64 truncate64 i:sii __syscall_truncate64
Index: sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h,v
retrieving revision 1.5
diff -u -p -r1.5 sysdep.h
--- sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h 5 Nov 2002 19:55:44 -0000 1.5
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h 4 Jan 2003 15:51:12 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992,97,98,99,2000,01,02 Free Software Foundation, Inc.
+/* Copyright (C) 1992,97,98,99,2000,01,02,03 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
@@ -93,10 +93,50 @@
ret; \
})
-# define LOADARGS_0(name) \
+/* Define a macro which expands inline into the wrapper code for a system
+ call. This use is for internal calls that do not need to handle errors
+ normally. It will never touch errno. This returns just what the kernel
+ gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
+ the negation of the return value in the kernel gets reverted. */
+
+#undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, nr, args...) \
+ ({ \
+ register long r0 __asm__ ("r0"); \
+ register long r3 __asm__ ("r3"); \
+ register long r4 __asm__ ("r4"); \
+ register long r5 __asm__ ("r5"); \
+ register long r6 __asm__ ("r6"); \
+ register long r7 __asm__ ("r7"); \
+ register long r8 __asm__ ("r8"); \
+ register long r9 __asm__ ("r9"); \
+ register long r10 __asm__ ("r10"); \
+ register long r11 __asm__ ("r11"); \
+ register long r12 __asm__ ("r12"); \
+ LOADARGS_##nr(name, args); \
+ __asm__ __volatile__ \
+ ("sc\n\t" \
+ "bns+ 0f\n\t" \
+ "neg %1,%1\n" \
+ "0:" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
+ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
+ : ASM_INPUT_##nr \
+ : "cr0", "ctr", "memory"); \
+ (int) r3; \
+ })
+
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= -4095U)
+
+#undef INTERNAL_SYSCALL_ERRNO
+#define INTERNAL_SYSCALL_ERRNO(val) (-(val))
+
+# define LOADARGS_0(name, dummy) \
r0 = __NR_##name
# define LOADARGS_1(name, arg1) \
- LOADARGS_0(name); \
+ LOADARGS_0(name, 0); \
r3 = (long) (arg1)
# define LOADARGS_2(name, arg1, arg2) \
LOADARGS_1(name, arg1); \
--- /dev/null 2002-11-11 17:51:46.000000000 -0700
+++ linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile 2003-01-03 17:36:07.000000000 -0700
@@ -0,0 +1 @@
+libpthread-routines += sysdep s_pread64 s_pwrite64
--- /dev/null 2002-11-11 17:51:46.000000000 -0700
+++ linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h 2003-01-04 07:27:43.000000000 -0700
@@ -0,0 +1,121 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.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 <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .section ".text"; \
+ ENTRY (name) \
+ SINGLE_THREAD_P; \
+ bne- .Lpseudo_cancel; \
+ DO_CALL (SYS_ify (syscall_name)); \
+ PSEUDO_RET; \
+ .Lpseudo_cancel: \
+ stwu 1,-48(1); \
+ mflr 9; \
+ stw 9,52(1); \
+ DOCARGS_##args; /* save syscall args around CENABLE. */ \
+ CENABLE; \
+ stw 3,16(1); /* store CENABLE return value (MASK). */ \
+ UNDOCARGS_##args; /* restore syscall args. */ \
+ DO_CALL (SYS_ify (syscall_name)); \
+ mfcr 0; /* save CR/R3 around CDISABLE. */ \
+ stw 3,8(1); \
+ stw 0,12(1); \
+ lwz 3,16(1); /* pass MASK to CDISABLE. */ \
+ CDISABLE; \
+ lwz 4,52(1); \
+ lwz 0,12(1); /* restore CR/R3. */ \
+ lwz 3,8(1); \
+ mtlr 4; \
+ mtcr 0; \
+ addi 1,1,48;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+
+# define DOCARGS_1 stw 3,20(1); DOCARGS_0
+# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0
+
+# define DOCARGS_2 stw 4,24(1); DOCARGS_1
+# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1
+
+# define DOCARGS_3 stw 5,28(1); DOCARGS_2
+# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2
+
+# define DOCARGS_4 stw 6,32(1); DOCARGS_3
+# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3
+
+# define DOCARGS_5 stw 7,36(1); DOCARGS_4
+# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4
+
+# ifdef IS_IN_libpthread
+# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel)
+# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel)
+# define __local_multiple_threads __pthread_multiple_threads
+# else
+# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel)
+# define CDISABLE bl JUMPTARGET(__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 \
+ lis 10,__local_multiple_threads@ha; \
+ lwz 10,__local_multiple_threads@l(10); \
+ cmpwi 10,0
+# else
+# if !defined HAVE_HIDDEN || !USE___THREAD
+# define SINGLE_THREAD_P \
+ mflr 9; \
+ bl _GLOBAL_OFFSET_TABLE_@local-4; \
+ mflr 10; \
+ mtlr 9; \
+ lwz 10,__local_multiple_threads@got(10); \
+ lwz 10,0(10); \
+ cmpwi 10,0
+# else
+# define SINGLE_THREAD_P \
+ mflr 9; \
+ bl _GLOBAL_OFFSET_TABLE_@local-4; \
+ mflr 10; \
+ mtlr 9; \
+ lwz 10,__local_multiple_threads@got(10); \
+ lwz 10,0(10); \
+ cmpwi 10,0
+# endif
+# endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow. */
+# define SINGLE_THREAD_P (1)
+
+#endif