[arm] Fix bug in _nocancel system call stubs.
[glibc-ports.git] / sysdeps / unix / sysv / linux / arm / linuxthreads / sysdep-cancel.h
blobb35d34728d84e5369ecfe887f75b7499969da504
1 /* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Phil Blundell <pb@nexus.co.uk>, 2003.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <sysdep.h>
21 #ifndef __ASSEMBLER__
22 # include <linuxthreads/internals.h>
23 #endif
25 #if !defined NOT_IN_libc || defined IS_IN_libpthread
27 /* We push lr onto the stack, so we have to use ldmib instead of ldmia
28 to find the saved arguments. */
29 # ifdef PIC
30 # undef DOARGS_5
31 # undef DOARGS_6
32 # undef DOARGS_7
33 # define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $8];
34 # define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmib ip, {r4, r5};
35 # define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmib ip, {r4, r5, r6};
36 # endif
38 # undef PSEUDO_RET
39 # define PSEUDO_RET \
40 ldrcc pc, [sp], $4; \
41 ldr lr, [sp], $4; \
42 b PLTJMP(SYSCALL_ERROR)
44 # undef PSEUDO
45 # define PSEUDO(name, syscall_name, args) \
46 .section ".text"; \
47 PSEUDO_PROLOGUE; \
48 ENTRY (name); \
49 SINGLE_THREAD_P; \
50 bne .Lpseudo_cancel; \
51 DO_CALL (syscall_name, args); \
52 cmn r0, $4096; \
53 RETINSTR(cc, lr); \
54 b PLTJMP(SYSCALL_ERROR); \
55 .Lpseudo_cancel: \
56 str lr, [sp, $-4]!; \
57 DOCARGS_##args; /* save syscall args around CENABLE. */ \
58 CENABLE; \
59 mov ip, r0; /* put mask in safe place. */ \
60 UNDOCARGS_##args; /* restore syscall args. */ \
61 swi SYS_ify (syscall_name); /* do the call. */ \
62 str r0, [sp, $-4]!; /* save syscall return value. */ \
63 mov r0, ip; /* get mask back. */ \
64 CDISABLE; \
65 ldr r0, [sp], $4; /* retrieve return value. */ \
66 UNDOC2ARGS_##args; /* fix register damage. */ \
67 cmn r0, $4096;
69 # define DOCARGS_0
70 # define UNDOCARGS_0
71 # define UNDOC2ARGS_0
73 # define DOCARGS_1 str r0, [sp, #-4]!;
74 # define UNDOCARGS_1 ldr r0, [sp], #4;
75 # define UNDOC2ARGS_1
77 # define DOCARGS_2 str r1, [sp, #-4]!; str r0, [sp, #-4]!;
78 # define UNDOCARGS_2 ldr r0, [sp], #4; ldr r1, [sp], #4;
79 # define UNDOC2ARGS_2
81 # define DOCARGS_3 str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!;
82 # define UNDOCARGS_3 ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4
83 # define UNDOC2ARGS_3
85 # define DOCARGS_4 stmfd sp!, {r0-r3}
86 # define UNDOCARGS_4 ldmfd sp!, {r0-r3}
87 # define UNDOC2ARGS_4
89 # define DOCARGS_5 stmfd sp!, {r0-r3}
90 # define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24]
91 # define UNDOC2ARGS_5 ldr r4, [sp], #20
93 # ifdef IS_IN_libpthread
94 # define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
95 # define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
96 # define __local_multiple_threads __pthread_multiple_threads
97 # else
98 # define CENABLE bl PLTJMP(__libc_enable_asynccancel)
99 # define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
100 # define __local_multiple_threads __libc_multiple_threads
101 # endif
103 # ifndef __ASSEMBLER__
104 extern int __local_multiple_threads attribute_hidden;
105 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
106 # else
107 # if !defined PIC
108 # define SINGLE_THREAD_P \
109 ldr ip, =__local_multiple_threads; \
110 ldr ip, [ip]; \
111 teq ip, #0;
112 # define PSEUDO_PROLOGUE
113 # else
114 # define SINGLE_THREAD_P \
115 ldr ip, 1b; \
116 2: \
117 ldr ip, [pc, ip]; \
118 teq ip, #0;
119 # define PSEUDO_PROLOGUE \
120 1: .word __local_multiple_threads - 2f - 8;
121 # endif
122 # endif
124 #elif !defined __ASSEMBLER__
126 /* This code should never be used but we define it anyhow. */
127 # define SINGLE_THREAD_P (1)
129 #endif