irq_work, smp: Allow irq_work on call_single_queue
Currently irq_work_queue_on() will issue an unconditional arch_send_call_function_single_ipi() and has the handler do irq_work_run(). This is unfortunate in that it makes the IPI handler look at a second cacheline and it misses the opportunity to avoid the IPI. Instead note that struct irq_work and struct __call_single_data are very similar in layout, so use a few bits in the flags word to encode a type and stick the irq_work on the call_single_queue list. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20200526161908.011635912@infradead.org
This commit is contained in:

committed by
Ingo Molnar

parent
b2a02fc43a
commit
4b44a21dd6
@@ -16,17 +16,38 @@
|
||||
|
||||
typedef void (*smp_call_func_t)(void *info);
|
||||
typedef bool (*smp_cond_func_t)(int cpu, void *info);
|
||||
|
||||
enum {
|
||||
CSD_FLAG_LOCK = 0x01,
|
||||
|
||||
/* IRQ_WORK_flags */
|
||||
|
||||
CSD_TYPE_ASYNC = 0x00,
|
||||
CSD_TYPE_SYNC = 0x10,
|
||||
CSD_TYPE_IRQ_WORK = 0x20,
|
||||
CSD_FLAG_TYPE_MASK = 0xF0,
|
||||
};
|
||||
|
||||
/*
|
||||
* structure shares (partial) layout with struct irq_work
|
||||
*/
|
||||
struct __call_single_data {
|
||||
struct llist_node llist;
|
||||
unsigned int flags;
|
||||
smp_call_func_t func;
|
||||
void *info;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/* Use __aligned() to avoid to use 2 cache lines for 1 csd */
|
||||
typedef struct __call_single_data call_single_data_t
|
||||
__aligned(sizeof(struct __call_single_data));
|
||||
|
||||
/*
|
||||
* Enqueue a llist_node on the call_single_queue; be very careful, read
|
||||
* flush_smp_call_function_queue() in detail.
|
||||
*/
|
||||
extern void __smp_call_single_queue(int cpu, struct llist_node *node);
|
||||
|
||||
/* total number of cpus in this system (may exceed NR_CPUS) */
|
||||
extern unsigned int total_cpus;
|
||||
|
||||
|
Reference in New Issue
Block a user