OSDN Git Service

add linuxthreads support for arm. By Will Newton (will.newton AT gmail.com)
authorDenis Vlasenko <vda.linux@googlemail.com>
Thu, 12 Mar 2009 23:04:19 +0000 (23:04 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Thu, 12 Mar 2009 23:04:19 +0000 (23:04 -0000)
libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h [new file with mode: 0644]
libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S [new file with mode: 0644]

diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..75fcf54
--- /dev/null
@@ -0,0 +1,130 @@
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 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 <tls.h>
+#include <pt-machine.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+/* We push lr onto the stack, so we have to use ldmib instead of ldmia
+   to find the saved arguments.  */
+# ifdef PIC
+#  undef DOARGS_5
+#  undef DOARGS_6
+#  undef DOARGS_7
+#  define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $8];
+#  define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmib ip, {r4, r5};
+#  define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmib ip, {r4, r5, r6};
+# endif
+
+# undef PSEUDO_RET
+# define PSEUDO_RET                                                    \
+    ldrcc pc, [sp], $4;                                                        \
+    ldr        lr, [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;                                                     \
+    RETINSTR(cc, lr);                                                  \
+    b PLTJMP(SYSCALL_ERROR);                                           \
+  .Lpseudo_cancel:                                                     \
+    str lr, [sp, $-4]!;                                                        \
+    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   ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24]
+# 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 PSEUDO_PROLOGUE
+#  else
+#   define SINGLE_THREAD_P                                             \
+  ldr ip, 1b;                                                          \
+2:                                                                     \
+  ldr ip, [pc, ip];                                                    \
+  teq ip, #0;
+#   define PSEUDO_PROLOGUE                                             \
+  1:  .word __local_multiple_threads - 2f - 8;
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
new file mode 100644 (file)
index 0000000..2543f57
--- /dev/null
@@ -0,0 +1,78 @@
+/* Copyright (C) 1999, 2002, 2003, 2005 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>
+#include <kernel-features.h>
+
+/* Clone the calling process, but without copying the whole address space.
+   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 process,
+   and the process ID of the new process to the old process.  */
+
+ENTRY (__vfork)
+
+#ifdef __NR_vfork
+
+#ifdef SHARED
+       ldr     ip, 1f
+       ldr     r0, 2f
+3:     add     ip, pc, ip
+       ldr     r0, [ip, r0]
+#else
+       ldr     r0, 1f
+#endif
+       movs    r0, r0
+       bne     HIDDEN_JUMPTARGET (__fork)
+
+       DO_CALL (vfork, 0)
+       cmn     a1, #4096
+       RETINSTR(cc, lr)
+
+#ifndef __ASSUME_VFORK_SYSCALL
+       /* Check if vfork syscall is known at all.  */
+       cmn     a1, #ENOSYS
+       bne     PLTJMP(C_SYMBOL_NAME(__syscall_error))
+#endif
+
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
+       /* If we don't have vfork, fork is close enough.  */
+       DO_CALL (fork, 0)
+       cmn     a1, #4096
+       RETINSTR(cc, lr)
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
+#endif
+       b       PLTJMP(C_SYMBOL_NAME(__syscall_error))
+
+#ifdef SHARED
+1:     .word   _GLOBAL_OFFSET_TABLE_ - 3b - 8
+2:     .word   __libc_pthread_functions(GOTOFF)
+#else
+       .weak   pthread_create
+1:     .word   pthread_create
+#endif
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)