-/* Adapted from glibc */
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */
+/* Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp> */
/* 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 <bits/errno.h>
#include <sys/syscall.h>
-/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg
+ void *parent_tidptr, void *tls, void *child_tidptr) */
#ifdef __H8300H__
.h8300h
#endif
.text
-.globl _clone
-_clone:
+.globl clone
+clone:
/* Sanity check arguments. */
mov.l #-EINVAL,er3
mov.l er0,er0 /* no NULL function pointers */
mov.l @(4:16,sp),er3
mov.l er3,@-er1
- /* Do the system call */
+ /* setup argument */
mov.l er0,er3 /* er3 = child entry */
- mov.l er1,er0
- mov.l er2,er1 /* er1 = flags */
- mov.l er0,er2 /* er2 = child sp */
- mov.l #__NR_clone,r0
+ sub.l #20,sp
+ mov.l er2,@sp /* flags */
+ mov.l er1,@(4,sp) /* new sp */
+ mov.l sp,er1
+ mov.l @(20+8,sp),er0
+ mov.l er0,@er1 /* parent tid */
+ adds #4,er1
+ mov.l @(20+16,sp),er0
+ mov.l er0,@er1 /* child tid */
+ adds #4,er1
+ mov.l @(20+12,sp),er0
+ mov.l er0,@er1 /* tls */
+ /* do the system call */
+ mov.l sp,er1
+ mov.l #__NR_clone,er0
trapa #0
+ add.l #20,sp
mov.l er0,er0
bmi __syscall_error
beq thread_start
mov.l er0,er1
mov.l #__NR_exit,er0
trapa #0
+
+ .end
+/* Copyright 2002, 2015 Yoshinori Sato <ysato@users.sourceforge.jp> */
#include <sys/syscall.h>
#endif
.text
.align 2
- .globl ___vfork
- .hidden ___vfork
- .type ___vfork,@function
-___vfork:
+ .globl __vfork
+ .hidden __vfork
+ .type __vfork,@function
+__vfork:
+#ifdef __NR_vfork
mov.l @sp+, er1
sub.l er0,er0
mov.b #__NR_vfork,r0l
trapa #0
+
mov.l #-4096, er2
cmp.l er0,er2
bcs fix_errno
fix_errno:
neg.l er0
#if !defined(__PIC__)
- mov.l er0,@_errno
+ mov.l er0,@errno
#else
- mov.l @(_errno@GOTOFF,er5),er2
+ mov.l @(errno@GOTOFF,er5),er2
mov.l er0,@er2
#endif
sub.l er0,er0
dec.l #1,er0
jmp @er1 /* don't return, just jmp directly */
+#else
+ mov.l @sp+,er2 /* er2 = return address */
+ mov.l #vfork_args,er1
+ sub.l er0,er0
+ mov.b #__NR_clone,r0l
+ trapa #0
+ mov.l #-4096,er1
+ cmp.l er0,er1
+ bcc done
+ neg.l er0
+#if !defined(__PIC__)
+ mov.l er0,@errno
+#else
+ mov.l @(errno@GOTOFF,er5),er2
+ mov.l er0,@er2
+#endif
+ sub.l er0,er0
+ dec.l #1,er0
+done:
+ jmp @er1
+
+vfork_args:
+ .long CLONE_VFORK | CLONE_VM | SIGCHLD
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+#endif
weak_alias(__vfork,vfork)
libc_hidden_def(vfork)
+ .end