Second Coming of Kthread: Using kthread
PATCH 2/2 Second Coming of Kthread: Using kthread
And this patch is *much* simpler than the previous version, since the kthread semantics are so close to kernel_thread.
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Name: Use Kthread For Core Kernel Threads
Author: Rusty Russell
Status: Tested on 2.6.1-rc1-bk6
Depends: Hotcpu-New-Kthread/kthread-simple.patch.gz
D: This simply changes over the migration threads, the workqueue
D: threads and the ksoftirqd threads to use kthread.
kernel/sched.c +19 -41
@@ -37,6 +37,7 @@#include <linux/rcupdate.h> #include <linux/cpu.h> #include <linux/percpu.h> +#include <linux/kthread.h> #ifdef CONFIG_NUMA #define cpu_to_node_mask (cpu) node_to_cpumask(cpu_to_node(cpu))
@@ -2640,12 +2641,6 @@ static void move_task_away(struct task_slocal_irq_restore (flags); } -typedef struct { -int cpu; -struct completion startup_done; -task_t *task; -}migration_startup_t ; -/* * migration_thread - this is a highprio system thread that performs * thread migration by bumping thread off CPU then 'pushing' onto
@@ -2655,27 +2650,17 @@ static int migration_thread(void * data) {/* Marking "param" __user is ok, since we do a set_fs(KERNEL_DS); */ struct sched_param __user param = { .sched_priority =MAX_RT_PRIO -1 }; -migration_startup_t *startup = data; -int cpu = startup->cpu;runqueue_t *rq; +int cpu = (long )data;int ret; - startup->task = current; -complete (&startup->startup_done); -set_current_state (TASK_UNINTERRUPTIBLE ); -schedule (); -BUG_ON (smp_processor_id () != cpu); - -daemonize ("migration/%d" , cpu); -set_fs (KERNEL_DS ); - ret =setscheduler (0 ,SCHED_FIFO , ¶m); rq =this_rq (); - rq->migration_thread = current; +BUG_ON (rq->migration_thread != current); -for (;;) { +while (!signal_pending (current)) {struct list_head *head;migration_req_t *req;
@@ -2698,6 +2683,7 @@ static int migration_thread(void * data) any_online_cpu(req->task->cpus_allowed));complete (&req->done); } +return 0 ; }/*
@@ -2708,36 +2694,28 @@ static int migration_call(struct notifieunsigned long action, void *hcpu) { - long cpu = (long) hcpu; -migration_startup_t startup; + int cpu = (long)hcpu; +struct task_struct *p;switch (action) {case CPU_ONLINE : - -printk ("Starting migration thread for cpu %li\n" , cpu); - - startup.cpu = cpu; - startup.task =NULL ; -init_completion (&startup.startup_done); - -kernel_thread (migration_thread, &startup,CLONE_KERNEL ); -wait_for_completion (&startup.startup_done); -wait_task_inactive (startup.task); - - startup.task->thread_info->cpu = cpu; - startup.task->cpus_allowed =cpumask_of_cpu (cpu); - -wake_up_process (startup.task); - -while (!cpu_rq (cpu)->migration_thread) -yield (); - + p =kthread_create (migration_thread, hcpu,"migration/%d" ,cpu); +if (IS_ERR (p)) +return NOTIFY_BAD ; + p->thread_info->cpu = cpu; + p->cpus_allowed =cpumask_of_cpu (cpu); +cpu_rq (cpu)->migration_thread = p; +kthread_start (p);break ; }return NOTIFY_OK ; } -static struct notifier_block migration_notifier = { &migration_call,NULL ,0 }; +/* Want this before the other threads, so they can use set_cpus_allowed. */ +static struct notifier_block __devinitdata migration_notifier = { + .notifier_call = migration_call, + .priority =10 , +};__init int migration_init (void ) {
kernel/softirq.c +10 -12
@@ -14,6 +14,7 @@#include <linux/notifier.h> #include <linux/percpu.h> #include <linux/cpu.h> +#include <linux/kthread.h> /* - No shared variables, all the data are CPU local.
@@ -337,20 +338,14 @@ static int ksoftirqd(void * __bind_cpu) {int cpu = (int ) (long ) __bind_cpu; -daemonize ("ksoftirqd/%d" , cpu);set_user_nice (current,19 ); current->flags |=PF_IOTHREAD ; -/* Migrate to the right CPU */ -set_cpus_allowed (current,cpumask_of_cpu (cpu));BUG_ON (smp_processor_id () != cpu); -__set_current_state (TASK_INTERRUPTIBLE ); -mb (); - -__get_cpu_var (ksoftirqd) = current; +set_current_state (TASK_INTERRUPTIBLE ); -for (;;) { +while (!signal_pending (current)) {if (!local_softirq_pending ())schedule ();
@@ -363,6 +358,7 @@ static int ksoftirqd(void * __bind_cpu)__set_current_state (TASK_INTERRUPTIBLE ); } +return 0 ; } static int __devinit cpu_callback(struct notifier_block *nfb,
@@ -370,15 +366,17 @@ static int __devinit cpu_callback(struct void *hcpu) {int hotcpu = (unsigned long )hcpu; +struct task_struct *p;if (action ==CPU_ONLINE ) { -if (kernel_thread (ksoftirqd, hcpu,CLONE_KERNEL ) <0 ) { + p =kthread_create (ksoftirqd, hcpu,"ksoftirqd/%d" , hotcpu); +if (IS_ERR (p)) {printk ("ksoftirqd for %i failed\n" , hotcpu);return NOTIFY_BAD ; } - -while (!per_cpu (ksoftirqd, hotcpu)) -yield (); +set_cpus_allowed (p,cpumask_of_cpu (hotcpu)); +kthread_start (p); +per_cpu (ksoftirqd, hotcpu) = p; }return NOTIFY_OK ; }
kernel/workqueue.c +24 -43
150 lines not on this page · raw message