From: Jan Kara <jack@suse.cz>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: pmladek@suse.cz, Steven Rostedt <rostedt@goodmis.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
LKML <linux-kernel@vger.kernel.org>,
Christoph Hellwig <hch@lst.de>, Jan Kara <jack@suse.cz>
Subject: [PATCH 3/9] kernel: use lockless list for smp_call_function_single()
Date: Mon, 23 Dec 2013 21:39:24 +0100 [thread overview]
Message-ID: <1387831171-5264-4-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1387831171-5264-1-git-send-email-jack@suse.cz>
From: Christoph Hellwig <hch@lst.de>
Make smp_call_function_single and friends more efficient by using
a lockless list.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
---
include/linux/elevator.h | 2 +-
include/linux/smp.h | 3 ++-
kernel/smp.c | 51 ++++++++++--------------------------------------
3 files changed, 13 insertions(+), 43 deletions(-)
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 0bdfd46f4735..06860e2a25c3 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -205,7 +205,7 @@ enum {
#define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist)
#define rq_fifo_clear(rq) do { \
list_del_init(&(rq)->queuelist); \
- INIT_LIST_HEAD(&(rq)->csd.list); \
+ (rq)->csd.llist.next = NULL; \
} while (0)
#else /* CONFIG_BLOCK */
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 5da22ee42e16..9a1b8ba05924 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -11,12 +11,13 @@
#include <linux/list.h>
#include <linux/cpumask.h>
#include <linux/init.h>
+#include <linux/llist.h>
extern void cpu_idle(void);
typedef void (*smp_call_func_t)(void *info);
struct call_single_data {
- struct list_head list;
+ struct llist_node llist;
smp_call_func_t func;
void *info;
u16 flags;
diff --git a/kernel/smp.c b/kernel/smp.c
index bd9f94028838..47b415e16c24 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -28,12 +28,7 @@ struct call_function_data {
static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
-struct call_single_queue {
- struct list_head list;
- raw_spinlock_t lock;
-};
-
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_single_queue, call_single_queue);
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
static int
hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
@@ -85,12 +80,8 @@ void __init call_function_init(void)
void *cpu = (void *)(long)smp_processor_id();
int i;
- for_each_possible_cpu(i) {
- struct call_single_queue *q = &per_cpu(call_single_queue, i);
-
- raw_spin_lock_init(&q->lock);
- INIT_LIST_HEAD(&q->list);
- }
+ for_each_possible_cpu(i)
+ init_llist_head(&per_cpu(call_single_queue, i));
hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
register_cpu_notifier(&hotplug_cfd_notifier);
@@ -141,18 +132,9 @@ static void csd_unlock(struct call_single_data *csd)
*/
static void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
{
- struct call_single_queue *dst = &per_cpu(call_single_queue, cpu);
- unsigned long flags;
- int ipi;
-
if (wait)
csd->flags |= CSD_FLAG_WAIT;
- raw_spin_lock_irqsave(&dst->lock, flags);
- ipi = list_empty(&dst->list);
- list_add_tail(&csd->list, &dst->list);
- raw_spin_unlock_irqrestore(&dst->lock, flags);
-
/*
* The list addition should be visible before sending the IPI
* handler locks the list to pull the entry off it because of
@@ -164,7 +146,7 @@ static void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
* locking and barrier primitives. Generic code isn't really
* equipped to do the right thing...
*/
- if (ipi)
+ if (llist_add(&csd->llist, &per_cpu(call_single_queue, cpu)))
arch_send_call_function_single_ipi(cpu);
if (wait)
@@ -177,26 +159,19 @@ static void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
*/
void generic_smp_call_function_single_interrupt(void)
{
- struct call_single_queue *q = &__get_cpu_var(call_single_queue);
- LIST_HEAD(list);
+ struct llist_node *entry;
+ struct call_single_data *csd, *csd_next;
/*
* Shouldn't receive this interrupt on a cpu that is not yet online.
*/
WARN_ON_ONCE(!cpu_online(smp_processor_id()));
- raw_spin_lock(&q->lock);
- list_replace_init(&q->list, &list);
- raw_spin_unlock(&q->lock);
-
- while (!list_empty(&list)) {
- struct call_single_data *csd;
-
- csd = list_entry(list.next, struct call_single_data, list);
- list_del(&csd->list);
+ entry = llist_del_all(&__get_cpu_var(call_single_queue));
+ entry = llist_reverse_order(entry);
+ llist_for_each_entry_safe(csd, csd_next, entry, llist) {
csd->func(csd->info);
-
csd_unlock(csd);
}
}
@@ -411,17 +386,11 @@ void smp_call_function_many(const struct cpumask *mask,
for_each_cpu(cpu, cfd->cpumask) {
struct call_single_data *csd = per_cpu_ptr(cfd->csd, cpu);
- struct call_single_queue *dst =
- &per_cpu(call_single_queue, cpu);
- unsigned long flags;
csd_lock(csd);
csd->func = func;
csd->info = info;
-
- raw_spin_lock_irqsave(&dst->lock, flags);
- list_add_tail(&csd->list, &dst->list);
- raw_spin_unlock_irqrestore(&dst->lock, flags);
+ llist_add(&csd->llist, &per_cpu(call_single_queue, cpu));
}
/* Send a message to all CPUs in the map */
--
1.8.1.4
next prev parent reply other threads:[~2013-12-23 20:42 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-23 20:39 [PATCH 0/9] printk: Cleanups and softlockup avoidance Jan Kara
2013-12-23 20:39 ` [PATCH 1/9] block: Stop abusing csd.list for fifo_time Jan Kara
2014-02-01 16:48 ` Frederic Weisbecker
2014-02-03 14:48 ` Jan Kara
2014-02-03 17:02 ` Frederic Weisbecker
2013-12-23 20:39 ` [PATCH 2/9] block: Stop abusing rq->csd.list in blk-softirq Jan Kara
2014-01-30 12:39 ` Frederic Weisbecker
2014-01-30 15:45 ` Jan Kara
2014-01-30 17:01 ` Frederic Weisbecker
2014-01-30 22:12 ` Jan Kara
2014-01-31 15:08 ` Frederic Weisbecker
2013-12-23 20:39 ` Jan Kara [this message]
2014-01-07 16:21 ` [PATCH 3/9] kernel: use lockless list for smp_call_function_single() Frederic Weisbecker
2013-12-23 20:39 ` [PATCH 4/9] smp: Teach __smp_call_function_single() to check for offline cpus Jan Kara
2014-01-03 0:47 ` Steven Rostedt
2013-12-23 20:39 ` [PATCH 5/9] smp: Provide __smp_call_function_any() Jan Kara
2014-01-03 0:51 ` Steven Rostedt
2013-12-23 20:39 ` [PATCH 6/9] printk: Release lockbuf_lock before calling console_trylock_for_printk() Jan Kara
2014-01-03 1:53 ` Steven Rostedt
2014-01-03 7:49 ` Jan Kara
2013-12-23 20:39 ` [PATCH 7/9] printk: Enable interrupts " Jan Kara
2013-12-23 20:39 ` [PATCH 8/9] printk: Remove separate printk_sched buffers and use printk buf instead Jan Kara
2013-12-23 20:39 ` [PATCH 9/9] printk: Hand over printing to console if printing too long Jan Kara
2014-01-05 7:57 ` Andrew Morton
2014-01-06 9:46 ` Jan Kara
2014-01-13 7:28 ` Jan Kara
2014-01-15 22:23 ` Andrew Morton
2014-01-16 15:52 ` Jan Kara
2013-12-23 20:39 ` [PATCH 10/10] printk: debug: Slow down printing to 9600 bauds Jan Kara
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=1387831171-5264-4-git-send-email-jack@suse.cz \
--to=jack@suse.cz \
--cc=akpm@linux-foundation.org \
--cc=fweisbec@gmail.com \
--cc=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=pmladek@suse.cz \
--cc=rostedt@goodmis.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®