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 */