diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-12 23:04:19 +0000 | 
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-12 23:04:19 +0000 | 
| commit | d0ac81b3ec586e7d053406de3741b62482b62e64 (patch) | |
| tree | 395344dfbf6e73b40cf4e6ec6c2a0937c56c03e9 /libpthread/linuxthreads/sysdeps | |
| parent | 52c9ef85a65f4dc25a4d1ff79c0fba1ed53ef43a (diff) | |
add linuxthreads support for arm. By Will Newton (will.newton AT gmail.com)
Diffstat (limited to 'libpthread/linuxthreads/sysdeps')
| -rw-r--r-- | libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h | 130 | ||||
| -rw-r--r-- | libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S | 78 | 
2 files changed, 208 insertions, 0 deletions
| 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 index 000000000..75fcf54fa --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -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 index 000000000..2543f578a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S @@ -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) | 
