RT-Thread版本:4.0.3
static void _signal_deliver(rt_thread_t tid)
{
rt_ubase_t level;
level = rt_hw_interrupt_disable();
/* thread is not interested in pended signals */
if (!(tid->sig_pending & tid->sig_mask))
{
rt_hw_interrupt_enable(level);
return;
}
if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
{
/* resume thread to handle signal */
rt_thread_resume(tid);
/* add signal state */
tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
rt_hw_interrupt_enable(level);
/* re-schedule */
rt_schedule();
}
else
{
if (tid == rt_thread_self())
{
/* add signal state */
tid->stat |= RT_THREAD_STAT_SIGNAL;
rt_hw_interrupt_enable(level);
/* do signal action in self thread context */
if (rt_interrupt_get_nest() == 0)
{
rt_thread_handle_sig(RT_TRUE);
}
}
else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
{
/* add signal state */
tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
#ifdef RT_USING_SMP
{
int cpu_id;
cpu_id = tid->oncpu;
if ((cpu_id != RT_CPU_DETACHED) && (cpu_id != rt_hw_cpu_id()))
{
rt_uint32_t cpu_mask;
cpu_mask = RT_CPU_MASK ^ (1 << cpu_id);
rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
}
}
#else
/* point to the signal handle entry */
tid->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
tid->sig_ret = tid->sp;
tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
(void *)((char *)tid->sig_ret - 32), RT_NULL);
#endif
rt_hw_interrupt_enable(level);
LOG_D("signal stack pointer <a href="/u/14012" data-type="user" data-id="14012" data-toggle="popover" data-title="">@</a> 0x%08x", tid->sp);
/* re-schedule */
rt_schedule();
}
else
{
rt_hw_interrupt_enable(level);
}
}
}
在src/signal.c的_signal_deliver()函数中,根据目标线程的状态分为三种情况:
我的疑问是:
上述3的情况,为什么要采用构建新的context的方式来处理信号,为什么不采用与情况1相同的处理,也就是通过设置信号标志,然后在目标线程被唤醒的rt_schedule()中来处理?
另外,这里为什么要主动调用一次rt_schedule()?
嗯,我理解到了这个任务被唤醒后是先去执行新构造的frame里的入口,执行完后再切换到原来的frame。但是没理解为什么要这么做,为什么没有像情况1那样简单处理。还没想象到您说的复杂性,可能还是全局观不行。。。