signal: adjust the signal processing logic to remove the judgment
Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
8275a846b1
commit
487fcb3bce
@ -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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user