IPI 通信(SMP)【轉】


轉自:https://winddoing.github.io/post/60164.html

IPI (Interrupt-Procecesorr Interrupt): 處理中間的中斷

主要應用是一個處理器讓另一個處理器做特定的事情(function 和 sched)

 
              +---------------------------+-+
system boot | request_percpu_irq() +
| mailbox irq handle +
+--+-----------------------+--+
| |
| |
+--v--+ +---v-+
| CPU0| > CPU1|
+--+--+ +----++
| |
+----+----+ +-----+-----+
|mailbox0 | +-->mailbox1 |
+---------+ | +-----------+
|
+---------------+ |
system run A send IPI CPU1 |
write mailbox1 |
| |
| +-----v-----------------+---+
+------+----+ | 1. 讀取mailbox中的action +
| Task A | | 2. 通過action判斷IPI類型 +
| | | 3. 進行function和sched處理+
+-----------+ | +
+---------------------------+

在多核處理器中,每一個 CPU 核有一個 mailbox(相當於郵箱),如果需要進行 IPI 通信時,其主要通過 IPI 的中斷實現。假設 CPU0 需要給 CPU1 發送一個 action(actionI 的類型:SMP_CALL_FUNCTION,SMP_RESCHEDULE_YOURSELF 等) 時,只需要 CPU0 向 CPU1 的 mailbox 中寫於 action 的 id(相當於信),此時 CPU1 將產生一個 IPI 中斷(表明收到信),mailbox 的中斷處理程序將讀取 mailbox(相當於看信)中的 action,判斷 action 的類型進行相應的處理。

MIPS 架構下的 IPI 通信

  1. 關閉中斷后還會發送 IPI

MIPS 接口

 
struct plat_smp_ops {
void (*send_ipi_single)(int cpu, unsigned int action);
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
...
}

IPI 通信就是多個處理器之間的交流
send_ipi_single: 一對一聊天
send_ipi_mask : 群發,mask 表示群發的成員(CPU)

action 類型

 
 
        
 
        

/* Octeon - Tell another core to flush its icache */

/* Used by kexec crashdump to save all cpu's state */
 
        
 

file: arch/mips/include/asm/smp.h

  1. 不同的 action (活動) 何時將產生?
  2. 各自都有什么作用?

SMP_RESCHEDULE_YOURSELF

SMP_RESCHEDULE_YOURSELF 將直接調用 scheduler_ipi. 將任務插入目標 CPU 的運行隊列。

 
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
* anything. Worst case is that we lose a reschedule ...
*/
static inline void smp_send_reschedule(int cpu)
{
extern struct plat_smp_ops *mp_ops; /* private */

mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF);
}

file: arch/mips/include/asm/smp.h

SMP_CALL_FUNCTION

SMP_CALL_FUNCTION: 將特定的函數在目標 CPU 上運行

  • 內核回調接口:
     
static inline void arch_send_call_function_single_ipi(int cpu)
{
extern struct plat_smp_ops *mp_ops; /* private */

mp_ops->send_ipi_mask(&cpumask_of_cpu(cpu), SMP_CALL_FUNCTION);
}

static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
extern struct plat_smp_ops *mp_ops; /* private */

mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
}

file: arch/mips/include/asm/smp.h

 
/*
* smp_call_function_single - Run a function on a specific CPU
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
* @wait: If true, wait until function has completed on other CPUs.
*
* Returns 0 on success, else a negative status code.
*/

smp_call_function_single
\->generic_exec_single
\->arch_send_call_function_single_ipi

/**
* smp_call_function_many(): Run a function on a set of other CPUs.
* @mask: The set of cpus to run on (only runs on online subset).
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
* @wait: If true, wait (atomically) until function has completed
* on other CPUs.
*
* If @wait is true, then returns once @func has returned.
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler. Preemption
* must be disabled when calling this function.
*/

smp_call_function_many
\->arch_send_call_function_ipi_mask

file: kernel/smp.c

刷新 TLB

多核進行 TLB 的同步?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM