summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-23 13:17:59 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-11-28 21:49:04 -0500
commitd2125043aebf7f53cd1c72115c17b01d0bc06ce1 (patch)
treee6d510a22905d870a612660c2da0bdb6e36bc7e6
parent25906730ec01be664534c9439d7cf5a373e8a4e4 (diff)
generic sys_fork / sys_vfork / sys_clone
... and get rid of idiotic struct pt_regs * in asm-generic/syscalls.h prototypes of the same, while we are at it. Eventually we want those in linux/syscalls.h, of course, but that'll have to wait a bit. Note that there are *three* variants of sys_clone() order of arguments. Braindamage galore... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/Kconfig14
-rw-r--r--include/asm-generic/syscalls.h7
-rw-r--r--kernel/fork.c43
3 files changed, 60 insertions, 4 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index 366ec06a518..8d698fb5ccc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -341,4 +341,18 @@ config MODULES_USE_ELF_REL
Modules only use ELF REL relocations. Modules with ELF RELA
relocations will give an error.
+#
+# ABI hall of shame
+#
+config CLONE_BACKWARDS
+ bool
+ help
+ Architecture has tls passed as the 4th argument of clone(2),
+ not the 5th one.
+
+config CLONE_BACKWARDS2
+ bool
+ help
+ Architecture has the first two arguments of clone(2) swapped.
+
source "kernel/gcov/Kconfig"
diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h
index d89dec864d4..7e4fdb64995 100644
--- a/include/asm-generic/syscalls.h
+++ b/include/asm-generic/syscalls.h
@@ -10,16 +10,15 @@
*/
#ifndef sys_clone
asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
- void __user *parent_tid, void __user *child_tid,
- struct pt_regs *regs);
+ void __user *parent_tid, void __user *child_tid);
#endif
#ifndef sys_fork
-asmlinkage long sys_fork(struct pt_regs *regs);
+asmlinkage long sys_fork(void);
#endif
#ifndef sys_vfork
-asmlinkage long sys_vfork(struct pt_regs *regs);
+asmlinkage long sys_vfork(void);
#endif
#ifndef sys_execve
diff --git a/kernel/fork.c b/kernel/fork.c
index 8b20ab7d3aa..27a337549da 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1645,6 +1645,49 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
}
#endif
+#ifdef __ARCH_WANT_SYS_FORK
+SYSCALL_DEFINE0(fork)
+{
+#ifdef CONFIG_MMU
+ return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL);
+#else
+ /* can not support in nommu mode */
+ return(-EINVAL);
+#endif
+}
+#endif
+
+#ifdef __ARCH_WANT_SYS_VFORK
+SYSCALL_DEFINE0(vfork)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, current_pt_regs(),
+ 0, NULL, NULL);
+}
+#endif
+
+#ifdef __ARCH_WANT_SYS_CLONE
+#ifdef CONFIG_CLONE_BACKWARDS
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+ int __user *, parent_tidptr,
+ int, tls_val,
+ int __user *, child_tidptr)
+#elif defined(CONFIG_CLONE_BACKWARDS2)
+SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
+ int __user *, parent_tidptr,
+ int __user *, child_tidptr,
+ int, tls_val)
+#else
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+ int __user *, parent_tidptr,
+ int __user *, child_tidptr,
+ int, tls_val)
+#endif
+{
+ return do_fork(clone_flags, newsp, current_pt_regs(), 0,
+ parent_tidptr, child_tidptr);
+}
+#endif
+
#ifndef ARCH_MIN_MMSTRUCT_ALIGN
#define ARCH_MIN_MMSTRUCT_ALIGN 0
#endif