Name: __kernel_thread Author: Rusty Russell Status: Experimental D: kernel_thread creates and starts a new kernel thread. Introduce D: __kernel_thread and start_kernel_thread which split this into to D: copy_process() part and the actual starting part. This is useful D: for more sophisticated thread creation, such as required for hotplug D: cpus creating new idle threads, and two-stage CPU bringup. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .6154-linux-2.5.74-bk7/arch/i386/kernel/process.c .6154-linux-2.5.74-bk7.updated/arch/i386/kernel/process.c --- .6154-linux-2.5.74-bk7/arch/i386/kernel/process.c 2003-06-23 10:52:42.000000000 +1000 +++ .6154-linux-2.5.74-bk7.updated/arch/i386/kernel/process.c 2003-07-10 13:01:06.000000000 +1000 @@ -210,7 +210,9 @@ __asm__(".align 4\n" /* * Create a kernel thread */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +struct task_struct *__kernel_thread(int (*fn)(void *), + void *arg, + unsigned long flags) { struct pt_regs regs; @@ -227,7 +229,8 @@ int kernel_thread(int (*fn)(void *), voi regs.eflags = 0x286; /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return copy_process(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, + NULL, NULL); } /* diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .6154-linux-2.5.74-bk7/include/asm-i386/processor.h .6154-linux-2.5.74-bk7.updated/include/asm-i386/processor.h --- .6154-linux-2.5.74-bk7/include/asm-i386/processor.h 2003-06-23 10:52:55.000000000 +1000 +++ .6154-linux-2.5.74-bk7.updated/include/asm-i386/processor.h 2003-07-10 14:46:12.000000000 +1000 @@ -463,9 +463,10 @@ extern void release_thread(struct task_s extern void prepare_to_copy(struct task_struct *tsk); /* - * create a kernel thread without removing it from tasklists + * create a kernel thread without removing it from tasklists, don't start it. */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); +extern struct task_struct *__kernel_thread(int (*fn)(void *), + void *arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *tsk); void show_trace(struct task_struct *task, unsigned long *stack); diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .6154-linux-2.5.74-bk7/kernel/fork.c .6154-linux-2.5.74-bk7.updated/kernel/fork.c --- .6154-linux-2.5.74-bk7/kernel/fork.c 2003-07-10 10:55:48.000000000 +1000 +++ .6154-linux-2.5.74-bk7.updated/kernel/fork.c 2003-07-10 13:05:57.000000000 +1000 @@ -1135,6 +1135,39 @@ long do_fork(unsigned long clone_flags, return pid; } +void start_kernel_thread(struct task_struct *p, int vforked) +{ + struct completion vfork; + + if (vforked) { + p->vfork_done = &vfork; + init_completion(&vfork); + } + + wake_up_forked_process(p); + ++total_forks; + + if (vforked) + wait_for_completion(&vfork); +} + +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct task_struct *p; + int pid; + + p = __kernel_thread(fn, arg, flags); + if (IS_ERR(p)) + return PTR_ERR(p); + + /* Grab pid before it's woken: it could exit immediately. */ + pid = p->pid; + + start_kernel_thread(p, flags & CLONE_VFORK); + return pid; +} + + /* SLAB cache for signal_struct structures (tsk->signal) */ kmem_cache_t *signal_cachep;