Use kthread primitives
PATCH 2/2 Use kthread primitives
And this is the patch actually uses the kthread primitives, simplifying and shrinking the code a little bit.
Name: Use Kthread For Core Kernel Threads
Author: Rusty Russell
Status: Tested on 2.6.0-bk3
Depends: Hotcpu/kthread.patch.gz
D: This simply changes over the migration threads, the workqueue
D: threads and the ksoftirqd threads to use kthread. D:
D: Changes: D: - kernel/sched.c: Split migration_thread() into D: migration_kthread_init() and migration_kthread() for use with D: kthread. Simplifies startup greatly. D: - No need for migration_startup_t. D: D: - kernel/softirq.c: Split ksoftirqd() into ksoftirqd_init() and D: ksoftirqd(). D: D: - kernel/workqueue.c: Split worker_thread() into worker_thread_init() D: and worker_thread(). D: - Change waitqueue to task pointer (we need it anyway, and there's D: always only one). D: - Remove exit completion (kthread_destroy handles that for us). D: - Make create_workqueue_thread() return a task struct directly, D: since kthread_create gives us that without needing to use D: a structure for the thread to put it in.
kernel/sched.c +42 -55
@@ -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,64 +2641,54 @@ 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 * another runqueue. */ -static int migration_thread (void * data) +static int migration_kthread_init (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 ret; - - startup->task = current; -complete (&startup->startup_done); -set_current_state (TASK_UNINTERRUPTIBLE ); -schedule (); +unsigned int cpu = (long )data;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; +setscheduler (0 ,SCHED_FIFO , ¶m); +return 0 ; +} -for (;;) { -struct list_head *head; -migration_req_t *req; +static int migration_kthread (void *data) +{ +runqueue_t *rq; +struct list_head *head; +migration_req_t *req; -if (current->flags &PF_FREEZE ) -refrigerator (PF_IOTHREAD ); + rq =this_rq (); -spin_lock_irq (&rq->lock); - head = &rq->migration_queue; - current->state =TASK_INTERRUPTIBLE ; -if (list_empty (head)) { -spin_unlock_irq (&rq->lock); -schedule (); -continue ; - } +spin_lock_irq (&rq->lock); + head = &rq->migration_queue; +while (!list_empty (head)) { req =list_entry (head->next, migration_req_t, list);list_del_init (head->next); -spin_unlock_irq (&rq->lock); +spin_unlock_irq (&rq->lock);move_task_away (req->task,any_online_cpu (req->task->cpus_allowed));complete (&req->done); +spin_lock_irq (&rq->lock); + current->state =TASK_INTERRUPTIBLE ; } + current->state =TASK_INTERRUPTIBLE ; +spin_unlock_irq (&rq->lock); + +/* FIXME: Should this be in kthread.c? --RR */ +if (current->flags &PF_FREEZE ) +refrigerator (PF_IOTHREAD ); + +return 0 ; }/*
@@ -2709,35 +2700,31 @@ static int migration_call(struct notifie void *hcpu) {long cpu = (long ) hcpu; -migration_startup_t startup; +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_kthread_init, migration_kthread, + hcpu,"migration/%ld" , cpu); +if (IS_ERR (p)) +return NOTIFY_BAD ; +/* Manually bind to CPU: thread stopped, so this is OK. */ + p->thread_info->cpu = cpu; + p->cpus_allowed =cpumask_of_cpu (cpu); +if (IS_ERR (kthread_start (p))) +return NOTIFY_BAD ; +cpu_rq (cpu)->migration_thread = 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 +22 -26
79 lines not on this page · raw message
kernel/workqueue.c +53 -84
224 lines not on this page · raw message
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.