Hi.

I finally found some time to finish this off. I don't really like the
end result - the macros looked clearer to me - but here goes. If it
looks okay, I'll seek sign offs from each of the affected driver
maintainers and from Ingo. Anyone else?

Regards,

Nigel

 drivers/acpi/osl.c          |    2 
 drivers/block/ll_rw_blk.c   |    2 
 drivers/char/hvc_console.c  |    2 
 drivers/char/hvcs.c         |    2 
 drivers/input/serio/serio.c |    2 
 drivers/md/dm-crypt.c       |    2 
 drivers/scsi/hosts.c        |    2 
 drivers/usb/net/pegasus.c   |    2 
 include/linux/kthread.h     |   27 ++++++++----
 include/linux/workqueue.h   |    9 ++--
 kernel/kthread.c            |   94 ++++++++++++++++++++++++++++++++++++++++----
 kernel/sched.c              |    1 
 kernel/softirq.c            |    3 -
 kernel/workqueue.c          |   36 +++++++++++-----
 14 files changed, 144 insertions(+), 42 deletions(-)
diff -ruNp 400-workthreads.patch-old/drivers/acpi/osl.c 
400-workthreads.patch-new/drivers/acpi/osl.c
--- 400-workthreads.patch-old/drivers/acpi/osl.c        2005-08-02 
22:30:57.000000000 +1000
+++ 400-workthreads.patch-new/drivers/acpi/osl.c        2005-08-02 
22:33:49.000000000 +1000
@@ -98,7 +98,7 @@ acpi_os_initialize1(void)
                return AE_NULL_ENTRY;
        }
 #endif
-       kacpid_wq = create_singlethread_workqueue("kacpid");
+       kacpid_wq = create_nofreeze_singlethread_workqueue("kacpid");
        BUG_ON(!kacpid_wq);
 
        return AE_OK;
