diff options
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/vfork.S | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S index 6f7477e89d..59657e49c0 100644 --- a/sysdeps/unix/sysv/linux/i386/vfork.S +++ b/sysdeps/unix/sysv/linux/i386/vfork.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Schwab <schwab@gnu.org>. @@ -20,6 +20,7 @@ #include <sysdep.h> #define _ERRNO_H 1 #include <bits/errno.h> +#include <kernel-features.h> /* Clone the calling process, but without copying the whole address space. The calling process is suspended until the new process exits or is @@ -36,22 +37,32 @@ ENTRY (__vfork) /* Stuff the syscall number in EAX and enter into the kernel. */ movl $SYS_ify (vfork), %eax int $0x80 + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + cmpl $-4095, %eax - jae .Lerror /* Branch forward if it failed. */ + /* Branch forward if it failed. */ +# ifdef __ASSUME_VFORK_SYSCALL + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: +# else + jae .Lerror +# endif - /* Jump to the return PC. */ - jmp *%ecx + ret +# ifndef __ASSUME_VFORK_SYSCALL .Lerror: - /* Push back the return PC. */ - pushl %ecx - /* Check if vfork syscall is known at all. */ cmpl $-ENOSYS, %eax jne SYSCALL_ERROR_LABEL - +# endif #endif +#ifndef __ASSUME_VFORK_SYSCALL /* If we don't have vfork, fork is close enough. */ movl $SYS_ify (fork), %eax @@ -60,7 +71,7 @@ ENTRY (__vfork) jae SYSCALL_ERROR_LABEL .Lpseudo_end: ret - +#endif PSEUDO_END (__vfork) weak_alias (__vfork, vfork) |