3.10的内核,
在子进程退出的时候,发送信号通知父进程,此时是持有父进程的sighand中的spinlock的,然后父进程和该子进程不在一个核上,发送ipi的reschedule中断给对应的核,
但是,由于信号其实是异步机制,在没有发送ipi之前,对应的接收进程已经在处理信号,
处理信号的过程中,又需要拿自己对应task_struct中的sighand里面的spinlock,导致了死锁。
那么,为什么子进程发送ipi需要这么久呢?按道理不是发送完ipi中断不就可以释放锁了么?
调用链为:kick_process--->smp_send_reschedule(父进程所在的cpu)--->native_smp_send_reschedule--->(apic->send_IPI_mask)
---->physflat_send_IPI_mask---default_send_IPI_mask_sequence_phys--->__default_send_IPI_dest_filed--->__xapic_wait_icr_idle
最后循环在:
static inline void __xapic_wait_icr_idle(void)
{
while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
cpu_relax();
}
嗯,操作对应的内存,发现APIC_ICR_BUSY一直满足,然后就死等了。
有一点没想清楚:
static inline void
__default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
{
unsigned long cfg;
/*
* Wait for idle.
*/
if (unlikely(vector == NMI_VECTOR))-----为啥发送NMI就需要用safe,而发送reschedule则不需要呢?
safe_apic_wait_icr_idle();
else
__xapic_wait_icr_idle();
从代码看,APIC_ICR是local apic,发送ipi的时候,按道理只需要自己这边空闲就行。