signal: adjust the signal processing logic to remove the judgment

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5 2024-09-09 20:17:25 +08:00 committed by Xiang Xiao
parent 8275a846b1
commit 487fcb3bce
33 changed files with 1938 additions and 2220 deletions

View File

@ -75,70 +75,61 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now. */
/* First, handle some special cases when the signal is (tcb->sigdeliver)(tcb);
* being delivered to the currently executing task. 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.
*/
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.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), /* Save the current register context location */
this_task()->xcp.regs);
if (tcb == this_task() && !up_interrupt_context()) tcb->xcp.saved_regs = tcb->xcp.regs;
{
/* In this case just deliver the signal now. */
sigdeliver(tcb); /* Duplicate the register context. These will be
tcb->sigdeliver = NULL; * restored by the signal trampoline after the signal has been
} * delivered.
/* 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 tcb->xcp.regs = (void *)
{ ((uint32_t)tcb->xcp.regs -
/* Save the return lr and cpsr and one scratch register XCPTCONTEXT_SIZE);
* These will be restored by the signal trampoline after memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
* the signals have been delivered.
*/
/* Save the current register context location */ tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
tcb->xcp.saved_regs = tcb->xcp.regs; /* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* Duplicate the register context. These will be tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
* restored by the signal trampoline after the signal has been tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
* delivered.
*/
tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
}
} }
} }

View File

@ -78,103 +78,93 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
DEBUGASSERT(tcb != NULL && sigdeliver != NULL); this_task()->xcp.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 == NULL) if (tcb == this_task() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handle will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
if (tcb == this_task() && !up_interrupt_context()) /* If we signaling a task running on the other CPU, we have
{ * to PAUSE the other CPU.
/* In this case just deliver the signal now. */
* REVISIT: Signal handle will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
* registers (and perhaps also the LR). These will be restored * registers (and perhaps also the LR). These will be restored
* by the signal trampoline after the signal has been delivered. * by the signal trampoline after the signal has been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled. We must already be in privileged thread mode to be
* here. * here.
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_PRIMASK] = 1;
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED #ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -77,98 +77,89 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on this CPU.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
if (tcb == this_task() && !up_interrupt_context()) /* If we signaling a task running on the other CPU, we have
{ * to PAUSE the other CPU.
/* In this case just deliver the signal now. */
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return lr and cpsr and one scratch register. These /* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals * will be restored by the signal trampoline after the signals
* have been delivered. * have been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -79,107 +79,97 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
DEBUGASSERT(tcb != NULL && sigdeliver != NULL); this_task()->xcp.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 == NULL) if (tcb == this_task() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handle will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
if (tcb == this_task() && !up_interrupt_context()) /* If we signaling a task running on the other CPU, we have
{ * to PAUSE the other CPU.
/* In this case just deliver the signal now. */
* REVISIT: Signal handle will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
* registers (and perhaps also the LR). These will be restored * registers (and perhaps also the LR). These will be restored
* by the signal trampoline after the signal has been delivered. * by the signal trampoline after the signal has been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled. We must already be in privileged thread mode to be
* here. * here.
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
#ifdef CONFIG_ARMV7M_USEBASEPRI #ifdef CONFIG_ARMV7M_USEBASEPRI
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
#else #else
tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_PRIMASK] = 1;
#endif #endif
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED #ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -75,90 +75,81 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
if (tcb == this_task() && !up_interrupt_context()) else
{ {
/* In this case just deliver the signal now. /* If we signaling a task running on the other CPU, we have
* REVISIT: Signal handler will run in a critical section! * to PAUSE the other CPU.
*/ */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return lr and cpsr and one scratch register. These /* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals * will be restored by the signal trampoline after the signals
* have been delivered. * have been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -79,107 +79,97 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
DEBUGASSERT(tcb != NULL && sigdeliver != NULL); this_task()->xcp.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 == NULL) if (tcb == this_task() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handle will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
if (tcb == this_task() && !up_interrupt_context()) /* If we signaling a task running on the other CPU, we have
{ * to PAUSE the other CPU.
/* In this case just deliver the signal now. */
* REVISIT: Signal handle will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
* registers (and perhaps also the LR). These will be restored * registers (and perhaps also the LR). These will be restored
* by the signal trampoline after the signal has been delivered. * by the signal trampoline after the signal has been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled. We must already be in privileged thread mode to be
* here. * here.
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
#ifdef CONFIG_ARMV8M_USEBASEPRI #ifdef CONFIG_ARMV8M_USEBASEPRI
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
#else #else
tcb->xcp.regs[REG_PRIMASK] = 1; tcb->xcp.regs[REG_PRIMASK] = 1;
#endif #endif
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED #ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -75,90 +75,81 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), (tcb->sigdeliver)(tcb);
this_task()->xcp.regs); tcb->sigdeliver = NULL;
}
if (tcb == this_task() && !up_interrupt_context()) else
{ {
/* In this case just deliver the signal now. /* If we signaling a task running on the other CPU, we have
* REVISIT: Signal handler will run in a critical section! * to PAUSE the other CPU.
*/ */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return lr and cpsr and one scratch register. These /* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals * will be restored by the signal trampoline after the signals
* have been delivered. * have been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -75,67 +75,58 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now. */
/* First, handle some special cases when the signal is (tcb->sigdeliver)(tcb);
* being delivered to the currently executing task. 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.
*/
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.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), /* Save the current register context location */
this_task()->xcp.regs);
if (tcb == this_task() && !up_interrupt_context()) tcb->xcp.saved_regs = tcb->xcp.regs;
{
/* In this case just deliver the signal now. */
sigdeliver(tcb); /* Duplicate the register context. These will be
tcb->sigdeliver = NULL; * restored by the signal trampoline after the signal has been
} * delivered.
/* 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 tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs -
{ XCPTCONTEXT_SIZE);
/* Save the return lr and cpsr and one scratch register memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
/* Save the current register context location */ tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
tcb->xcp.saved_regs = tcb->xcp.regs; /* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* Duplicate the register context. These will be tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
* restored by the signal trampoline after the signal has been tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
* delivered. tcb->xcp.regs[REG_IRQ_EN] = 0;
*/
tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
tcb->xcp.regs[REG_IRQ_EN] = 0;
}
} }
} }

