summaryrefslogtreecommitdiff
path: root/linuxthreads/sysdeps/unix/sysv/linux/arm
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads/sysdeps/unix/sysv/linux/arm')
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h19
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S57
2 files changed, 70 insertions, 6 deletions
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
index 5f3709f742..38e472d2ba 100644
--- a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
@@ -27,6 +27,7 @@
# undef PSEUDO_RET
# define PSEUDO_RET \
ldrcc pc, [sp], $4; \
+ ldr lr, [sp], $4; \
b PLTJMP(SYSCALL_ERROR)
# undef PSEUDO
@@ -34,7 +35,7 @@
.section ".text"; \
PSEUDO_PROLOGUE; \
ENTRY (name) \
- SINGLE_THREAD_P; \
+ SINGLE_THREAD_P_INT; \
bne .Lpseudo_cancel; \
DO_CALL (syscall_name, args); \
cmn r0, $4096; \
@@ -74,7 +75,7 @@
# define UNDOC2ARGS_4
# define DOCARGS_5 stmfd sp!, {r0-r3}
-# define UNDOCARGS_5 str r4, [sp, #-4]!; ldmfd sp, {r0-r4}
+# define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24]
# define UNDOC2ARGS_5 ldr r4, [sp], #20
# ifdef IS_IN_libpthread
@@ -92,10 +93,11 @@ 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 \
+# define SINGLE_THREAD_P_INT \
ldr ip, =__local_multiple_threads; \
ldr ip, [ip]; \
teq ip, #0;
+# define SINGLE_THREAD_P SINGLE_THREAD_P_INT
# define MAYBE_SAVE_LR \
str lr, [sp, $-4]!;
# define PSEUDO_RET_MOV \
@@ -103,14 +105,19 @@ extern int __local_multiple_threads attribute_hidden;
b PLTJMP(SYSCALL_ERROR)
# define PSEUDO_PROLOGUE
# else
-# define SINGLE_THREAD_P \
- str lr, [sp, $-4]!; \
+# define SINGLE_THREAD_P_PIC(reg) \
ldr ip, 1b; \
- ldr lr, 2b; \
+ ldr reg, 2b; \
3: \
add ip, pc, ip; \
ldr ip, [ip, lr]; \
teq ip, #0;
+# define SINGLE_THREAD_P_INT \
+ str lr, [sp, $-4]!; \
+ SINGLE_THREAD_P_PIC(lr)
+# define SINGLE_THREAD_P \
+ SINGLE_THREAD_P_INT; \
+ ldr lr, [sp], $4
# define PSEUDO_PROLOGUE \
1: .word _GLOBAL_OFFSET_TABLE_ - 3f - 8; \
2: .word __local_multiple_threads(GOTOFF);
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
new file mode 100644
index 0000000000..6092bd9fd4
--- /dev/null
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
@@ -0,0 +1,57 @@
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Philip Blundell <philb@gnu.org>.
+
+ 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-cancel.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+/* Clone the calling process, but without copying the whole address
+pace.
+ The calling process is suspended until the new process exits or is
+ replaced by a call to `execve'. Return -1 for errors, 0 to the new
+rocess,
+ and the process ID of the new process to the old process. */
+
+ PSEUDO_PROLOGUE
+
+ENTRY (__vfork)
+
+#ifdef __NR_vfork
+ SINGLE_THREAD_P
+ bne HIDDEN_JUMPTARGET (__fork)
+ swi __NR_vfork
+ cmn a1, #4096
+ RETINSTR(movcc, pc, lr)
+
+ /* Check if vfork syscall is known at all. */
+ ldr a2, =-ENOSYS
+ teq a1, a2
+ bne PLTJMP(C_SYMBOL_NAME(__syscall_error))
+#endif
+
+ /* If we don't have vfork, fork is close enough. */
+ swi __NR_fork
+ cmn a1, #4096
+ RETINSTR(movcc, pc, lr)
+ b PLTJMP(C_SYMBOL_NAME(__syscall_error))
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)