Browse Source

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>
Al Viro 13 years ago
parent
commit
d2125043ae
3 changed files with 60 additions and 4 deletions
  1. 14 0
      arch/Kconfig
  2. 3 4
      include/asm-generic/syscalls.h
  3. 43 0
      kernel/fork.c

+ 14 - 0
arch/Kconfig

@@ -341,4 +341,18 @@ config MODULES_USE_ELF_REL
 	  Modules only use ELF REL relocations.  Modules with ELF RELA
 	  Modules only use ELF REL relocations.  Modules with ELF RELA
 	  relocations will give an error.
 	  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"
 source "kernel/gcov/Kconfig"

+ 3 - 4
include/asm-generic/syscalls.h

@@ -10,16 +10,15 @@
  */
  */
 #ifndef sys_clone
 #ifndef sys_clone
 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
 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
 #endif
 
 
 #ifndef sys_fork
 #ifndef sys_fork
-asmlinkage long sys_fork(struct pt_regs *regs);
+asmlinkage long sys_fork(void);
 #endif
 #endif
 
 
 #ifndef sys_vfork
 #ifndef sys_vfork
-asmlinkage long sys_vfork(struct pt_regs *regs);
+asmlinkage long sys_vfork(void);
 #endif
 #endif
 
 
 #ifndef sys_execve
 #ifndef sys_execve

+ 43 - 0
kernel/fork.c

@@ -1645,6 +1645,49 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 }
 }
 #endif
 #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
 #ifndef ARCH_MIN_MMSTRUCT_ALIGN
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
 #endif