Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1244/?format=api
{ "id": 1244, "url": "http://patchwork.ozlabs.org/api/patches/1244/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20080924.004247.193721529.davem@davemloft.net/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20080924.004247.193721529.davem@davemloft.net>", "list_archive_url": null, "date": "2008-09-24T07:42:47", "name": "[0/2] : Remote softirq invocation infrastructure.", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": true, "hash": "a4ff8843110c439fc2dda5d892d645e1f3ea4cf2", "submitter": { "id": 15, "url": "http://patchwork.ozlabs.org/api/people/15/?format=api", "name": "David Miller", "email": "davem@davemloft.net" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20080924.004247.193721529.davem@davemloft.net/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/1244/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1244/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.176.167])\n\tby ozlabs.org (Postfix) with ESMTP id BB4C6DDF5C\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 24 Sep 2008 17:43:07 +1000 (EST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751834AbYIXHnB (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tWed, 24 Sep 2008 03:43:01 -0400", "(majordomo@vger.kernel.org) by vger.kernel.org id S1751940AbYIXHnB\n\t(ORCPT <rfc822; netdev-outgoing>); Wed, 24 Sep 2008 03:43:01 -0400", "from 74-93-104-97-Washington.hfc.comcastbusiness.net\n\t([74.93.104.97]:33976\n\t\"EHLO sunset.davemloft.net\" rhost-flags-OK-FAIL-OK-OK)\n\tby vger.kernel.org with ESMTP id S1751834AbYIXHm7 (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Wed, 24 Sep 2008 03:42:59 -0400", "from localhost (localhost [127.0.0.1])\n\tby sunset.davemloft.net (Postfix) with ESMTP id ABC22C8C183;\n\tWed, 24 Sep 2008 00:42:47 -0700 (PDT)" ], "Date": "Wed, 24 Sep 2008 00:42:47 -0700 (PDT)", "Message-Id": "<20080924.004247.193721529.davem@davemloft.net>", "To": "linux-kernel@vger.kernel.org", "Cc": "netdev@vger.kernel.org, jens.axboe@oracle.com,\n\tsteffen.klassert@secunet.com", "Subject": "Re: [PATCH 0/2]: Remote softirq invocation infrastructure.", "From": "David Miller <davem@davemloft.net>", "In-Reply-To": "<20080919.234824.223177211.davem@davemloft.net>", "References": "<20080919.234824.223177211.davem@davemloft.net>", "X-Mailer": "Mew version 6.1 on Emacs 22.1 / Mule 5.0 (SAKAKI)", "Mime-Version": "1.0", "Content-Type": "Text/Plain; charset=us-ascii", "Content-Transfer-Encoding": "7bit", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "From: David Miller <davem@davemloft.net>\nDate: Fri, 19 Sep 2008 23:48:24 -0700 (PDT)\n\n> Jens Axboe has written some hacks for the block layer that allow\n> queueing softirq work to remote cpus. In the context of the block\n> layer he used this facility to trigger the softirq block I/O\n> completion on the same cpu where the I/O was submitted.\n\nAs a followup to this, I've refreshed my patches and put them\nin a tree cloned from Linus's current GIT tree:\n\n\tmaster.kernel.org:/pub/scm/linux/kernel/git/davem/softirq-2.6.git\n\nI made minor touchups to the second patch, such as adding a few more\ndescriptive comments, and adding the missing export of the softirq_work\nlist array.\n\nUpdated version below for reference:\n\nsoftirq: Add support for triggering softirq work on softirqs.\n\nThis is basically a genericization of Jens Axboe's block layer\nremote softirq changes.\n\nSigned-off-by: David S. Miller <davem@davemloft.net>\nSigned-off-by: Jens Axboe <jens.axboe@oracle.com>\n---\n include/linux/interrupt.h | 21 +++++++\n include/linux/smp.h | 4 +-\n kernel/softirq.c | 129 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 153 insertions(+), 1 deletions(-)", "diff": "diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h\nindex fdd7b90..0a7a14b 100644\n--- a/include/linux/interrupt.h\n+++ b/include/linux/interrupt.h\n@@ -11,6 +11,8 @@\n #include <linux/hardirq.h>\n #include <linux/sched.h>\n #include <linux/irqflags.h>\n+#include <linux/smp.h>\n+#include <linux/percpu.h>\n #include <asm/atomic.h>\n #include <asm/ptrace.h>\n #include <asm/system.h>\n@@ -272,6 +274,25 @@ extern void softirq_init(void);\n extern void raise_softirq_irqoff(unsigned int nr);\n extern void raise_softirq(unsigned int nr);\n \n+/* This is the worklist that queues up per-cpu softirq work.\n+ *\n+ * send_remote_sendirq() adds work to these lists, and\n+ * the softirq handler itself dequeues from them. The queues\n+ * are protected by disabling local cpu interrupts and they must\n+ * only be accessed by the local cpu that they are for.\n+ */\n+DECLARE_PER_CPU(struct list_head [NR_SOFTIRQ], softirq_work_list);\n+\n+/* Try to send a softirq to a remote cpu. If this cannot be done, the\n+ * work will be queued to the local cpu.\n+ */\n+extern void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq);\n+\n+/* Like send_remote_softirq(), but the caller must disable local cpu interrupts\n+ * and compute the current cpu, passed in as 'this_cpu'.\n+ */\n+extern void __send_remote_softirq(struct call_single_data *cp, int cpu,\n+\t\t\t\t int this_cpu, int softirq);\n \n /* Tasklets --- multithreaded analogue of BHs.\n \ndiff --git a/include/linux/smp.h b/include/linux/smp.h\nindex 66484d4..2e4d58b 100644\n--- a/include/linux/smp.h\n+++ b/include/linux/smp.h\n@@ -7,6 +7,7 @@\n */\n \n #include <linux/errno.h>\n+#include <linux/types.h>\n #include <linux/list.h>\n #include <linux/cpumask.h>\n \n@@ -16,7 +17,8 @@ struct call_single_data {\n \tstruct list_head list;\n \tvoid (*func) (void *info);\n \tvoid *info;\n-\tunsigned int flags;\n+\tu16 flags;\n+\tu16 priv;\n };\n \n #ifdef CONFIG_SMP\ndiff --git a/kernel/softirq.c b/kernel/softirq.c\nindex 27642a2..77aba5e 100644\n--- a/kernel/softirq.c\n+++ b/kernel/softirq.c\n@@ -6,6 +6,8 @@\n *\tDistribute under GPLv2.\n *\n *\tRewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)\n+ *\n+ *\tRemote softirq infrastructure is by Jens Axboe.\n */\n \n #include <linux/module.h>\n@@ -463,17 +465,144 @@ void tasklet_kill(struct tasklet_struct *t)\n \n EXPORT_SYMBOL(tasklet_kill);\n \n+DEFINE_PER_CPU(struct list_head [NR_SOFTIRQ], softirq_work_list);\n+EXPORT_PER_CPU_SYMBOL(softirq_work_list);\n+\n+static void __local_trigger(struct call_single_data *cp, int softirq)\n+{\n+\tstruct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);\n+\n+\tlist_add_tail(&cp->list, head);\n+\n+\t/* Trigger the softirq only if the list was previously empty. */\n+\tif (head->next == &cp->list)\n+\t\traise_softirq_irqoff(softirq);\n+}\n+\n+#ifdef CONFIG_USE_GENERIC_SMP_HELPERS\n+static void remote_softirq_receive(void *data)\n+{\n+\tstruct call_single_data *cp = data;\n+\tunsigned long flags;\n+\tint softirq;\n+\n+\tsoftirq = cp->priv;\n+\n+\tlocal_irq_save(flags);\n+\t__local_trigger(cp, softirq);\n+\tlocal_irq_restore(flags);\n+}\n+\n+static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)\n+{\n+\tif (cpu_online(cpu)) {\n+\t\tcp->func = remote_softirq_receive;\n+\t\tcp->info = cp;\n+\t\tcp->flags = 0;\n+\t\tcp->priv = softirq;\n+\n+\t\t__smp_call_function_single(cpu, cp);\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+#else /* CONFIG_USE_GENERIC_SMP_HELPERS */\n+static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)\n+{\n+\treturn 1;\n+}\n+#endif\n+\n+/**\n+ * __send_remote_softirq - try to schedule softirq work on a remote cpu\n+ * @cp: private SMP call function data area\n+ * @cpu: the remote cpu\n+ * @this_cpu: the currently executing cpu\n+ * @softirq: the softirq for the work\n+ *\n+ * Attempt to schedule softirq work on a remote cpu. If this cannot be\n+ * done, the work is instead queued up on the local cpu.\n+ *\n+ * Interrupts must be disabled.\n+ */\n+void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)\n+{\n+\tif (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))\n+\t\t__local_trigger(cp, softirq);\n+}\n+EXPORT_SYMBOL(__send_remote_softirq);\n+\n+/**\n+ * send_remote_softirq - try to schedule softirq work on a remote cpu\n+ * @cp: private SMP call function data area\n+ * @cpu: the remote cpu\n+ * @softirq: the softirq for the work\n+ *\n+ * Like __send_remote_softirq except that disabling interrupts and\n+ * computing the current cpu is done for the caller.\n+ */\n+void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)\n+{\n+\tunsigned long flags;\n+\tint this_cpu;\n+\n+\tlocal_irq_save(flags);\n+\tthis_cpu = smp_processor_id();\n+\t__send_remote_softirq(cp, cpu, this_cpu, softirq);\n+\tlocal_irq_restore(flags);\n+}\n+EXPORT_SYMBOL(send_remote_softirq);\n+\n+static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self,\n+\t\t\t\t\t unsigned long action, void *hcpu)\n+{\n+\t/*\n+\t * If a CPU goes away, splice its entries to the current CPU\n+\t * and trigger a run of the softirq\n+\t */\n+\tif (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {\n+\t\tint cpu = (unsigned long) hcpu;\n+\t\tint i;\n+\n+\t\tlocal_irq_disable();\n+\t\tfor (i = 0; i < NR_SOFTIRQ; i++) {\n+\t\t\tstruct list_head *head = &per_cpu(softirq_work_list[i], cpu);\n+\t\t\tstruct list_head *local_head;\n+\n+\t\t\tif (list_empty(head))\n+\t\t\t\tcontinue;\n+\n+\t\t\tlocal_head = &__get_cpu_var(softirq_work_list[i]);\n+\t\t\tlist_splice_init(head, local_head);\n+\t\t\traise_softirq_irqoff(i);\n+\t\t}\n+\t\tlocal_irq_enable();\n+\t}\n+\n+\treturn NOTIFY_OK;\n+}\n+\n+static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = {\n+\t.notifier_call\t= remote_softirq_cpu_notify,\n+};\n+\n void __init softirq_init(void)\n {\n \tint cpu;\n \n \tfor_each_possible_cpu(cpu) {\n+\t\tint i;\n+\n \t\tper_cpu(tasklet_vec, cpu).tail =\n \t\t\t&per_cpu(tasklet_vec, cpu).head;\n \t\tper_cpu(tasklet_hi_vec, cpu).tail =\n \t\t\t&per_cpu(tasklet_hi_vec, cpu).head;\n+\t\tfor (i = 0; i < NR_SOFTIRQ; i++)\n+\t\t\tINIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));\n \t}\n \n+\tregister_hotcpu_notifier(&remote_softirq_cpu_notifier);\n+\n \topen_softirq(TASKLET_SOFTIRQ, tasklet_action);\n \topen_softirq(HI_SOFTIRQ, tasklet_hi_action);\n }\n", "prefixes": [ "0/2" ] }