Mercurial > sdl-ios-xcode
diff src/thread/linux/clone.S @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | 974ba6ae0fa3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/thread/linux/clone.S Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,186 @@ + +/* Taken with thanks from LinuxThreads 0.6 */ + +/* This is no longer necessary with glibc-2.1, which has it's own clone() */ +#ifdef linux +/* Look to see if glibc is available, and if so, what version */ +#include <features.h> + +#if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) +#define HAVE_CLONE +#endif /* glibc 2.1 or newer */ +#endif /* linux */ + +#if defined(linux) && !defined(SDL_USE_PTHREADS) && !defined(HAVE_CLONE) + +#if defined(__i386__) +/************************************************************************/ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@tamu.edu) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif +Cambridge, MA 02139, USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include <asm/errno.h> +#include <asm/unistd.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + .align 4 + .globl __clone + .type __clone,@function + .weak clone + clone = __clone +__clone: + /* Sanity check arguments. */ + movl $-EINVAL,%eax + movl 4(%esp),%ecx /* no NULL function pointers */ + testl %ecx,%ecx + jz syscall_error + movl 8(%esp),%ecx /* no NULL stack pointers */ + testl %ecx,%ecx + jz syscall_error + + /* Insert the argument onto the new stack. */ + subl $8,%ecx + movl 16(%esp),%eax + movl %eax,4(%ecx) + + /* Save the function pointer as the zeroth argument. */ + /* It will be popped off in the child in the ebx frobbing below. */ + movl 4(%esp),%eax + movl %eax,0(%ecx) + + /* Do the system call */ + pushl %ebx + movl 16(%esp),%ebx + movl $__NR_clone,%eax + int $0x80 + popl %ebx + + test %eax,%eax + jl syscall_error + jz thread_start + + ret + +syscall_error: + negl %eax + pushl %eax +#ifdef __PIC__ + call __errno_location@PLT +#else + call __errno_location +#endif + popl 0(%eax) + movl $-1, %eax + ret + +thread_start: + subl %ebp,%ebp /* terminate the stack frame */ + call *%ebx + pushl %eax +#ifdef __PIC__ + call _exit@PLT +#else + call _exit +#endif +/************************************************************************/ +#elif defined(sparc) +/************************************************************************/ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Miguel de Icaza (miguel@nuclecu.unam.mx) + Based on code written for the Intel by Richard + Henderson (rth@tamu.edu) + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include <asm/errno.h> +#include <asm/unistd.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + .align 4 + .globl __clone + .type __clone,@function + .weak clone + clone = __clone +__clone: + save %sp,-96,%sp + /* sanity check arguments */ + tst %i0 + be __clone_syscall_error + tst %i1 + be __clone_syscall_error + nop + + /* Do the system call */ + mov %i1,%o1 + mov %i2,%o0 + set __NR_clone,%g1 + ta 0x10 + bcs __clone_syscall_error + tst %o1 + bne __thread_start + nop + mov %o0,%i0 + ret + restore + +__clone_syscall_error: + call __errno_location + set EINVAL,%i0 + st %i0,[%o0] + mov -1,%i0 + ret + restore + +__thread_start: + call %i0 + mov %i3,%o0 + call _exit,0 + nop +/************************************************************************/ +#else +#error "Unknown Linux architecture" +#endif + +#endif /* Linux && ! SDL_USE_PTHREADS */