static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq) { if (cpu_online(cpu)) { cp->func = remote_softirq_receive; cp->info = &softirq; cp->flags = 0; __smp_call_function_single(cpu, cp, 0); return 0; } return 1; }
/* * Setup and invoke a run of 'trigger_softirq' on the given cpu. */ static int raise_blk_irq(int cpu, struct request *rq) { if (cpu_online(cpu)) { struct call_single_data *data = &rq->csd; data->func = trigger_softirq; data->info = rq; data->flags = 0; __smp_call_function_single(cpu, data, 0); return 0; } return 1; }
static void update_timers(int cpu) { struct call_single_data data = {.func = restart_watchdog_hrtimer}; /* * Make sure that perf event counter will adopt to a new * sampling period. Updating the sampling period directly would * be much nicer but we do not have an API for that now so * let's use a big hammer. * Hrtimer will adopt the new period on the next tick but this * might be late already so we have to restart the timer as well. */ watchdog_nmi_disable(cpu); __smp_call_function_single(cpu, &data, 1); watchdog_nmi_enable(cpu); }
static void null_cmd_end_ipi(struct nullb_cmd *cmd) { struct call_single_data *data = &cmd->csd; int cpu = get_cpu(); struct completion_queue *cq = &per_cpu(completion_queues, cpu); cmd->ll_list.next = NULL; if (llist_add(&cmd->ll_list, &cq->list)) { data->func = null_ipi_cmd_end_io; data->flags = 0; __smp_call_function_single(cpu, data, 0); } put_cpu(); }
int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { /* prevent preemption and reschedule on another processor */ unsigned long flags; int me = get_cpu(); if (cpu == me) { local_irq_save(flags); func(info); local_irq_restore(flags); } else { spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); } put_cpu(); return 0; }
int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { /* prevent preemption and reschedule on another processor */ int me = get_cpu(); if (cpu == me) { WARN_ON(1); put_cpu(); return -EBUSY; } /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); put_cpu(); return 0; }