public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: LKML <linux-kernel@vger.kernel.org>
Cc: 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: [RFC PATCH 6/6] Convert tasklets to work queues
Date: Fri, 22 Jun 2007 00:00:20 -0400	[thread overview]
Message-ID: <20070622040137.414439610@goodmis.org> (raw)
In-Reply-To: 20070622040014.234651401@goodmis.org

[-- Attachment #1: tasklets-to-workqueues.patch --]
[-- Type: text/plain, Size: 8569 bytes --]

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);
+	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);
+	}
+
+	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)
+{
+}
+
+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");
+}
+
+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";
+	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);

-- 

  parent reply	other threads:[~2007-06-22  4:04 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 ` Steven Rostedt [this message]
2007-06-22  7:06   ` [RFC PATCH 6/6] Convert tasklets to work queues Daniel Walker
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=20070622040137.414439610@goodmis.org \
    --to=rostedt@goodmis.org \
    --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=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