summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/Android.mk1
-rw-r--r--libc/SYSCALLS.TXT7
-rw-r--r--libc/arch-arm/bionic/clone.S108
-rw-r--r--libc/arch-arm/syscalls.mk2
-rw-r--r--libc/arch-arm/syscalls/__sys_clone.S (renamed from libc/arch-arm/syscalls/__clone.S)14
-rw-r--r--libc/arch-sh/bionic/clone.S5
-rw-r--r--libc/arch-sh/syscalls.mk2
-rw-r--r--libc/arch-sh/syscalls/__sys_clone.S (renamed from libc/arch-sh/syscalls/__clone.S)11
-rw-r--r--libc/arch-x86/bionic/clone.S5
-rw-r--r--libc/arch-x86/syscalls.mk2
-rw-r--r--libc/arch-x86/syscalls/__sys_clone.S (renamed from libc/arch-x86/syscalls/__clone.S)17
-rw-r--r--libc/bionic/bionic_clone.c81
-rw-r--r--libc/docs/CHANGES.TXT1
-rw-r--r--libc/include/sched.h5
-rw-r--r--libc/include/sys/linux-unistd.h2
15 files changed, 212 insertions, 51 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index c32cc30..e820b60 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -289,6 +289,7 @@ libc_common_src_files := \
ifeq ($(TARGET_ARCH),arm)
libc_common_src_files += \
bionic/eabi.c \
+ bionic/bionic_clone.c \
arch-arm/bionic/__get_pc.S \
arch-arm/bionic/__get_sp.S \
arch-arm/bionic/_exit_with_stack_teardown.S \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 684b43e..6a21b04 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -34,7 +34,12 @@ void _exit_thread:exit (int) 1
pid_t __fork:fork (void) 2
pid_t _waitpid:waitpid (pid_t, int*, int, struct rusage*) -1,7
int waitid(int, pid_t, struct siginfo_t*, int,void*) 280,284
-pid_t __clone:clone(int (*fn)(void*), void *child_stack, int flags, void *arg) 120
+
+# NOTE: this system call is never called directly, but we list it there
+# to have __NR_clone properly defined.
+#
+pid_t __sys_clone:clone (int, void*, int*, void*, int*) 120
+
int execve (const char*, char* const*, char* const*) 11
int setuid:setuid32 (uid_t) 213
diff --git a/libc/arch-arm/bionic/clone.S b/libc/arch-arm/bionic/clone.S
index 791c73d..9c25053 100644
--- a/libc/arch-arm/bionic/clone.S
+++ b/libc/arch-arm/bionic/clone.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,48 +27,102 @@
*/
#include <sys/linux-syscalls.h>
- .text
- .type __pthread_clone, #function
- .global __pthread_clone
- .align 4
-
+ .text
+ .type __pthread_clone, #function
+ .global __pthread_clone
+ .align 4
+ .fnstart
+
__pthread_clone:
- @ insert the args onto the new stack
- str r0, [r1, #-4]
- str r3, [r1, #-8]
+ @ insert the args onto the new stack
+ str r0, [r1, #-4]
+ str r3, [r1, #-8]
+
+ @ do the system call
+ @ get flags
- @ do the system call
- @ get flags
-
mov r0, r2
-
+
@ new sp is already in r1
#if __ARM_EABI__
stmfd sp!, {r4, r7}
ldr r7, =__NR_clone
- swi #0
+ swi #0
#else
- swi #__NR_clone
+ swi #__NR_clone
#endif
- movs r0, r0
+ movs r0, r0
#if __ARM_EABI__
ldmnefd sp!, {r4, r7}
#endif
- blt __error
- bxne lr
+ blt __error
+ bxne lr
- @ pick the function arg and call address off the stack and jump
- @ to the C __thread_entry function which does some setup and then
- @ calls the thread's start function
+ @ pick the function arg and call address off the stack and jump
+ @ to the C __thread_entry function which does some setup and then
+ @ calls the thread's start function
- ldr r0, [sp, #-4]
- ldr r1, [sp, #-8]
- mov r2, sp @ __thread_entry needs the TLS pointer
- b __thread_entry
+ ldr r0, [sp, #-4]
+ ldr r1, [sp, #-8]
+ mov r2, sp @ __thread_entry needs the TLS pointer
+ b __thread_entry
__error:
- mov r0, #-1
- bx lr
+ mov r0, #-1
+ bx lr
+ .fnend
+
+
+ #
+ # This function is defined as:
+ #
+ # pid_t __bionic_clone( int flags, void *child_stack,
+ # pid_t *pid, void *tls, pid_t *ctid,
+ # int (*fn)(void *), void* arg );
+ #
+ # NOTE: This is not the same signature than the GLibc
+ # __clone function here !! Placing 'fn' and 'arg'
+ # at the end of the parameter list makes the
+ # implementation much simpler.
+ #
+ .type __bionic_clone, #function
+ .globl __bionic_clone
+ .align 4
+ .fnstart
+
+__bionic_clone:
+ mov ip, sp
+ .save {r4, r5, r6, r7}
+
+ # save registers to parent stack
+ stmfd sp!, {r4, r5, r6, r7}
+
+ # load extra parameters
+ ldmfd ip, {r4, r5, r6}
+
+ # store 'fn' and 'arg' to the child stack
+ str r5, [r1, #-4]
+ str r6, [r1, #-8]
+
+ # system call
+ ldr r7, =__NR_clone
+ swi #0
+ movs r0, r0
+ beq 1f
+
+ # in parent, reload saved registers
+ # then either exit or error
+ #
+ ldmfd sp!, {r4, r5, r6, r7}
+ bxne lr
+ b __set_syscall_errno
+
+1: # in the child - pick arguments
+ ldr r0, [sp, #-4]
+ ldr r1, [sp, #-8]
+ b __bionic_clone_entry
+
+ .fnend
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 706cb0c..5f416e8 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -4,7 +4,7 @@ syscall_src += arch-arm/syscalls/_exit.S
syscall_src += arch-arm/syscalls/_exit_thread.S
syscall_src += arch-arm/syscalls/__fork.S
syscall_src += arch-arm/syscalls/waitid.S
-syscall_src += arch-arm/syscalls/__clone.S
+syscall_src += arch-arm/syscalls/__sys_clone.S
syscall_src += arch-arm/syscalls/execve.S
syscall_src += arch-arm/syscalls/setuid.S
syscall_src += arch-arm/syscalls/getuid.S
diff --git a/libc/arch-arm/syscalls/__clone.S b/libc/arch-arm/syscalls/__sys_clone.S
index 650e2c0..9fe2641 100644
--- a/libc/arch-arm/syscalls/__clone.S
+++ b/libc/arch-arm/syscalls/__sys_clone.S
@@ -2,17 +2,19 @@
#include <sys/linux-syscalls.h>
.text
- .type __clone, #function
- .globl __clone
+ .type __sys_clone, #function
+ .globl __sys_clone
.align 4
.fnstart
-__clone:
- .save {r4, r7}
- stmfd sp!, {r4, r7}
+__sys_clone:
+ mov ip, sp
+ .save {r4, r5, r6, r7}
+ stmfd sp!, {r4, r5, r6, r7}
+ ldmfd ip, {r4, r5, r6}
ldr r7, =__NR_clone
swi #0
- ldmfd sp!, {r4, r7}
+ ldmfd sp!, {r4, r5, r6, r7}
movs r0, r0
bxpl lr
b __set_syscall_errno
diff --git a/libc/arch-sh/bionic/clone.S b/libc/arch-sh/bionic/clone.S
index 0bbaecb..9cb19ee 100644
--- a/libc/arch-sh/bionic/clone.S
+++ b/libc/arch-sh/bionic/clone.S
@@ -72,3 +72,8 @@ __return:
.align 2
0: .long __NR_clone
1: .long __thread_entry
+
+/* XXX: TODO: Add __bionic_clone here
+ * See bionic/bionic_clone.c and arch-arm/bionic/clone.S
+ * for more details...
+ */ \ No newline at end of file
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index cefb2ec..d3e531e 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -5,7 +5,7 @@ syscall_src += arch-sh/syscalls/_exit_thread.S
syscall_src += arch-sh/syscalls/__fork.S
syscall_src += arch-sh/syscalls/_waitpid.S
syscall_src += arch-sh/syscalls/waitid.S
-syscall_src += arch-sh/syscalls/__clone.S
+syscall_src += arch-sh/syscalls/__sys_clone.S
syscall_src += arch-sh/syscalls/execve.S
syscall_src += arch-sh/syscalls/setuid.S
syscall_src += arch-sh/syscalls/getuid.S
diff --git a/libc/arch-sh/syscalls/__clone.S b/libc/arch-sh/syscalls/__sys_clone.S
index 1df6ca2..c2e7dd2 100644
--- a/libc/arch-sh/syscalls/__clone.S
+++ b/libc/arch-sh/syscalls/__sys_clone.S
@@ -2,15 +2,18 @@
#include <sys/linux-syscalls.h>
.text
- .type __clone, @function
- .globl __clone
+ .type __sys_clone, @function
+ .globl __sys_clone
.align 4
-__clone:
+__sys_clone:
+
+ /* get ready for additonal arg */
+ mov.l @r15, r0
/* invoke trap */
mov.l 0f, r3 /* trap num */
- trapa #(4 + 0x10)
+ trapa #(5 + 0x10)
/* check return value */
cmp/pz r0
diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S
index 361808d..3b50cc3 100644
--- a/libc/arch-x86/bionic/clone.S
+++ b/libc/arch-x86/bionic/clone.S
@@ -48,3 +48,8 @@ __pthread_clone:
popl %ecx
popl %ebx
ret
+
+/* XXX: TODO: Add __bionic_clone here
+ * See bionic/bionic_clone.c and arch-arm/bionic/clone.S
+ * for more details...
+ */ \ No newline at end of file
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 86d2308..e718e18 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -5,7 +5,7 @@ syscall_src += arch-x86/syscalls/_exit_thread.S
syscall_src += arch-x86/syscalls/__fork.S
syscall_src += arch-x86/syscalls/_waitpid.S
syscall_src += arch-x86/syscalls/waitid.S
-syscall_src += arch-x86/syscalls/__clone.S
+syscall_src += arch-x86/syscalls/__sys_clone.S
syscall_src += arch-x86/syscalls/execve.S
syscall_src += arch-x86/syscalls/setuid.S
syscall_src += arch-x86/syscalls/getuid.S
diff --git a/libc/arch-x86/syscalls/__clone.S b/libc/arch-x86/syscalls/__sys_clone.S
index 5862129..172d6af 100644
--- a/libc/arch-x86/syscalls/__clone.S
+++ b/libc/arch-x86/syscalls/__sys_clone.S
@@ -2,19 +2,21 @@
#include <sys/linux-syscalls.h>
.text
- .type __clone, @function
- .globl __clone
+ .type __sys_clone, @function
+ .globl __sys_clone
.align 4
-__clone:
+__sys_clone:
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
- mov 20(%esp), %ebx
- mov 24(%esp), %ecx
- mov 28(%esp), %edx
- mov 32(%esp), %esi
+ pushl %edi
+ mov 24(%esp), %ebx
+ mov 28(%esp), %ecx
+ mov 32(%esp), %edx
+ mov 36(%esp), %esi
+ mov 40(%esp), %edi
movl $__NR_clone, %eax
int $0x80
cmpl $-129, %eax
@@ -25,6 +27,7 @@ __clone:
addl $4, %esp
orl $-1, %eax
1:
+ popl %edi
popl %esi
popl %edx
popl %ecx
diff --git a/libc/bionic/bionic_clone.c b/libc/bionic/bionic_clone.c
new file mode 100644
index 0000000..6b2fa58
--- /dev/null
+++ b/libc/bionic/bionic_clone.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define __GNU_SOURCE 1
+#include <sched.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/* WARNING: AT THE MOMENT, THIS IS ONLY SUPPORTED ON ARM
+ */
+
+extern int __bionic_clone(unsigned long clone_flags,
+ void* newsp,
+ int *parent_tidptr,
+ void *new_tls,
+ int *child_tidptr,
+ int (*fn)(void *),
+ void *arg);
+
+extern void _exit_thread(int retCode);
+
+/* this function is called from the __bionic_clone
+ * assembly fragment to call the thread function
+ * then exit. */
+extern void
+__bionic_clone_entry( int (*fn)(void *), void *arg )
+{
+ int ret = (*fn)(arg);
+ _exit_thread(ret);
+}
+
+int
+clone(int (*fn)(void *), void *child_stack, int flags, void* arg, ...)
+{
+ va_list args;
+ int *parent_tidptr = NULL;
+ void *new_tls = NULL;
+ int *child_tidptr = NULL;
+ int ret;
+
+ /* extract optional parameters - they are cummulative */
+ va_start(args, arg);
+ if (flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) {
+ parent_tidptr = va_arg(args, int*);
+ }
+ if (flags & (CLONE_SETTLS|CLONE_CHILD_SETTID)) {
+ new_tls = va_arg(args, void*);
+ }
+ if (flags & CLONE_CHILD_SETTID) {
+ child_tidptr = va_arg(args, int*);
+ }
+ va_end(args);
+
+ ret = __bionic_clone(flags, child_stack, parent_tidptr, new_tls, child_tidptr, fn, arg);
+ return ret;
+}
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 07eac57..c2655c5 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -46,6 +46,7 @@ Differences between current and Android 2.1:
- <wchar.h>: Add mbstowcs() and wcstombs()
+- add clone() implementation for ARM (x86 and SH-4 not working yet)
-------------------------------------------------------------------------------
Differences between Android 2.1 and 2.0.1:
diff --git a/libc/include/sched.h b/libc/include/sched.h
index 6600bae..33b9ad6 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -69,8 +69,9 @@ extern int sched_rr_get_interval(pid_t pid, struct timespec *tp);
#define CLONE_CHILD_SETTID 0x01000000
#define CLONE_STOPPED 0x02000000
-extern int clone(int (*fn)(void*), void *child_stack, int flags, void *arg);
-extern pid_t __clone(int, void *);
+#ifdef __GNU_SOURCE
+extern int clone(int (*fn)(void *), void *child_stack, int flags, void* arg, ...);
+#endif
__END_DECLS
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index 12f7704..9a151d2 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -10,7 +10,7 @@ void _exit_thread (int);
pid_t __fork (void);
pid_t _waitpid (pid_t, int*, int, struct rusage*);
int waitid (int, pid_t, struct siginfo_t*, int,void*);
-pid_t __clone (int (*fn)(void*), void *child_stack, int flags, void *arg);
+pid_t __sys_clone (int, void*, int*, void*, int*);
int execve (const char*, char* const*, char* const*);
int setuid (uid_t);
uid_t getuid (void);