View File

@ -112,62 +112,56 @@ void arm64_init_signal_process(struct tcb_s *tcb, struct regs_context *regs)
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.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() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/ */
if (tcb == this_task() && !up_interrupt_context()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* In this case just deliver the signal now. }
* REVISIT: Signal handler will run in a critical section! else
*/ {
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return lr and cpsr and one scratch register. These /* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals * will be restored by the signal trampoline after the signals
* have been delivered. * have been delivered.
*/ */
tcb->xcp.saved_reg = tcb->xcp.regs; tcb->xcp.saved_reg = tcb->xcp.regs;
/* create signal process context */ /* create signal process context */
arm64_init_signal_process(tcb, NULL); arm64_init_signal_process(tcb, NULL);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -75,120 +75,112 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
uintptr_t reg_ptr = (uintptr_t)avr_sigdeliver; uintptr_t reg_ptr = (uintptr_t)avr_sigdeliver;
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0];
tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1];
#if defined(REG_PC2)
tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2];
#endif
tcb->xcp.saved_sreg = up_current_regs()[REG_SREG];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
#if !defined(REG_PC2)
up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8;
up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff;
#else
up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16;
up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8;
up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff;
#endif
up_current_regs()[REG_SREG] &= ~(1 << SREG_I);
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
avr_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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 else
{ {
/* Save registers that must be protected while the signal handler /* Save registers that must be protected while the signal
* runs. These will be restored by the signal trampoline after * handler runs. These will be restored by the signal
* the signals have been delivered. * trampoline after the signal(s) have been delivered.
*/ */
tcb->xcp.saved_pc0 = tcb->xcp.regs[REG_PC0]; tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0];
tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1]; tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1];
#if defined(REG_PC2) #if defined(REG_PC2)
tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2]; tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2];
#endif #endif
tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; tcb->xcp.saved_sreg = up_current_regs()[REG_SREG];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
#if !defined(REG_PC2) #if !defined(REG_PC2)
tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8; up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8;
tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff; up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff;
#else #else
tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16; up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16;
tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8; up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8;
tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff; up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff;
#endif #endif
tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I); up_current_regs()[REG_SREG] &= ~(1 << SREG_I);
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
avr_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 registers that must be protected while the signal handler
* runs. These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc0 = tcb->xcp.regs[REG_PC0];
tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1];
#if defined(REG_PC2)
tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2];
#endif
tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
#if !defined(REG_PC2)
tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8;
tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff;
#else
tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16;
tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8;
tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff;
#endif
tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I);
}
} }

View File

@ -75,95 +75,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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver;
up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
avr_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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 else
{ {
/* Save registers that must be protected while the signal handler /* Save registers that must be protected while the signal
* runs. These will be restored by the signal trampoline after * handler runs. These will be restored by the signal
* the signals have been delivered. * trampoline after the signal(s) have been delivered.
*/ */
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver; up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver;
tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK; up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
avr_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 registers that must be protected while the signal handler
* runs. These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver;
tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK;
}
} }

View File

