From ddf42be0e23af7a82c129a7d22de10cecd03c306 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 7 Jan 2003 00:39:17 +0000 Subject: [PATCH] Syscall cancellation handling for Arm. --- .../sysv/linux/arm/linuxthreads/sysdep-cancel.h | 127 +++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/arm/linuxthreads/sysdep-cancel.h diff --git a/sysdeps/unix/sysv/linux/arm/linuxthreads/sysdep-cancel.h b/sysdeps/unix/sysv/linux/arm/linuxthreads/sysdep-cancel.h new file mode 100644 index 0000000..5f3709f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/linuxthreads/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 , 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 +#ifndef __ASSEMBLER__ +# include +#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 -- 2.7.4