| /* |
| * libc/sysdeps/linux/nios2/clone.c -- `clone' syscall for linux/nios2 |
| * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> |
| * |
| * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. |
| * |
| * |
| * Copyright (C) 2004,05 Microtronix Datacom Ltd |
| * Copyright (C) 2002,03 NEC Electronics Corporation |
| * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> |
| * |
| * Written by Miles Bader <miles@gnu.org> |
| * Nios2 port by Wentao Xu |
| */ |
| |
| #include <errno.h> |
| #include <sched.h> |
| #include <sys/syscall.h> |
| |
| int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) |
| { |
| register unsigned long rval __asm__ ("r2") = -EINVAL; |
| |
| if (fn && child_stack) { |
| register unsigned long syscall __asm__ ("r3"); |
| register unsigned long arg0 __asm__ ("r4"); |
| register unsigned long arg1 __asm__ ("r5"); |
| |
| /* Clone this thread. */ |
| rval = TRAP_ID_SYSCALL; |
| syscall = __NR_clone; |
| arg0 = flags; |
| arg1 = (unsigned long)child_stack; |
| __asm__ __volatile__ ("trap " |
| : "=r" (rval), "=r" (syscall) |
| : "0" (rval),"1" (syscall), "r" (arg0), "r" (arg1) |
| ); |
| |
| if (rval == 0) { |
| /* In child thread, call fn and exit. */ |
| arg0 = (*fn) (arg); |
| syscall = __NR_exit; |
| __asm__ __volatile__ ("trap " |
| : "=r" (rval), "=r" (syscall) |
| : "1" (syscall), "r" (arg0)); |
| } |
| } |
| |
| __syscall_return (int, rval); |
| } |