@ -72,139 +72,130 @@
* *
****************************************************************************/ ****************************************************************************/
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,
DEBUGASSERT(tcb != NULL && sigdeliver != NULL); this_task(), up_current_regs());
/* Refuse to handle nested signal actions */ /* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
if (tcb->sigdeliver == NULL) if (tcb->task_state == TSTATE_TASK_RUNNING)
{ {
tcb->sigdeliver = sigdeliver; uint8_t me = this_cpu();
#ifdef CONFIG_SMP
uint8_t cpu = tcb->cpu;
#else
uint8_t cpu = 0;
#endif
/* First, handle some special cases when the signal is being delivered /* CASE 1: We are not in an interrupt handler and a task is
* to task that is currently executing on any CPU. * signaling itself for some reason.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (cpu == me && !up_current_regs())
if (tcb->task_state == TSTATE_TASK_RUNNING)
{ {
uint8_t me = this_cpu(); /* In this case just deliver the signal now. */
#ifdef CONFIG_SMP
uint8_t cpu = tcb->cpu;
#else
uint8_t cpu = 0;
#endif
/* CASE 1: We are not in an interrupt handler and a task is (tcb->sigdeliver)(tcb);
* signaling itself for some reason. tcb->sigdeliver = NULL;
*/
if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
else
{
#ifdef CONFIG_SMP
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me)
{
/* Pause the CPU */
up_cpu_pause(cpu);
}
/* Now tcb on the other CPU can be accessed safely */
#endif
/* Save the current register context location */
tcb->xcp.saved_regs = up_current_regs();
/* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
up_current_regs() -= XCPTCONTEXT_REGS;
memcpy(up_current_regs(), up_current_regs() +
XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE);
up_current_regs()[REG_SP] = (uint32_t)up_current_regs();
/* Then set up to vector to the trampoline with interrupts
* unchanged. We must already be in privileged thread mode
* to be here.
*/
up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver;
#ifdef REG_OM
up_current_regs()[REG_OM] &= ~REG_OM_MASK;
up_current_regs()[REG_OM] |= REG_OM_KERNEL;
#endif
#ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */
if (cpu != me)
{
up_cpu_resume(cpu);
}
#endif
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* CASE 2: The task that needs to receive the signal is running.
* interrupt handler or (2) we are not in an interrupt handler and the * This could happen if the task is running on another CPU OR if
* running task is signaling some other non-running task. * we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/ */
else else
{ {
#ifdef CONFIG_SMP
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me)
{
/* Pause the CPU */
up_cpu_pause(cpu);
}
/* Now tcb on the other CPU can be accessed safely */
#endif
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = up_current_regs();
/* Duplicate the register context. These will be restored /* Duplicate the register context. These will be
* by the signal trampoline after the signal has been delivered. * restored by the signal trampoline after the signal has been
* delivered.
*/ */
tcb->xcp.regs -= XCPTCONTEXT_REGS; up_current_regs() -= XCPTCONTEXT_REGS;
memcpy(tcb->xcp.regs, tcb->xcp.regs + memcpy(up_current_regs(), up_current_regs() +
XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs; up_current_regs()[REG_SP] = (uint32_t)up_current_regs();
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* unchanged. We must already be in privileged thread mode to be * unchanged. We must already be in privileged thread mode
* here. * to be here.
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver; up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver;
#ifdef REG_OM #ifdef REG_OM
tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK; up_current_regs()[REG_OM] &= ~REG_OM_MASK;
tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL; up_current_regs()[REG_OM] |= REG_OM_KERNEL;
#endif
#ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */
if (cpu != me)
{
up_cpu_resume(cpu);
}
#endif #endif
} }
} }
/* 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 signaling some other non-running task.
*/
else
{
/* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be restored
* by the signal trampoline after the signal has been delivered.
*/
tcb->xcp.regs -= XCPTCONTEXT_REGS;
memcpy(tcb->xcp.regs, tcb->xcp.regs +
XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs;
/* Then set up to vector to the trampoline with interrupts
* unchanged. We must already be in privileged thread mode to be
* here.
*/
tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver;
#ifdef REG_OM
tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK;
tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL;
#endif
}
} }
#endif /* !CONFIG_DISABLE_SIGNALS */ #endif /* !CONFIG_DISABLE_SIGNALS */

View File

@ -76,88 +76,41 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
uint32_t status; uint32_t status;
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
tcb->xcp.saved_status = up_current_regs()[REG_STATUS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver;
status = up_current_regs()[REG_STATUS];
status &= ~CP0_STATUS_INT_MASK;
status |= CP0_STATUS_INT_SW0;
up_current_regs()[REG_STATUS] = status;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
mips_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
" New: %08" PRIx32 "/%08" PRIx32 "\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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 else
@ -167,23 +120,62 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* been delivered. * been delivered.
*/ */
tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS]; tcb->xcp.saved_status = up_current_regs()[REG_STATUS];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver; up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver;
status = tcb->xcp.regs[REG_STATUS]; status = up_current_regs()[REG_STATUS];
status &= ~CP0_STATUS_INT_MASK; status &= ~CP0_STATUS_INT_MASK;
status |= CP0_STATUS_INT_SW0; status |= CP0_STATUS_INT_SW0;
tcb->xcp.regs[REG_STATUS] = status; up_current_regs()[REG_STATUS] = status;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
mips_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
" New: %08" PRIx32 "/%08" PRIx32 "\n", " New: %08" PRIx32 "/%08" PRIx32 "\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status, tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
} }
} }
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver;
status = tcb->xcp.regs[REG_STATUS];
status &= ~CP0_STATUS_INT_MASK;
status |= CP0_STATUS_INT_SW0;
tcb->xcp.regs[REG_STATUS] = status;
sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
" New: %08" PRIx32 "/%08" PRIx32 "\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]);
}
} }

View File

@ -75,81 +75,39 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver;
up_current_regs()[REG_INT_CTX] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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 else
@ -159,19 +117,53 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* been delivered. * been delivered.
*/ */
tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver; up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver;
tcb->xcp.regs[REG_INT_CTX] = 0; up_current_regs()[REG_INT_CTX] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status, tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
} }
} }
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver;
tcb->xcp.regs[REG_INT_CTX] = 0;
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]);
}
} }

View File

@ -76,103 +76,95 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_CSR_MEPC] =
(uint32_t)minerva_sigdeliver;
up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE;
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_CSR_MEPC],
up_current_regs()[REG_CSR_MSTATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* CASE 2: We are in an interrupt handler AND the interrupted task
* interrupt handler or (2) we are not in an interrupt handler and the * is the same as the one that must receive the signal, then we
* running task is signalling some non-running task. * 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 else
{ {
/* Save the return EPC and STATUS registers. These will be /* Save the return EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have been * restored by the signal trampoline after the signals have
* delivered. * been delivered.
*/ */
tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC]; tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver; up_current_regs()[REG_CSR_MEPC] =
(uint32_t)minerva_sigdeliver;
up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE;
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status, tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]); up_current_regs()[REG_CSR_MEPC],
up_current_regs()[REG_CSR_MSTATUS]);
} }
} }
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have been
* delivered.
*/
tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver;
up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE;
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]);
}
} }

View File

@ -74,80 +74,39 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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
* 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_pc = up_current_regs()[REG_PC];
* tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR];
*/
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver;
* up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT |
* PSR_F_BIT;
*/
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
or1k_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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
* current_regs does not refer to the thread of this_task()!
*/ */
else else
@ -157,17 +116,50 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* the signals have been delivered. * the signals have been delivered.
*/ */
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; /* tcb->xcp.saved_pc = up_current_regs()[REG_PC];
* tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR];
/* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */ */
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
/* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver; /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver;
* tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT |
* PSR_F_BIT;
*/ */
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
or1k_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_pc = tcb->xcp.regs[REG_PC];
/* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver;
* tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
*/
}
} }

View File

@ -74,73 +74,33 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Save the return PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC];
tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1];
tcb->xcp.saved_flg = up_current_regs()[REG_FLG];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8;
up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_FLG] &= ~M16C_FLG_I;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * the return state as well as the state in the TCB.
*/ */
else else
@ -150,17 +110,49 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* the signals have been delivered. * the signals have been delivered.
*/ */
tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC]; tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC];
tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1]; tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1];
tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG]; tcb->xcp.saved_flg = up_current_regs()[REG_FLG];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8;
tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver; up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I; up_current_regs()[REG_FLG] &= ~M16C_FLG_I;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_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 PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1];
tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8;
tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I;
}
} }

View File

@ -74,71 +74,33 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Save the return PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = up_current_regs()[REG_PSW];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_PSW] |= 0x00030000;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * the return state as well as the state in the TCB.
*/ */
else else
@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* the signals have been delivered. * the signals have been delivered.
*/ */
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW]; tcb->xcp.saved_sr = up_current_regs()[REG_PSW];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_PSW] |= 0x00030000; up_current_regs()[REG_PSW] |= 0x00030000;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_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 PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_PSW] |= 0x00030000;
}
} }

View File

@ -74,71 +74,33 @@
* *
****************************************************************************/ ****************************************************************************/
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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Save the return PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_SR] |= 0x000000f0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * the return state as well as the state in the TCB.
*/ */
else else
@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* the signals have been delivered. * the signals have been delivered.
*/ */
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_SR] |= 0x000000f0 ; up_current_regs()[REG_SR] |= 0x000000f0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_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 PC and SR and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver;
tcb->xcp.regs[REG_SR] |= 0x000000f0 ;
}
} }

View File

@ -76,89 +76,83 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
uintptr_t int_ctx; uintptr_t int_ctx;
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
this_task()->xcp.regs);
/* Refuse to handle nested signal actions */ /* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
if (!tcb->sigdeliver) if (tcb == this_task() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/ */
if (tcb == this_task() && !up_interrupt_context()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* In this case just deliver the signal now. }
* REVISIT: Signal handler will run in a critical section! else
*/ {
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the return EPC and STATUS registers. These will be /* Save the return EPC and STATUS registers. These will be
* by the signal trampoline after the signal has been delivered. * by the signal trampoline after the signal has been delivered.
*/ */
/* Save the current register context location */ /* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (uintreg_t *) tcb->xcp.regs = (uintreg_t *)
((uintptr_t)tcb->xcp.regs - ((uintptr_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uintptr_t)tcb->xcp.regs + tcb->xcp.regs[REG_SP] = (uintptr_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled. We must already be in privileged thread mode to be
* here. * here.
*/ */
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = tcb->xcp.regs[REG_INT_CTX]; int_ctx = tcb->xcp.regs[REG_INT_CTX];
int_ctx &= ~STATUS_PIE; int_ctx &= ~STATUS_PIE;
#ifndef CONFIG_BUILD_FLAT #ifndef CONFIG_BUILD_FLAT
int_ctx |= STATUS_PPP; int_ctx |= STATUS_PPP;
#endif #endif
tcb->xcp.regs[REG_INT_CTX] = int_ctx; tcb->xcp.regs[REG_INT_CTX] = int_ctx;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -71,27 +71,15 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
irqstate_t flags;
/* We don't have to anything complex for the simulated target */ /* We don't have to anything complex for the simulated target */
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); sinfo("tcb=%p\n", tcb);
/* Make sure that interrupts are disabled */ if (tcb == this_task())
flags = enter_critical_section();
if (tcb->sigdeliver == NULL)
{ {
tcb->sigdeliver = sigdeliver; (tcb->sigdeliver)(tcb);
if (tcb == this_task()) tcb->sigdeliver = NULL;
{
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
} }
leave_critical_section(flags);
} }

View File

@ -72,245 +72,39 @@
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
irqstate_t flags; sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); /* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
/* Make sure that interrupts are disabled */ if (tcb == this_task())
flags = enter_critical_section();
/* Refuse to handle nested signal actions */
if (!tcb->sigdeliver)
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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
* current_regs does not refer to the thread of this_task()!
*/
else
{
/* Save registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
tcb->xcp.saved_status = up_current_regs()[REG_PSR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
sparc_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * the return state as well as the state in the TCB.
*/ *
* Hmmm... there looks like a latent bug here: The following
else * logic would fail in the strange case where we are in an
{ * interrupt handler, the thread is signalling itself, but
/* Save registers that must be protected while the signal handler * a context switch to another task has occurred so that
* runs. These will be restored by the signal trampoline after * current_regs does not refer to the thread of this_task()!
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
}
}
leave_critical_section(flags);
}
#endif /* !CONFIG_SMP */
#ifdef CONFIG_SMP
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
{
irqstate_t flags;
int cpu;
int me;
sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
/* Make sure that interrupts are disabled */
flags = enter_critical_section();
/* Refuse to handle nested signal actions */
if (!tcb->sigdeliver)
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(), up_current_regs());
if (tcb->task_state == TSTATE_TASK_RUNNING)
{
me = this_cpu();
cpu = tcb->cpu;
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/
if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me)
{
/* Pause the CPU */
up_cpu_pause(cpu);
/* Now tcb on the other CPU can be accessed safely */
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
* restored by the signal trampoline after the signal has
* been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
/* Then set up vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode
* to be here.
*/
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
}
else
{
/* tcb is running on the same CPU */
/* Save registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
tcb->xcp.saved_status = up_current_regs()[REG_PSR];
/* Then set up vector to the trampoline with interrupts
* disabled. The kernel-space trampoline must run in
* privileged thread mode.
*/
up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver
+ 4;
up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB is the
* same as the interrupt return context.
*/
sparc_savestate(tcb->xcp.regs);
}
/* NOTE: If the task runs on another CPU(cpu), adjusting
* global IRQ controls will be done in the pause handler
* on the CPU(cpu) by taking a critical section.
* If the task is scheduled on this CPU(me), do nothing
* because this CPU already took a critical section
*/
/* RESUME the other CPU if it was PAUSED */
if (cpu != me)
{
up_cpu_resume(cpu);
}
}
}
/* 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 signaling some other non-running task.
*/ */
else else
@ -325,16 +119,191 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.saved_status = up_current_regs()[REG_PSR]; tcb->xcp.saved_status = up_current_regs()[REG_PSR];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled
* here.
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
sparc_savestate(tcb->xcp.regs);
} }
} }
leave_critical_section(flags); /* 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 registers that must be protected while the signal handler
* runs. These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
}
}
#endif /* !CONFIG_SMP */
#ifdef CONFIG_SMP
void up_schedule_sigaction(struct tcb_s *tcb)
{
int cpu;
int me;
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
if (tcb->task_state == TSTATE_TASK_RUNNING)
{
me = this_cpu();
cpu = tcb->cpu;
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/
if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me)
{
/* Pause the CPU */
up_cpu_pause(cpu);
/* Now tcb on the other CPU can be accessed safely */
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
* restored by the signal trampoline after the signal has
* been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
/* Then set up vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode
* to be here.
*/
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
}
else
{
/* tcb is running on the same CPU */
/* Save registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
tcb->xcp.saved_status = up_current_regs()[REG_PSR];
/* Then set up vector to the trampoline with interrupts
* disabled. The kernel-space trampoline must run in
* privileged thread mode.
*/
up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver
+ 4;
up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB is the
* same as the interrupt return context.
*/
sparc_savestate(tcb->xcp.regs);
}
/* NOTE: If the task runs on another CPU(cpu), adjusting
* global IRQ controls will be done in the pause handler
* on the CPU(cpu) by taking a critical section.
* If the task is scheduled on this CPU(me), do nothing
* because this CPU already took a critical section
*/
/* RESUME the other CPU if it was PAUSED */
if (cpu != me)
{
up_cpu_resume(cpu);
}
}
}
/* 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 signaling some other non-running task.
*/
else
{
/* Save registers that must be protected while the signal
* handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
tcb->xcp.saved_status = up_current_regs()[REG_PSR];
/* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be
* here.
*/
tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver;
tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
}
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */

View File

@ -76,88 +76,81 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(struct tcb_s *tcb)
{ {
/* 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 == NULL) if (tcb == this_task())
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
if (tcb == this_task()) if (up_current_regs() == NULL)
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (up_current_regs() == NULL) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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 context registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tricore_savestate(tcb->xcp.saved_regs);
/* Create a new CSA for signal delivery. The new context
* will borrow the process stack of the current tcb.
*/
up_set_current_regs(tricore_alloc_csa((uintptr_t)
tricore_sigdeliver,
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
PSW_IO_SUPERVISOR | PSW_CDE, true));
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the
* from an interrupt handler or (2) we are not in an * interrupted task is the same as the one that
* interrupt handler and the running task is signalling * must receive the signal, then we will have to modify
* some non-running task. * 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 else
{ {
/* Save the return EPC and STATUS registers. These will be /* Save the context registers. These will be
* restored by the signal trampoline after the signals have * restored by the signal trampoline after the signals have
* been delivered. * been delivered.
*/ */
/* Save the current register context location */ tricore_savestate(tcb->xcp.saved_regs);
tcb->xcp.saved_regs = tcb->xcp.regs;
/* Create a new CSA for signal delivery. The new context /* Create a new CSA for signal delivery. The new context
* will borrow the process stack of the current tcb. * will borrow the process stack of the current tcb.
*/ */
tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver, up_set_current_regs(tricore_alloc_csa((uintptr_t)
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), tricore_sigdeliver,
PSW_IO_SUPERVISOR | PSW_CDE, true); STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
PSW_IO_SUPERVISOR | PSW_CDE, true));
} }
} }
/* 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 EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
/* Save the current register context location */
tcb->xcp.saved_regs = tcb->xcp.regs;
/* Create a new CSA for signal delivery. The new context
* will borrow the process stack of the current tcb.
*/
tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
PSW_IO_SUPERVISOR | PSW_CDE, true);
}
} }

View File

@ -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; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the interrupted task
* from an interrupt handler or (2) we are not in an * is the same as the one that must receive the signal, then we
* interrupt handler and the running task is signalling * will have to modify the return state as well as the state in the
* some non-running task. * 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 else
{ {
/* Save the return lr and cpsr and one scratch register /* Save the return lr and cpsr and one scratch register. These
* These will be restored by the signal trampoline after * will be restored by the signal trampoline after the signals
* the signals have been delivered. * have been delivered.
*/ */
tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP]; tcb->xcp.saved_eip = up_current_regs()[REG_EIP];
tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS]; tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver; up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver;
tcb->xcp.regs[REG_EFLAGS] = 0; 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;
}
} }

View File

@ -71,54 +71,173 @@
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
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,
sinfo("rtcb=%p g_current_regs=%p\n", this_task(), up_current_regs()); 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; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
if (tcb == this_task()) if (!up_current_regs())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal with a function call
* signalling itself for some reason. * now.
*/ */
if (!up_current_regs()) (tcb->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 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_rip = up_current_regs()[REG_RIP];
tcb->xcp.saved_rsp = up_current_regs()[REG_RSP];
tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver;
up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8;
up_current_regs()[REG_RFLAGS] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
x86_64_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_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
}
#else /* !CONFIG_SMP */
void up_schedule_sigaction(struct tcb_s *tcb)
{
int cpu;
int me;
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
if (tcb->task_state == TSTATE_TASK_RUNNING)
{
me = this_cpu();
cpu = tcb->cpu;
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/
if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* In this case just deliver the signal with a function call /* Pause the CPU */
* now.
up_cpu_pause(cpu);
/* Now tcb on the other CPU can be accessed safely */
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
* restored by the signal trampoline after the signal has
* been delivered.
*/ */
sigdeliver(tcb); tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->sigdeliver = NULL; tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
} }
/* 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 current_regs does not
* refer to the thread of this_task()!
*/
else else
{ {
/* Save the return lr and cpsr and one scratch register. These /* tcb is running on the same CPU */
* 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_rip = up_current_regs()[REG_RIP]; tcb->xcp.saved_rip = up_current_regs()[REG_RIP];
@ -139,184 +258,46 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
x86_64_savestate(tcb->xcp.regs); x86_64_savestate(tcb->xcp.regs);
} }
}
/* Otherwise, we are (1) signaling a task is not running /* NOTE: If the task runs on another CPU(cpu), adjusting
* from an interrupt handler or (2) we are not in an * global IRQ controls will be done in the pause handler
* interrupt handler and the running task is signalling * on the CPU(cpu) by taking a critical section.
* some non-running task. * If the task is scheduled on this CPU(me), do nothing
*/ * because this CPU already took a critical section
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_rip = tcb->xcp.regs[REG_RIP]; /* RESUME the other CPU if it was PAUSED */
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
* disabled {
*/ up_cpu_resume(cpu);
}
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
} }
} }
}
#else /* !CONFIG_SMP */
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
{
int cpu;
int me;
sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); /* 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 signaling some other non-running task.
*/
/* Refuse to handle nested signal actions */ else
if (tcb->sigdeliver == NULL)
{ {
tcb->sigdeliver = sigdeliver; /* Save the return lr and cpsr and one scratch register
* These will be restored by the signal trampoline after
/* First, handle some special cases when the signal is being delivered * the signals have been delivered.
* to task that is currently executing on any CPU.
*/ */
sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(), tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
up_current_regs()); tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
if (tcb->task_state == TSTATE_TASK_RUNNING) /* Then set up to vector to the trampoline with interrupts
{ * disabled
me = this_cpu();
cpu = tcb->cpu;
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/
if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/
else
{
/* If we signaling a task running on the other CPU, we have
* to PAUSE the other CPU.
*/
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{
/* Pause the CPU */
up_cpu_pause(cpu);
/* Now tcb on the other CPU can be accessed safely */
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
* restored by the signal trampoline after the signal has
* been delivered.
*/
tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
else
{
/* tcb is running on the same CPU */
/* 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_rip = up_current_regs()[REG_RIP];
tcb->xcp.saved_rsp = up_current_regs()[REG_RSP];
tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
up_current_regs()[REG_RIP] =
(uint64_t)x86_64_sigdeliver;
up_current_regs()[REG_RSP] =
up_current_regs()[REG_RSP] - 8;
up_current_regs()[REG_RFLAGS] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
x86_64_savestate(tcb->xcp.regs);
}
/* NOTE: If the task runs on another CPU(cpu), adjusting
* global IRQ controls will be done in the pause handler
* on the CPU(cpu) by taking a critical section.
* If the task is scheduled on this CPU(me), do nothing
* because this CPU already took a critical section
*/
/* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{
up_cpu_resume(cpu);
}
}
}
/* 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 signaling some other non-running task.
*/ */
else tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
{ tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
/* Save the return lr and cpsr and one scratch register tcb->xcp.regs[REG_RFLAGS] = 0;
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
} }
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */

View File

@ -78,94 +78,88 @@
* *
****************************************************************************/ ****************************************************************************/
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(),
this_task()->xcp.regs);
/* Refuse to handle nested signal actions */ /* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/
if (!tcb->sigdeliver) if (tcb == this_task() && !up_interrupt_context())
{ {
tcb->sigdeliver = sigdeliver; /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/ */
if (tcb == this_task() && !up_interrupt_context()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* In this case just deliver the signal now. }
* REVISIT: Signal handler will run in a critical section! else
*/ {
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
else
{
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpu = tcb->cpu; int cpu = tcb->cpu;
int me = this_cpu(); int me = this_cpu();
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
/* Pause the CPU */ /* Pause the CPU */
up_cpu_pause(cpu); up_cpu_pause(cpu);
} }
#endif #endif
/* Save the context registers. These will be restored by the /* Save the context registers. These will be restored by the
* signal trampoline after the signals have been delivered. * signal trampoline after the signals have been delivered.
* *
* NOTE: that hi-priority interrupts are not disabled. * NOTE: that hi-priority interrupts are not disabled.
*/ */
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.saved_regs = tcb->xcp.regs;
if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0)
{ {
tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK;
} }
/* Duplicate the register context. These will be /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been * restored by the signal trampoline after the signal has been
* delivered. * delivered.
*/ */
tcb->xcp.regs = (void *) tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs - ((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE); XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver; tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver;
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
tcb->xcp.regs[REG_PS] = (uint32_t) tcb->xcp.regs[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
#else #else
tcb->xcp.regs[REG_PS] = (uint32_t) tcb->xcp.regs[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1)); PS_WOE | PS_CALLINC(1));
#endif #endif
#ifndef CONFIG_BUILD_FLAT #ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(tcb->xcp.regs); xtensa_raiseprivilege(tcb->xcp.regs);
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* RESUME the other CPU if it was PAUSED */ /* RESUME the other CPU if it was PAUSED */
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{ {
up_cpu_resume(cpu); up_cpu_resume(cpu);
}
#endif
} }
#endif
} }
} }

View File

@ -74,93 +74,85 @@
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(FAR struct tcb_s *tcb)
{ {
sinfo("tcb=%p sigdeliver=0x%06x\n", tcb, (uint32_t)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; /* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/ */
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); if (!up_current_regs())
if (tcb == this_task())
{ {
/* CASE 1: We are not in an interrupt handler and /* In this case just deliver the signal now. */
* a task is signalling itself for some reason.
*/
if (!up_current_regs()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
FAR uint32_t *current_pc =
(FAR uint32_t *)&up_current_regs()[REG_PC];
/* Save the return address and interrupt state. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_pc = *current_pc;
tcb->xcp.saved_i = up_current_regs()[REG_FLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
*current_pc = (uint32_t)z16_sigdeliver;
up_current_regs()[REG_FLAGS] = 0;
/* And make sure that the saved context in the TCB is the
* same as the interrupt return context.
*/
z16_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* CASE 2: We are in an interrupt handler AND the interrupted
* interrupt handler or (2) we are not in an interrupt handler * task is the same as the one that must receive the signal, then
* and the running task is signalling some non-running task. * we will have to modify the return state as well as the state
* in the TCB.
*/ */
else else
{ {
FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC]; FAR uint32_t *current_pc =
(FAR uint32_t *)&up_current_regs()[REG_PC];
/* Save the return lr and cpsr and one scratch register /* Save the return address and interrupt state. These will be
* These will be restored by the signal trampoline after * restored by the signal trampoline after the signals have
* the signals have been delivered. * been delivered.
*/ */
tcb->xcp.saved_pc = *saved_pc; tcb->xcp.saved_pc = *current_pc;
tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS]; tcb->xcp.saved_i = up_current_regs()[REG_FLAGS];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
*saved_pc = (uint32_t)z16_sigdeliver; *current_pc = (uint32_t)z16_sigdeliver;
tcb->xcp.regs[REG_FLAGS] = 0; up_current_regs()[REG_FLAGS] = 0;
/* And make sure that the saved context in the TCB is the
* same as the interrupt return context.
*/
z16_copystate(tcb->xcp.regs, up_current_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
{
FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC];
/* 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_pc = *saved_pc;
tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
*saved_pc = (uint32_t)z16_sigdeliver;
tcb->xcp.regs[REG_FLAGS] = 0;
}
} }

View File

@ -43,8 +43,7 @@
* Name: ez80_sigsetup * Name: ez80_sigsetup
****************************************************************************/ ****************************************************************************/
static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, static void ez80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs)
FAR chipreg_t *regs)
{ {
/* Save the return address and interrupt state. These will be restored by /* Save the return address and interrupt state. These will be restored by
* the signal trampoline after the signals have been delivered. * the signal trampoline after the signals have been delivered.
@ -99,66 +98,60 @@ static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver,
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(FAR struct tcb_s *tcb)
{ {
sinfo("tcb=%p sigdeliver=0x%06" PRIx32 "\n", tcb, (uint32_t)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 == NULL) if (tcb == this_task())
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
if (tcb == this_task()) if (!IN_INTERRUPT())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!IN_INTERRUPT()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
ez80_sigsetup(tcb, sigdeliver, (chipreg_t *)IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* CASE 2: We are in an interrupt handler AND the interrupted task
* interrupt handler or (2) we are not in an interrupt handler and the * is the same as the one that must receive the signal, then we
* running task is signaling some non-running task. * will have to modify the return state as well as the state in
* the TCB.
*/ */
else else
{ {
/* Set up to vector to the trampoline with interrupts disabled. */ /* Set up to vector to the trampoline with interrupts
* disabled.
*/
ez80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); ez80_sigsetup(tcb, (chipreg_t *)IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
} }
} }
/* 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 signaling some non-running task.
*/
else
{
/* Set up to vector to the trampoline with interrupts disabled. */
ez80_sigsetup(tcb, tcb->xcp.regs);
}
} }

View File

@ -46,8 +46,7 @@
* Name: z180_sigsetup * Name: z180_sigsetup
****************************************************************************/ ****************************************************************************/
static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, static void z180_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs)
FAR chipreg_t *regs)
{ {
/* Save the return address and interrupt state. These will be restored by /* Save the return address and interrupt state. These will be restored by
* the signal trampoline after the signals have been delivered. * the signal trampoline after the signals have been delivered.
@ -102,67 +101,61 @@ static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver,
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(FAR struct tcb_s *tcb)
{ {
_info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)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 == NULL) if (tcb == this_task())
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
if (tcb == this_task()) if (!IN_INTERRUPT())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!IN_INTERRUPT()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
z180_sigsetup(tcb, sigdeliver, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the interrupted task
* from an interrupt handler or (2) we are not in an * is the same as the one that must receive the signal, then we
* interrupt handler and the running task is signalling * will have to modify the return state as well as the state in
* some non-running task. * the TCB.
*/ */
else else
{ {
/* Set up to vector to the trampoline with interrupts disabled. */ /* Set up to vector to the trampoline with interrupts
* disabled.
*/
z180_sigsetup(tcb, sigdeliver, tcb->xcp.regs); z180_sigsetup(tcb, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
} }
} }
/* 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
{
/* Set up to vector to the trampoline with interrupts disabled. */
z180_sigsetup(tcb, tcb->xcp.regs);
}
} }

View File

@ -43,8 +43,7 @@
* Name: z8_sigsetup * Name: z8_sigsetup
****************************************************************************/ ****************************************************************************/
static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, static void z8_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs)
FAR chipreg_t *regs)
{ {
/* Save the return address and interrupt state. These will be restored by /* Save the return address and interrupt state. These will be restored by
* the signal trampoline after the signals have been delivered. * the signal trampoline after the signals have been delivered.
@ -99,60 +98,33 @@ static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver,
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(FAR struct tcb_s *tcb)
{ {
sinfo("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)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 == NULL) if (tcb == this_task())
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
if (tcb == this_task()) if (!IN_INTERRUPT())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!IN_INTERRUPT()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
z8_sigsetup(tcb, sigdeliver, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the interrupted task
* from an interrupt handler or (2) we are not in an * is the same as the one that must receive the signal, then we
* interrupt handler and the running task is signalling * will have to modify the return state as well as the state in
* some non-running task. * the TCB.
*/ */
else else
@ -161,7 +133,28 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver)
* disabled. * disabled.
*/ */
z8_sigsetup(tcb, sigdeliver, tcb->xcp.regs); z8_sigsetup(tcb, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
} }
} }
/* 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
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
z8_sigsetup(tcb, tcb->xcp.regs);
}
} }

View File

@ -44,8 +44,7 @@
* Name: z80_sigsetup * Name: z80_sigsetup
****************************************************************************/ ****************************************************************************/
static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, static void z80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs)
FAR chipreg_t *regs)
{ {
/* Save the return address and interrupt state. These will be restored by /* Save the return address and interrupt state. These will be restored by
* the signal trampoline after the signals have been delivered. * the signal trampoline after the signals have been delivered.
@ -100,67 +99,61 @@ static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver,
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) void up_schedule_sigaction(FAR struct tcb_s *tcb)
{ {
_info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)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 == NULL) if (tcb == this_task())
{ {
tcb->sigdeliver = sigdeliver; /* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/ */
if (tcb == this_task()) if (!IN_INTERRUPT())
{ {
/* CASE 1: We are not in an interrupt handler and a task is /* In this case just deliver the signal now. */
* signalling itself for some reason.
*/
if (!IN_INTERRUPT()) (tcb->sigdeliver)(tcb);
{ tcb->sigdeliver = NULL;
/* 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.
*/
else
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
z80_sigsetup(tcb, sigdeliver, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* CASE 2: We are in an interrupt handler AND the interrupted task
* from an interrupt handler or (2) we are not in an * is the same as the one that must receive the signal, then we
* interrupt handler and the running task is signalling * will have to modify the return state as well as the state in
* some non-running task. * the TCB.
*/ */
else else
{ {
/* Set up to vector to the trampoline with interrupts disabled. */ /* Set up to vector to the trampoline with interrupts
* disabled.
*/
z80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); z80_sigsetup(tcb, IRQ_STATE());
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
SAVE_IRQCONTEXT(tcb);
} }
} }
/* 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
{
/* Set up to vector to the trampoline with interrupts disabled. */
z80_sigsetup(tcb, tcb->xcp.regs);
}
} }

View File

@ -541,7 +541,7 @@ int up_backtrace(FAR struct tcb_s *tcb,
* *
****************************************************************************/ ****************************************************************************/
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver); void up_schedule_sigaction(FAR struct tcb_s *tcb);
/**************************************************************************** /****************************************************************************
* Name: up_task_start * Name: up_task_start

View File

@ -115,7 +115,12 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, siginfo_t *info)
* up_schedule_sigaction() * up_schedule_sigaction()
*/ */
up_schedule_sigaction(stcb, nxsig_deliver); if (!stcb->sigdeliver)
{
stcb->sigdeliver = nxsig_deliver;
up_schedule_sigaction(stcb);
}
leave_critical_section(flags); leave_critical_section(flags);
} }
} }