From: Daniel Walker <dwalker@mvista.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Ingo Molnar <mingo@elte.hu>,
Andrew Morton <akpm@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Christoph Hellwig <hch@infradead.org>,
john stultz <johnstul@us.ibm.com>,
Oleg Nesterov <oleg@tv-sign.ru>,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
Dipankar Sarma <dipankar@in.ibm.com>,
"David S. Miller" <davem@davemloft.net>,
matthew.wilcox@hp.com, kuznet@ms2.inr.ac.ru
Subject: Re: [RFC PATCH 6/6] Convert tasklets to work queues
Date: Fri, 22 Jun 2007 00:06:48 -0700 [thread overview]
Message-ID: <1182496008.3228.25.camel@dhcp193.mvista.com> (raw)
In-Reply-To: <20070622040137.414439610@goodmis.org>
On Fri, 2007-06-22 at 00:00 -0400, Steven Rostedt wrote:
> plain text document attachment (tasklets-to-workqueues.patch)
> This patch creates an alternative for drivers from using tasklets.
> It creates a "work_tasklet". When configured to use work_tasklets
> instead of tasklets, instead of creating tasklets, a work queue
> is made in its place. The API is still the same, and the drivers
> don't know that a work queue is being used.
>
> This is (for now) a proof of concept approach to using work queues
> instead of tasklets. More can be done. For one thing, we could make
> individual work queues for each tasklet instead of using the global
> ktasklet_wq. But for now it's just easier to do this.
>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
>
>
> Index: linux-2.6-test/kernel/Kconfig.preempt
> ===================================================================
> --- linux-2.6-test.orig/kernel/Kconfig.preempt
> +++ linux-2.6-test/kernel/Kconfig.preempt
> @@ -63,3 +63,18 @@ config PREEMPT_BKL
> Say Y here if you are building a kernel for a desktop system.
> Say N if you are unsure.
>
> +config TASKLETS_AS_WORKQUEUES
> + bool "Treat tasklets as workqueues (EXPERIMENTAL)"
> + depends on EXPERIMENTAL
> + help
> + Tasklets are an old solution to an old problem with respect
> + to SMP. But today they are not necessary anymore.
> + There are better solutions to the problem that tasklets
> + are trying to solve.
> +
> + This option converts tasklets into workqueues and
> + removes the tasklet softirq. This is a clean up until
> + we get rid of all tasklets that are currently in
> + the kernel.
> +
> + Say Y if you are unsure and brave (not very well tested code!).
> Index: linux-2.6-test/kernel/Makefile
> ===================================================================
> --- linux-2.6-test.orig/kernel/Makefile
> +++ linux-2.6-test/kernel/Makefile
> @@ -21,7 +21,11 @@ obj-$(CONFIG_FUTEX) += futex.o
> ifeq ($(CONFIG_COMPAT),y)
> obj-$(CONFIG_FUTEX) += futex_compat.o
> endif
> +ifeq ($(CONFIG_TASKLETS_AS_WORKQUEUES), y)
> +obj-y += tasklet_work.o
> +else
> obj-y += tasklet.o
> +endif
> obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
> obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
> obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
> Index: linux-2.6-test/init/main.c
> ===================================================================
> --- linux-2.6-test.orig/init/main.c
> +++ linux-2.6-test/init/main.c
> @@ -121,6 +121,11 @@ extern void time_init(void);
> /* Default late time init is NULL. archs can override this later. */
> void (*late_time_init)(void);
> extern void softirq_init(void);
> +#ifdef CONFIG_TASKLETS_AS_WORKQUEUES
> + extern void init_tasklets(void);
> +#else
> +# define init_tasklets() do { } while(0)
> +#endif
>
> /* Untouched command line saved by arch-specific code. */
> char __initdata boot_command_line[COMMAND_LINE_SIZE];
> @@ -706,6 +711,7 @@ static void __init do_basic_setup(void)
> {
> /* drivers will send hotplug events */
> init_workqueues();
> + init_tasklets();
> usermodehelper_init();
> driver_init();
> init_irq_proc();
> Index: linux-2.6-test/include/linux/tasklet.h
> ===================================================================
> --- linux-2.6-test.orig/include/linux/tasklet.h
> +++ linux-2.6-test/include/linux/tasklet.h
> @@ -1,6 +1,10 @@
> #ifndef _LINUX_TASKLET_H
> #define _LINUX_TASKLET_H
>
> -#include <linux/tasklet_softirq.h>
> +#ifdef CONFIG_TASKLETS_AS_WORKQUEUES
> +# include <linux/tasklet_work.h>
> +#else
> +# include <linux/tasklet_softirq.h>
> +#endif
>
> #endif
> Index: linux-2.6-test/include/linux/tasklet_work.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6-test/include/linux/tasklet_work.h
> @@ -0,0 +1,62 @@
> +#ifndef _LINUX_WORK_TASKLET_H
> +#define _LINUX_WORK_TASKLET_H
> +
> +#ifndef _LINUX_INTERRUPT_H
> +# error "Do not include this header directly! use linux/interrupt.h"
> +#endif
> +
> +#include <linux/workqueue.h>
> +
> +extern void work_tasklet_exec(struct work_struct *work);
> +
> +struct tasklet_struct
> +{
> + struct work_struct work;
> + struct list_head list;
> + unsigned long state;
> + atomic_t count;
> + void (*func)(unsigned long);
> + unsigned long data;
> + char *n;
> +};
> +
> +#define DECLARE_TASKLET(name, func, data) \
> + struct tasklet_struct name = { \
> + __WORK_INITIALIZER((name).work, work_tasklet_exec), \
> + LIST_HEAD_INIT((name).list), \
> + 0, \
> + ATOMIC_INIT(0), \
> + func, \
> + data, \
> + #name \
> + }
> +
> +#define DECLARE_TASKLET_DISABLED(name, func, data) \
> + struct tasklet_struct name = { \
> + __WORK_INITIALIZER((name).work, work_tasklet_exec), \
> + LIST_HEAD_INIT((name).list), \
> + 0, \
> + ATOMIC_INIT(1), \
> + func, \
> + data, \
> + #name \
> + }
> +
> +void tasklet_schedule(struct tasklet_struct *t);
> +#define tasklet_hi_schedule tasklet_schedule
> +extern fastcall void tasklet_enable(struct tasklet_struct *t);
> +#define tasklet_hi_enable tasklet_enable
> +
> +void tasklet_disable_nosync(struct tasklet_struct *t);
> +void tasklet_disable(struct tasklet_struct *t);
> +
> +extern int tasklet_is_scheduled(struct tasklet_struct *t);
> +
> +extern void tasklet_kill(struct tasklet_struct *t);
> +extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
> +extern void tasklet_init(struct tasklet_struct *t,
> + void (*func)(unsigned long), unsigned long data);
> +void takeover_tasklets(unsigned int cpu);
> +
> +
> +#endif /* _LINUX_WORK_TASKLET_H */
> Index: linux-2.6-test/kernel/tasklet_work.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6-test/kernel/tasklet_work.c
> @@ -0,0 +1,138 @@
> +/*
> + * linux/kernel/work_tasklet.c
> + *
> + * Copyright (C) 2007 Steven Rostedt, Red Hat
> + *
> + */
> +
> +#include <linux/interrupt.h>
> +
> +static struct workqueue_struct *ktaskletd_wq;
> +
> +enum
> +{
> + TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
> + TASKLET_STATE_RUN, /* Tasklet is running (SMP only) */
> + TASKLET_STATE_PENDING /* Tasklet is pending */
> +};
> +
> +#define TASKLET_STATEF_SCHED (1 << TASKLET_STATE_SCHED)
> +#define TASKLET_STATEF_RUN (1 << TASKLET_STATE_RUN)
> +#define TASKLET_STATEF_PENDING (1 << TASKLET_STATE_PENDING)
> +
> +void tasklet_schedule(struct tasklet_struct *t)
> +{
> + BUG_ON(!ktaskletd_wq);
> + pr_debug("scheduling tasklet %s %p\n", t->n, t);
I'd change these pr_debug lines to "tasklet : scheduling %s %p\n" for
readability ..
> + queue_work(ktaskletd_wq, &t->work);
> +}
> +
> +EXPORT_SYMBOL(tasklet_schedule);
> +
> +int tasklet_is_scheduled(struct tasklet_struct *t)
> +{
> + int ret;
> + ret = work_pending(&t->work);
> + pr_debug("sched %s pending=%d\n", t->n, ret);
> + return ret;
> +}
> +
> +EXPORT_SYMBOL(tasklet_is_scheduled);
> +
> +void tasklet_disable_nosync(struct tasklet_struct *t)
> +{
> + pr_debug("disable tasklet %s %p\n", t->n, t);
> + atomic_inc(&t->count);
> + smp_mb__after_atomic_inc();
> +}
> +
> +EXPORT_SYMBOL(tasklet_disable_nosync);
> +
> +void tasklet_disable(struct tasklet_struct *t)
> +{
> + tasklet_disable_nosync(t);
> + pr_debug("flush tasklet %s %p\n", t->n, t);
> + flush_workqueue(ktaskletd_wq);
> + smp_mb();
> +}
> +
> +EXPORT_SYMBOL(tasklet_disable);
> +
> +void work_tasklet_exec(struct work_struct *work)
> +{
> + struct tasklet_struct *t =
> + container_of(work, struct tasklet_struct, work);
> +
> + if (unlikely(atomic_read(&t->count))) {
> + pr_debug("tasklet disabled %s %p\n", t->n, t);
> + set_bit(TASKLET_STATE_PENDING, &t->state);
> + smp_mb();
> + /* make sure we were not just enabled */
> + if (likely(atomic_read(&t->count)))
> + goto out;
> + clear_bit(TASKLET_STATE_PENDING, &t->state);
smp_mb__before_clear_bit ?
> + }
> +
> + local_bh_disable();
> + pr_debug("run tasklet %s %p\n", t->n, t);
> + t->func(t->data);
> + local_bh_enable();
> +
> +out:
> + return;
> +}
> +
> +EXPORT_SYMBOL(work_tasklet_exec);
> +
> +void __init softirq_init(void)
> +{
> +}
ifdef's ?
> +void init_tasklets(void)
> +{
> + ktaskletd_wq = create_workqueue("tasklets");
> + BUG_ON(!ktaskletd_wq);
> +}
> +
> +void takeover_tasklets(unsigned int cpu)
> +{
> + pr_debug("Implement takeover tasklets??\n");
> +}
hmm .. Looks like it's for migration of tasklets .. I take it your not
sure that's handled ? Try cpu hotplug ..
> +void tasklet_init(struct tasklet_struct *t,
> + void (*func)(unsigned long), unsigned long data)
> +{
> + INIT_WORK(&t->work, work_tasklet_exec);
> + INIT_LIST_HEAD(&t->list);
> + t->state = 0;
> + atomic_set(&t->count, 0);
> + t->func = func;
> + t->data = data;
> + t->n = "anonymous";
Is this "anonymous" just used for debugging ? Is so you could fill it
with a kallsyms lookup with the __builtin_return_address() ..
> + pr_debug("anonymous tasklet %p set at %p\n",
> + t, __builtin_return_address(0));
> +}
> +
> +EXPORT_SYMBOL(tasklet_init);
> +
> +void fastcall tasklet_enable(struct tasklet_struct *t)
> +{
> + pr_debug("enable tasklet %s (count was %d)\n",
> + t->n, atomic_read(&t->count));
> + if (!atomic_dec_and_test(&t->count))
> + return;
> + if (test_and_clear_bit(TASKLET_STATE_PENDING, &t->state)) {
> + pr_debug("tasklet %s was pending\n", t->n);
> + tasklet_schedule(t);
> + }
> +}
> +
> +EXPORT_SYMBOL(tasklet_enable);
> +
> +void tasklet_kill(struct tasklet_struct *t)
> +{
> + pr_debug("kill tasklet %s\n", t->n);
> + flush_workqueue(ktaskletd_wq);
> +}
> +
> +EXPORT_SYMBOL(tasklet_kill);
>
next prev parent reply other threads:[~2007-06-22 7:11 UTC|newest]
Thread overview: 127+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-22 4:00 [RFC PATCH 0/6] Convert all tasklets to workqueues Steven Rostedt
2007-06-22 4:00 ` [RFC PATCH 1/6] Convert the RCU tasklet into a softirq Steven Rostedt
2007-06-22 7:10 ` Christoph Hellwig
2007-06-22 7:43 ` Ingo Molnar
2007-06-22 12:35 ` Steven Rostedt
2007-06-22 12:55 ` Ingo Molnar
2007-06-22 4:00 ` [RFC PATCH 2/6] Split out tasklets from softirq.c Steven Rostedt
2007-06-22 7:11 ` Christoph Hellwig
2007-06-22 12:40 ` Steven Rostedt
2007-06-22 13:45 ` Akinobu Mita
2007-06-22 13:58 ` Steven Rostedt
2007-06-22 4:00 ` [RFC PATCH 3/6] Add a tasklet is-scheduled API Steven Rostedt
2007-06-22 4:00 ` [RFC PATCH 4/6] Make DRM use the tasklet is-sched API Steven Rostedt
2007-06-22 6:36 ` Daniel Walker
2007-06-22 6:49 ` Thomas Gleixner
2007-06-22 7:08 ` Daniel Walker
2007-06-22 12:15 ` Steven Rostedt
2007-06-22 15:36 ` Daniel Walker
2007-06-22 22:38 ` Ingo Molnar
2007-06-22 23:28 ` Daniel Walker
2007-06-22 16:10 ` Arnd Bergmann
2007-06-22 16:56 ` Steven Rostedt
2007-06-22 18:24 ` Christoph Hellwig
2007-06-22 23:38 ` Dave Airlie
2007-06-22 4:00 ` [RFC PATCH 5/6] Move tasklet.h to tasklet_softirq.h Steven Rostedt
2007-06-22 4:00 ` [RFC PATCH 6/6] Convert tasklets to work queues Steven Rostedt
2007-06-22 7:06 ` Daniel Walker [this message]
2007-06-22 13:29 ` Steven Rostedt
2007-06-22 15:52 ` Oleg Nesterov
2007-06-22 16:35 ` Steven Rostedt
2007-06-23 11:15 ` Arnd Bergmann
2007-06-22 7:09 ` [RFC PATCH 0/6] Convert all tasklets to workqueues Christoph Hellwig
2007-06-22 7:51 ` Ingo Molnar
2007-06-22 7:53 ` Christoph Hellwig
2007-06-22 11:23 ` Ingo Molnar
2007-06-22 12:32 ` Steven Rostedt
2007-06-22 12:38 ` Ingo Molnar
2007-06-22 12:58 ` Steven Rostedt
2007-06-22 13:12 ` Ingo Molnar
2007-06-22 14:27 ` Steven Rostedt
2007-06-22 13:13 ` Andrew Morton
2007-06-22 13:26 ` Ingo Molnar
2007-06-22 13:41 ` Andrew Morton
2007-06-22 14:00 ` Ingo Molnar
2007-06-22 13:35 ` Steven Rostedt
2007-06-22 14:25 ` Arjan van de Ven
2007-06-22 14:42 ` Steven Rostedt
2007-06-22 14:43 ` Arjan van de Ven
2007-06-22 17:16 ` Linus Torvalds
2007-06-22 17:31 ` Steven Rostedt
2007-06-22 18:32 ` Christoph Hellwig
2007-06-22 20:40 ` Ingo Molnar
2007-06-22 21:00 ` Christoph Hellwig
2007-06-22 21:10 ` Ingo Molnar
2007-06-22 21:13 ` Thomas Gleixner
2007-06-22 21:37 ` Linus Torvalds
2007-06-22 21:59 ` Ingo Molnar
2007-06-22 22:09 ` Ingo Molnar
2007-06-22 22:43 ` Roland Dreier
2007-06-22 22:57 ` Alan Cox
2007-06-22 22:58 ` Steven Rostedt
2007-06-23 6:23 ` Dave Airlie
2007-06-24 15:16 ` Jonathan Corbet
2007-06-24 15:52 ` Steven Rostedt
2007-06-25 16:50 ` Tilman Schmidt
2007-06-25 17:06 ` Steven Rostedt
2007-06-25 20:50 ` Tilman Schmidt
2007-06-25 21:03 ` Steven Rostedt
2007-06-25 19:52 ` Stephen Hemminger
2007-06-26 0:00 ` Jonathan Corbet
2007-06-26 0:52 ` Steven Rostedt
2007-06-25 18:48 ` Kristian Høgsberg
2007-06-25 19:11 ` Steven Rostedt
2007-06-25 20:07 ` Kristian Høgsberg
2007-06-25 20:31 ` Steven Rostedt
2007-06-25 21:08 ` Kristian Høgsberg
2007-06-25 21:15 ` Ingo Molnar
2007-06-25 23:36 ` Stefan Richter
2007-06-26 0:46 ` Steven Rostedt
2007-06-26 1:46 ` Dan Williams
2007-06-26 2:01 ` Steven Rostedt
2007-06-26 2:12 ` Dan Williams
2007-06-28 12:37 ` Steven Rostedt
2007-06-28 16:37 ` Oleg Nesterov
2007-06-28 18:02 ` Dan Williams
2007-06-28 20:46 ` Steven Rostedt
2007-06-28 21:23 ` Dan Williams
2007-06-28 21:40 ` Dan Williams
2007-06-28 22:01 ` Steven Rostedt
2007-06-28 22:00 ` Steven Rostedt
2007-06-28 5:48 ` Jeff Garzik
2007-06-28 9:23 ` Ingo Molnar
2007-06-28 14:38 ` Alexey Kuznetsov
2007-06-28 15:23 ` Jeff Garzik
2007-06-28 15:54 ` Steven Rostedt
2007-06-28 16:00 ` Ingo Molnar
2007-06-28 17:26 ` Jeff Garzik
2007-06-28 17:44 ` Jeff Garzik
2007-06-28 18:19 ` Andrew Morton
2007-06-28 20:07 ` Ingo Molnar
2007-06-29 11:34 ` Alexey Kuznetsov
2007-06-29 11:48 ` Duncan Sands
2007-06-29 13:36 ` Alexey Kuznetsov
2007-06-29 14:01 ` Duncan Sands
2007-06-29 16:34 ` Alexey Kuznetsov
2007-06-29 12:29 ` Ingo Molnar
2007-06-29 13:25 ` Alexey Kuznetsov
2007-06-29 13:43 ` Ingo Molnar
2007-06-29 15:23 ` Alexey Kuznetsov
2007-06-29 13:41 ` Steven Rostedt
2007-06-29 14:24 ` Jeff Garzik
2007-06-29 14:26 ` Oleg Nesterov
2007-06-29 19:04 ` Alexey Kuznetsov
2007-06-29 14:27 ` Alexey Kuznetsov
2007-06-29 15:51 ` Oleg Nesterov
2007-06-29 16:21 ` Alexey Kuznetsov
2007-06-29 16:52 ` Oleg Nesterov
2007-06-29 17:09 ` Oleg Nesterov
2007-06-30 11:25 ` Oleg Nesterov
2007-06-28 15:17 ` Jeff Garzik
2007-06-22 21:53 ` Daniel Walker
2007-06-22 22:09 ` david
2007-06-22 22:15 ` Daniel Walker
2007-06-22 22:44 ` Ingo Molnar
2007-06-22 23:28 ` Daniel Walker
2007-06-22 22:15 ` Ingo Molnar
2007-06-23 5:14 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1182496008.3228.25.camel@dhcp193.mvista.com \
--to=dwalker@mvista.com \
--cc=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=dipankar@in.ibm.com \
--cc=hch@infradead.org \
--cc=johnstul@us.ibm.com \
--cc=kuznet@ms2.inr.ac.ru \
--cc=linux-kernel@vger.kernel.org \
--cc=matthew.wilcox@hp.com \
--cc=mingo@elte.hu \
--cc=oleg@tv-sign.ru \
--cc=paulmck@linux.vnet.ibm.com \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®