diff -ruNp 400-workthreads.patch-old/drivers/block/ll_rw_blk.c 
400-workthreads.patch-new/drivers/block/ll_rw_blk.c
--- 400-workthreads.patch-old/drivers/block/ll_rw_blk.c 2005-08-02 
22:30:57.000000000 +1000
+++ 400-workthreads.patch-new/drivers/block/ll_rw_blk.c 2005-08-02 
22:33:49.000000000 +1000
@@ -3215,7 +3215,7 @@ EXPORT_SYMBOL(kblockd_flush);
 
 int __init blk_dev_init(void)
 {
-       kblockd_workqueue = create_workqueue("kblockd");
+       kblockd_workqueue = create_nofreeze_workqueue("kblockd");
        if (!kblockd_workqueue)
                panic("Failed to create kblockd\n");
 
diff -ruNp 400-workthreads.patch-old/drivers/char/hvc_console.c 
400-workthreads.patch-new/drivers/char/hvc_console.c
--- 400-workthreads.patch-old/drivers/char/hvc_console.c        2005-08-02 
22:30:58.000000000 +1000
+++ 400-workthreads.patch-new/drivers/char/hvc_console.c        2005-08-02 
22:33:49.000000000 +1000
@@ -844,7 +844,7 @@ int __init hvc_init(void)
 
        /* Always start the kthread because there can be hotplug vty adapters
         * added later. */
-       hvc_task = kthread_run(khvcd, NULL, "khvcd");
+       hvc_task = kthread_nofreeze_run(khvcd, NULL, "khvcd");
        if (IS_ERR(hvc_task)) {
                panic("Couldn't create kthread for console.\n");
                put_tty_driver(hvc_driver);
diff -ruNp 400-workthreads.patch-old/drivers/char/hvcs.c 
400-workthreads.patch-new/drivers/char/hvcs.c
--- 400-workthreads.patch-old/drivers/char/hvcs.c       2005-08-02 
22:30:58.000000000 +1000
+++ 400-workthreads.patch-new/drivers/char/hvcs.c       2005-08-02 
22:33:49.000000000 +1000
@@ -1403,7 +1403,7 @@ static int __init hvcs_module_init(void)
                return -ENOMEM;
        }
 
-       hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
+       hvcs_task = kthread_nofreeze_run(khvcsd, NULL, "khvcsd");
        if (IS_ERR(hvcs_task)) {
                printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not 
loaded.\n");
                kfree(hvcs_pi_buff);
diff -ruNp 400-workthreads.patch-old/drivers/input/serio/serio.c 
400-workthreads.patch-new/drivers/input/serio/serio.c
--- 400-workthreads.patch-old/drivers/input/serio/serio.c       2005-08-04 
11:48:01.000000000 +1000
+++ 400-workthreads.patch-new/drivers/input/serio/serio.c       2005-08-02 
22:33:49.000000000 +1000
@@ -899,7 +899,7 @@ irqreturn_t serio_interrupt(struct serio
 
 static int __init serio_init(void)
 {
-       serio_task = kthread_run(serio_thread, NULL, "kseriod");
+       serio_task = kthread_nofreeze_run(serio_thread, NULL, "kseriod");
        if (IS_ERR(serio_task)) {
                printk(KERN_ERR "serio: Failed to start kseriod\n");
                return PTR_ERR(serio_task);
diff -ruNp 400-workthreads.patch-old/drivers/md/dm-crypt.c 
400-workthreads.patch-new/drivers/md/dm-crypt.c
--- 400-workthreads.patch-old/drivers/md/dm-crypt.c     2005-08-02 
22:31:02.000000000 +1000
+++ 400-workthreads.patch-new/drivers/md/dm-crypt.c     2005-08-02 
22:33:49.000000000 +1000
@@ -926,7 +926,7 @@ static int __init dm_crypt_init(void)
        if (!_crypt_io_pool)
                return -ENOMEM;
 
-       _kcryptd_workqueue = create_workqueue("kcryptd");
+       _kcryptd_workqueue = create_nofreeze_workqueue("kcryptd");
        if (!_kcryptd_workqueue) {
                r = -ENOMEM;
                DMERR(PFX "couldn't create kcryptd");
diff -ruNp 400-workthreads.patch-old/drivers/scsi/hosts.c 
400-workthreads.patch-new/drivers/scsi/hosts.c
--- 400-workthreads.patch-old/drivers/scsi/hosts.c      2005-08-02 
22:31:10.000000000 +1000
+++ 400-workthreads.patch-new/drivers/scsi/hosts.c      2005-08-02 
22:33:49.000000000 +1000
@@ -132,7 +132,7 @@ int scsi_add_host(struct Scsi_Host *shos
        if (shost->transportt->create_work_queue) {
                snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
                        shost->host_no);
-               shost->work_q = create_singlethread_workqueue(
+               shost->work_q = create_nofreeze_singlethread_workqueue(
                                        shost->work_q_name);
                if (!shost->work_q)
                        goto out_free_shost_data;
diff -ruNp 400-workthreads.patch-old/drivers/usb/net/pegasus.c 
400-workthreads.patch-new/drivers/usb/net/pegasus.c
--- 400-workthreads.patch-old/drivers/usb/net/pegasus.c 2005-08-02 
22:31:15.000000000 +1000
+++ 400-workthreads.patch-new/drivers/usb/net/pegasus.c 2005-08-02 
22:33:49.000000000 +1000
@@ -1411,7 +1411,7 @@ static struct usb_driver pegasus_driver 
 static int __init pegasus_init(void)
 {
        pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
-       pegasus_workqueue = create_singlethread_workqueue("pegasus");
+       pegasus_workqueue = create_nofreeze_singlethread_workqueue("pegasus");
        if (!pegasus_workqueue)
                return -ENOMEM;
        return usb_register(&pegasus_driver);
diff -ruNp 400-workthreads.patch-old/include/linux/kthread.h 
400-workthreads.patch-new/include/linux/kthread.h
--- 400-workthreads.patch-old/include/linux/kthread.h   2004-11-03 
21:51:12.000000000 +1100
+++ 400-workthreads.patch-new/include/linux/kthread.h   2005-08-03 
11:52:01.000000000 +1000
@@ -23,10 +23,20 @@
  *
  * Returns a task_struct or ERR_PTR(-ENOMEM).
  */
+struct task_struct *__kthread_create(int (*threadfn)(void *data),
+                                  void *data,
+                                  unsigned long freezer_flags,
+                                  const char namefmt[],
+                                  va_list * args);
+
 struct task_struct *kthread_create(int (*threadfn)(void *data),
                                   void *data,
                                   const char namefmt[], ...);
 
+struct task_struct *kthread_nofreeze_create(int (*threadfn)(void *data),
+                                  void *data,
+                                  const char namefmt[], ...);
+
 /**
  * kthread_run: create and wake a thread.
  * @threadfn: the function to run until signal_pending(current).
@@ -35,14 +45,15 @@ struct task_struct *kthread_create(int (
  *
  * Description: Convenient wrapper for kthread_create() followed by
  * wake_up_process().  Returns the kthread, or ERR_PTR(-ENOMEM). */
-#define kthread_run(threadfn, data, namefmt, ...)                         \
-({                                                                        \
-       struct task_struct *__k                                            \
-               = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
-       if (!IS_ERR(__k))                                                  \
-               wake_up_process(__k);                                      \
-       __k;                                                               \
-})
+
+extern struct task_struct * kthread_run(int (*threadfn)(void *data),
+                                       void *data,
+                                       const char namefmt[], ...);
+
+extern struct task_struct * kthread_nofreeze_run(int (*threadfn)(void *data),
+                                       void *data,
+                                       const char namefmt[], ...);
+
 
 /**
  * kthread_bind: bind a just-created kthread to a cpu.
diff -ruNp 400-workthreads.patch-old/include/linux/workqueue.h 
400-workthreads.patch-new/include/linux/workqueue.h
--- 400-workthreads.patch-old/include/linux/workqueue.h 2005-06-20 
11:47:30.000000000 +1000
+++ 400-workthreads.patch-new/include/linux/workqueue.h 2005-08-03 
11:49:34.000000000 +1000
@@ -51,9 +51,12 @@ struct work_struct {
        } while (0)
 
 extern struct workqueue_struct *__create_workqueue(const char *name,
-                                                   int singlethread);
-#define create_workqueue(name) __create_workqueue((name), 0)
-#define create_singlethread_workqueue(name) __create_workqueue((name), 1)
+                                                   int singlethread,
+                                                   unsigned long freezer_flag);
+#define create_workqueue(name) __create_workqueue((name), 0, 0)
+#define create_nofreeze_workqueue(name) __create_workqueue((name), 0, 
PF_NOFREEZE)
+#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
+#define create_nofreeze_singlethread_workqueue(name) 
__create_workqueue((name), 1, PF_NOFREEZE)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
diff -ruNp 400-workthreads.patch-old/kernel/kthread.c 
400-workthreads.patch-new/kernel/kthread.c
--- 400-workthreads.patch-old/kernel/kthread.c  2005-06-20 11:47:31.000000000 
+1000
+++ 400-workthreads.patch-new/kernel/kthread.c  2005-08-04 09:46:43.000000000 
+1000
@@ -25,6 +25,7 @@ struct kthread_create_info
        /* Information passed to kthread() from keventd. */
        int (*threadfn)(void *data);
        void *data;
+       unsigned long freezer_flags;
        struct completion started;
 
        /* Result passed back to kthread_create() from keventd. */
@@ -86,6 +87,10 @@ static int kthread(void *_create)
        /* By default we can run anywhere, unlike keventd. */
        set_cpus_allowed(current, CPU_MASK_ALL);
 
+       /* Set our freezer flags */
+       current->flags &= ~PF_NOFREEZE;
+       current->flags |= (create->freezer_flags & PF_NOFREEZE);
+
        /* OK, tell user we're spawned, wait for stop or wakeup */
        __set_current_state(TASK_INTERRUPTIBLE);
        complete(&create->started);
@@ -119,16 +124,18 @@ static void keventd_create_kthread(void 
        complete(&create->done);
 }
 
-struct task_struct *kthread_create(int (*threadfn)(void *data),
+struct task_struct *__kthread_create(int (*threadfn)(void *data),
                                   void *data,
+                                  unsigned long freezer_flags,
                                   const char namefmt[],
-                                  ...)
+                                  va_list * args)
 {
        struct kthread_create_info create;
        DECLARE_WORK(work, keventd_create_kthread, &create);
 
        create.threadfn = threadfn;
        create.data = data;
+       create.freezer_flags = freezer_flags;
        init_completion(&create.started);
        init_completion(&create.done);
 
@@ -141,18 +148,89 @@ struct task_struct *kthread_create(int (
                queue_work(helper_wq, &work);
                wait_for_completion(&create.done);
        }
-       if (!IS_ERR(create.result)) {
-               va_list args;
-               va_start(args, namefmt);
+       if (!IS_ERR(create.result))
                vsnprintf(create.result->comm, sizeof(create.result->comm),
-                         namefmt, args);
-               va_end(args);
-       }
+                         namefmt, *args);
 
        return create.result;
 }
+
+struct task_struct *kthread_create(int (*threadfn)(void *data),
+                                  void *data,
+                                  const char namefmt[], ...)
+{
+       struct task_struct * result;
+
+       va_list args;
+       va_start(args, namefmt);
+       result = __kthread_create(threadfn, data, 0, namefmt, &args);
+       va_end(args);
+       return result;
+}
+
 EXPORT_SYMBOL(kthread_create);
 
+struct task_struct *kthread_nofreeze_create(int (*threadfn)(void *data),
+                                  void *data,
+                                  const char namefmt[], ...)
+{
+       struct task_struct * result;
+
+       va_list args;
+       va_start(args, namefmt);
+       result = __kthread_create(threadfn, data, PF_NOFREEZE, namefmt, &args);
+       va_end(args);
+       return result;
+}
+
+EXPORT_SYMBOL(kthread_nofreeze_create);
+
+/**
+ * kthread_run: create and wake a thread.
+ * @threadfn: the function to run until signal_pending(current).
+ * @data: data ptr for @threadfn.
+ * @namefmt: printf-style name for the thread.
+ *
+ * Description: Convenient wrapper for kthread_create() followed by
+ * wake_up_process().  Returns the kthread, or ERR_PTR(-ENOMEM).
+ **/
+struct task_struct * kthread_run(int (*threadfn)(void *data),
+               void *data,
+               const char namefmt[], ...)
+{
+       struct task_struct *__k;
+       va_list args;
+
+       va_start(args, namefmt);
+       __k = __kthread_create(threadfn, data, 0, namefmt, &args);
+       va_end(args);
+
+       if(!IS_ERR(__k))
+               wake_up_process(__k);
+
+       return __k;
+}
+
+EXPORT_SYMBOL(kthread_run);
+
+struct task_struct * kthread_nofreeze_run(int (*threadfn)(void *data),
+               void *data,
+               const char namefmt[], ...)
+{
+       struct task_struct *__k;
+       va_list args;
+
+       va_start(args, namefmt);
+       __k = __kthread_create(threadfn, data, PF_NOFREEZE, namefmt, &args);
+       va_end(args);
+
+       if(!IS_ERR(__k))
+               wake_up_process(__k);
+
+       return __k;
+}
+EXPORT_SYMBOL(kthread_nofreeze_run);
+
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
        BUG_ON(k->state != TASK_INTERRUPTIBLE);
diff -ruNp 400-workthreads.patch-old/kernel/sched.c 
400-workthreads.patch-new/kernel/sched.c
--- 400-workthreads.patch-old/kernel/sched.c    2005-08-04 11:48:00.000000000 
+1000
+++ 400-workthreads.patch-new/kernel/sched.c    2005-08-04 11:48:19.000000000 
+1000
@@ -4585,7 +4585,6 @@ static int migration_call(struct notifie
                p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
                if (IS_ERR(p))
                        return NOTIFY_BAD;
-               p->flags |= PF_NOFREEZE;
                kthread_bind(p, cpu);
                /* Must be high prio: stop_machine expects to yield to it. */
                rq = task_rq_lock(p, &flags);
diff -ruNp 400-workthreads.patch-old/kernel/softirq.c 
400-workthreads.patch-new/kernel/softirq.c
--- 400-workthreads.patch-old/kernel/softirq.c  2005-06-20 11:47:32.000000000 
+1000
+++ 400-workthreads.patch-new/kernel/softirq.c  2005-08-02 22:33:49.000000000 
+1000
@@ -350,7 +350,6 @@ void __init softirq_init(void)
 static int ksoftirqd(void * __bind_cpu)
 {
        set_user_nice(current, 19);
-       current->flags |= PF_NOFREEZE;
 
        set_current_state(TASK_INTERRUPTIBLE);
 
@@ -456,7 +455,7 @@ static int __devinit cpu_callback(struct
        case CPU_UP_PREPARE:
                BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
                BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
-               p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
+               p = kthread_nofreeze_create(ksoftirqd, hcpu, "ksoftirqd/%d", 
hotcpu);
                if (IS_ERR(p)) {
                        printk("ksoftirqd for %i failed\n", hotcpu);
                        return NOTIFY_BAD;
diff -ruNp 400-workthreads.patch-old/kernel/workqueue.c 
400-workthreads.patch-new/kernel/workqueue.c
--- 400-workthreads.patch-old/kernel/workqueue.c        2005-06-20 
11:47:32.000000000 +1000
+++ 400-workthreads.patch-new/kernel/workqueue.c        2005-08-03 
11:57:01.000000000 +1000
@@ -186,8 +186,6 @@ static int worker_thread(void *__cwq)
        struct k_sigaction sa;
        sigset_t blocked;
 
-       current->flags |= PF_NOFREEZE;
-
        set_user_nice(current, -5);
 
        /* Block and flush all signals */
@@ -208,6 +206,7 @@ static int worker_thread(void *__cwq)
                        schedule();
                else
                        __set_current_state(TASK_RUNNING);
+               try_to_freeze();
                remove_wait_queue(&cwq->more_work, &wait);
 
                if (!list_empty(&cwq->worklist))
@@ -277,7 +276,8 @@ void fastcall flush_workqueue(struct wor
 }
 
 static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
-                                                  int cpu)
+                                                  int cpu,
+                                                  unsigned long freezer_flags)
 {
        struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
        struct task_struct *p;
@@ -291,10 +291,21 @@ static struct task_struct *create_workqu
        init_waitqueue_head(&cwq->more_work);
        init_waitqueue_head(&cwq->work_done);
 
-       if (is_single_threaded(wq))
-               p = kthread_create(worker_thread, cwq, "%s", wq->name);
-       else
-               p = kthread_create(worker_thread, cwq, "%s/%d", wq->name, cpu);
+       if (is_single_threaded(wq)) {
+               if (freezer_flags)
+                       p = kthread_nofreeze_create(worker_thread, cwq,
+                                       "%s", wq->name);
+               else
+                       p = kthread_create(worker_thread, cwq,
+                                       "%s", wq->name);
+       } else {
+               if (freezer_flags)
+                       p = kthread_nofreeze_create(worker_thread, cwq,
+                                       "%s/%d", wq->name, cpu);
+               else
+                       p = kthread_create(worker_thread, cwq,
+                                       "%s/%d", wq->name, cpu);
+       }
        if (IS_ERR(p))
                return NULL;
        cwq->thread = p;
@@ -302,7 +313,8 @@ static struct task_struct *create_workqu
 }
 
 struct workqueue_struct *__create_workqueue(const char *name,
-                                           int singlethread)
+                                           int singlethread,
+                                           unsigned long freezer_flags)
 {
        int cpu, destroy = 0;
        struct workqueue_struct *wq;
@@ -320,7 +332,7 @@ struct workqueue_struct *__create_workqu
        lock_cpu_hotplug();
        if (singlethread) {
                INIT_LIST_HEAD(&wq->list);
-               p = create_workqueue_thread(wq, 0);
+               p = create_workqueue_thread(wq, 0, freezer_flags);
                if (!p)
                        destroy = 1;
                else
@@ -330,7 +342,7 @@ struct workqueue_struct *__create_workqu
                list_add(&wq->list, &workqueues);
                spin_unlock(&workqueue_lock);
                for_each_online_cpu(cpu) {
-                       p = create_workqueue_thread(wq, cpu);
+                       p = create_workqueue_thread(wq, cpu, freezer_flags);
                        if (p) {
                                kthread_bind(p, cpu);
                                wake_up_process(p);
@@ -501,7 +513,7 @@ static int __devinit workqueue_cpu_callb
        case CPU_UP_PREPARE:
                /* Create a new workqueue thread for it. */
                list_for_each_entry(wq, &workqueues, list) {
-                       if (create_workqueue_thread(wq, hotcpu) < 0) {
+                       if (create_workqueue_thread(wq, hotcpu, 0) < 0) {
                                printk("workqueue for %i failed\n", hotcpu);
                                return NOTIFY_BAD;
                        }
@@ -540,7 +552,7 @@ static int __devinit workqueue_cpu_callb
 void init_workqueues(void)
 {
        hotcpu_notifier(workqueue_cpu_callback, 0);
-       keventd_wq = create_workqueue("events");
+       keventd_wq = create_nofreeze_workqueue("events");
        BUG_ON(!keventd_wq);
 }
 

-- 
Evolution.
Enumerate the requirements.
Consider the interdependencies.
Calculate the probabilities.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to