From: Ingo Molnar We dont want to execute off keventd since it might hold a semaphore our callers hold too. This can happen when kthread_create() is called from within keventd. This happened due to the IRQ threading patches but it could happen with other code too. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton --- 25-akpm/kernel/kthread.c | 25 +++++++++++++++++++++---- 1 files changed, 21 insertions(+), 4 deletions(-) diff -puN kernel/kthread.c~fix-keventd-execution-dependency kernel/kthread.c --- 25/kernel/kthread.c~fix-keventd-execution-dependency Tue Sep 14 17:41:41 2004 +++ 25-akpm/kernel/kthread.c Tue Sep 14 17:41:41 2004 @@ -14,6 +14,12 @@ #include #include +/* + * We dont want to execute off keventd since it might + * hold a semaphore our callers hold too: + */ +static struct workqueue_struct *helper_wq; + struct kthread_create_info { /* Information passed to kthread() from keventd. */ @@ -126,12 +132,13 @@ struct task_struct *kthread_create(int ( init_completion(&create.started); init_completion(&create.done); - /* If we're being called to start the first workqueue, we - * can't use keventd. */ - if (!keventd_up()) + /* + * The workqueue needs to start up first: + */ + if (!helper_wq) work.func(work.data); else { - schedule_work(&work); + queue_work(helper_wq, &work); wait_for_completion(&create.done); } if (!IS_ERR(create.result)) { @@ -183,3 +190,13 @@ int kthread_stop(struct task_struct *k) return ret; } EXPORT_SYMBOL(kthread_stop); + +static __init int helper_init(void) +{ + helper_wq = create_singlethread_workqueue("kthread"); + BUG_ON(!helper_wq); + + return 0; +} +core_initcall(helper_init); + _