mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
signal: adjust the signal processing logic to remove the judgment
Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
@@ -70,95 +70,87 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
|
||||
this_task(), up_current_regs());
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
if (!tcb->sigdeliver)
|
||||
if (tcb == this_task())
|
||||
{
|
||||
tcb->sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted task
|
||||
* is the same as the one that must receive the signal, then we
|
||||
* will have to modify the return state as well as the state in the
|
||||
* TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that g_current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_eip = up_current_regs()[REG_EIP];
|
||||
tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver;
|
||||
up_current_regs()[REG_EFLAGS] = 0;
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
*/
|
||||
|
||||
x86_savestate(tcb->xcp.regs);
|
||||
}
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running
|
||||
* from an interrupt handler or (2) we are not in an
|
||||
* interrupt handler and the running task is signalling
|
||||
* some non-running task.
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted task
|
||||
* is the same as the one that must receive the signal, then we
|
||||
* will have to modify the return state as well as the state in the
|
||||
* TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that g_current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP];
|
||||
tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS];
|
||||
tcb->xcp.saved_eip = up_current_regs()[REG_EIP];
|
||||
tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver;
|
||||
tcb->xcp.regs[REG_EFLAGS] = 0;
|
||||
up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver;
|
||||
up_current_regs()[REG_EFLAGS] = 0;
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
*/
|
||||
|
||||
x86_savestate(tcb->xcp.regs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running
|
||||
* from an interrupt handler or (2) we are not in an
|
||||
* interrupt handler and the running task is signalling
|
||||
* some non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP];
|
||||
tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver;
|
||||
tcb->xcp.regs[REG_EFLAGS] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user