.
[glibc-ports.git] / sysdeps / unix / sysv / linux / arm / linuxthreads / sysdep-cancel.h
blobcd4d171c70b38d861be1bb47ba1d62fd40e0dfa5
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 PSEUDO_RET_MOV; \
54 .Lpseudo_cancel: \
55 MAYBE_SAVE_LR; \
56 DOCARGS_##args; /* save syscall args around CENABLE. */ \
57 CENABLE; \
58 mov ip, r0; /* put mask in safe place. */ \
59 UNDOCARGS_##args; /* restore syscall args. */ \
60 swi SYS_ify (syscall_name); /* do the call. */ \
61 str r0, [sp, $-4]!; /* save syscall return value. */ \
62 mov r0, ip; /* get mask back. */ \
63 CDISABLE; \
64 ldr r0, [sp], $4; /* retrieve return value. */ \
65 UNDOC2ARGS_##args; /* fix register damage. */ \
66 cmn r0, $4096;
68 # define DOCARGS_0
69 # define UNDOCARGS_0
70 # define UNDOC2ARGS_0
72 # define DOCARGS_1 str r0, [sp, #-4]!;
73 # define UNDOCARGS_1 ldr r0, [sp], #4;
74 # define UNDOC2ARGS_1
76 # define DOCARGS_2 str r1, [sp, #-4]!; str r0, [sp, #-4]!;
77 # define UNDOCARGS_2 ldr r0, [sp], #4; ldr r1, [sp], #4;
78 # define UNDOC2ARGS_2
80 # define DOCARGS_3 str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!;
81 # define UNDOCARGS_3 ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4
82 # define UNDOC2ARGS_3
84 # define DOCARGS_4 stmfd sp!, {r0-r3}
85 # define UNDOCARGS_4 ldmfd sp!, {r0-r3}
86 # define UNDOC2ARGS_4
88 # define DOCARGS_5 stmfd sp!, {r0-r3}
89 # define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24]
90 # define UNDOC2ARGS_5 ldr r4, [sp], #20
92 # ifdef IS_IN_libpthread
93 # define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
94 # define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
95 # define __local_multiple_threads __pthread_multiple_threads
96 # else
97 # define CENABLE bl PLTJMP(__libc_enable_asynccancel)
98 # define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
99 # define __local_multiple_threads __libc_multiple_threads
100 # endif
102 # ifndef __ASSEMBLER__
103 extern int __local_multiple_threads attribute_hidden;
104 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
105 # else
106 # if !defined PIC
107 # define SINGLE_THREAD_P \
108 ldr ip, =__local_multiple_threads; \
109 ldr ip, [ip]; \
110 teq ip, #0;
111 # define MAYBE_SAVE_LR \
112 str lr, [sp, $-4]!;
113 # define PSEUDO_RET_MOV \
114 RETINSTR(cc, lr); \
115 b PLTJMP(SYSCALL_ERROR)
116 # define PSEUDO_PROLOGUE
117 # else
118 # define SINGLE_THREAD_P \
119 ldr ip, 1b; \
120 2: \
121 ldr ip, [pc, ip]; \
122 teq ip, #0;
123 # define PSEUDO_PROLOGUE \
124 1: .word __local_multiple_threads - 2f - 8;
125 # define MAYBE_SAVE_LR /* lr already saved */
126 # define PSEUDO_RET_MOV PSEUDO_RET
127 # endif
128 # endif
130 #elif !defined __ASSEMBLER__
132 /* This code should never be used but we define it anyhow. */
133 # define SINGLE_THREAD_P (1)
135 #endif