mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 22:21:21 +00:00
smp: Optimize flush_smp_call_function_queue()
The call_single_queue can contain (two) different callbacks, synchronous and asynchronous. The current interrupt handler runs them in-order, which means that remote CPUs that are waiting for their synchronous call can be delayed by running asynchronous callbacks. Rework the interrupt handler to first run the synchonous callbacks. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20200526161907.836818381@infradead.org
This commit is contained in:
parent
19a1f5ec69
commit
52103be07d
1 changed files with 23 additions and 4 deletions
27
kernel/smp.c
27
kernel/smp.c
|
@ -209,9 +209,9 @@ void generic_smp_call_function_single_interrupt(void)
|
||||||
*/
|
*/
|
||||||
static void flush_smp_call_function_queue(bool warn_cpu_offline)
|
static void flush_smp_call_function_queue(bool warn_cpu_offline)
|
||||||
{
|
{
|
||||||
struct llist_head *head;
|
|
||||||
struct llist_node *entry;
|
|
||||||
call_single_data_t *csd, *csd_next;
|
call_single_data_t *csd, *csd_next;
|
||||||
|
struct llist_node *entry, *prev;
|
||||||
|
struct llist_head *head;
|
||||||
static bool warned;
|
static bool warned;
|
||||||
|
|
||||||
lockdep_assert_irqs_disabled();
|
lockdep_assert_irqs_disabled();
|
||||||
|
@ -235,20 +235,39 @@ static void flush_smp_call_function_queue(bool warn_cpu_offline)
|
||||||
csd->func);
|
csd->func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First; run all SYNC callbacks, people are waiting for us.
|
||||||
|
*/
|
||||||
|
prev = NULL;
|
||||||
llist_for_each_entry_safe(csd, csd_next, entry, llist) {
|
llist_for_each_entry_safe(csd, csd_next, entry, llist) {
|
||||||
smp_call_func_t func = csd->func;
|
smp_call_func_t func = csd->func;
|
||||||
void *info = csd->info;
|
void *info = csd->info;
|
||||||
|
|
||||||
/* Do we wait until *after* callback? */
|
/* Do we wait until *after* callback? */
|
||||||
if (csd->flags & CSD_FLAG_SYNCHRONOUS) {
|
if (csd->flags & CSD_FLAG_SYNCHRONOUS) {
|
||||||
|
if (prev) {
|
||||||
|
prev->next = &csd_next->llist;
|
||||||
|
} else {
|
||||||
|
entry = &csd_next->llist;
|
||||||
|
}
|
||||||
func(info);
|
func(info);
|
||||||
csd_unlock(csd);
|
csd_unlock(csd);
|
||||||
} else {
|
} else {
|
||||||
csd_unlock(csd);
|
prev = &csd->llist;
|
||||||
func(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Second; run all !SYNC callbacks.
|
||||||
|
*/
|
||||||
|
llist_for_each_entry_safe(csd, csd_next, entry, llist) {
|
||||||
|
smp_call_func_t func = csd->func;
|
||||||
|
void *info = csd->info;
|
||||||
|
|
||||||
|
csd_unlock(csd);
|
||||||
|
func(info);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle irq works queued remotely by irq_work_queue_on().
|
* Handle irq works queued remotely by irq_work_queue_on().
|
||||||
* Smp functions above are typically synchronous so they
|
* Smp functions above are typically synchronous so they
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue