preparation for generic kernel_thread()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Sep 2012 23:55:31 +0000 (19:55 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 30 Sep 2012 17:35:55 +0000 (13:35 -0400)
Let architectures select GENERIC_KERNEL_THREAD and have their copy_thread()
treat NULL regs as "it came from kernel_thread(), sp argument contains
the function new thread will be calling and stack_size - the argument for
that function".  Switching the architectures begins shortly...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/Kconfig
include/linux/sched.h
kernel/fork.c

index 72f2fa189cc5200bb98143c6b35de8ffc9e0aaee..d397e11d167d9c9923e418dcb3599a3a14de6590 100644 (file)
@@ -258,6 +258,9 @@ config ARCH_WANT_OLD_COMPAT_IPC
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        bool
 
+config GENERIC_KERNEL_THREAD
+       bool
+
 config HAVE_ARCH_SECCOMP_FILTER
        bool
        help
index 23bddac4bad8d08f3781d1e8a453aa41edb28632..34da9340c6a43dacb0f67404a3efeb650084c006 100644 (file)
@@ -2325,6 +2325,9 @@ extern int do_execve(const char *,
                     const char __user * const __user *, struct pt_regs *);
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
 struct task_struct *fork_idle(int);
+#ifdef CONFIG_GENERIC_KERNEL_THREAD
+extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+#endif
 
 extern void set_task_comm(struct task_struct *tsk, char *from);
 extern char *get_task_comm(char *to, struct task_struct *tsk);
index 2c8857e12855393759562b3c6eeec2d23de6f080..a42c62a8eb248b9540aa86298101055eb96562b9 100644 (file)
@@ -1609,7 +1609,7 @@ long do_fork(unsigned long clone_flags,
         * requested, no event is reported; otherwise, report if the event
         * for the type of forking is enabled.
         */
-       if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
+       if (!(clone_flags & CLONE_UNTRACED) && likely(user_mode(regs))) {
                if (clone_flags & CLONE_VFORK)
                        trace = PTRACE_EVENT_VFORK;
                else if ((clone_flags & CSIGNAL) != SIGCHLD)
@@ -1659,6 +1659,17 @@ long do_fork(unsigned long clone_flags,
        return nr;
 }
 
+#ifdef CONFIG_GENERIC_KERNEL_THREAD
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, NULL,
+               (unsigned long)arg, NULL, NULL);
+}
+#endif
+
 #ifndef ARCH_MIN_MMSTRUCT_ALIGN
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif