signal: adjust the signal processing logic to remove the judgment

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

View File

@ -75,70 +75,61 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
this_task()->xcp.regs);
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task() && !up_interrupt_context())
{
tcb->sigdeliver = sigdeliver;
/* In this case just deliver the signal now. */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
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(),
this_task()->xcp.regs);
/* Save the current register context location */
if (tcb == this_task() && !up_interrupt_context())
{
/* In this case just deliver the signal now. */
tcb->xcp.saved_regs = tcb->xcp.regs;
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
/* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
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.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* 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
* restored by the signal trampoline after the signal has been
* 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;
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
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,67 +75,58 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
this_task()->xcp.regs);
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task() && !up_interrupt_context())
{
tcb->sigdeliver = sigdeliver;
/* In this case just deliver the signal now. */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
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(),
this_task()->xcp.regs);
/* Save the current register context location */
if (tcb == this_task() && !up_interrupt_context())
{
/* In this case just deliver the signal now. */
tcb->xcp.saved_regs = tcb->xcp.regs;
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
/* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
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.regs = (void *)((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* 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
* restored by the signal trampoline after the signal has been
* 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_LR] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
tcb->xcp.regs[REG_IRQ_EN] = 0;
}
tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
tcb->xcp.regs[REG_IRQ_EN] = 0;
}
}

View File

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

View File

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

View File

@ -75,95 +75,87 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task())
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
if (tcb == this_task())
if (!up_current_regs())
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
/* In this case just deliver the signal now. */
if (!up_current_regs())
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* g_current_regs does not refer to the thread of this_task()!
*/
else
{
/* Save 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);
}
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* g_current_regs does not refer to the thread of this_task()!
*/
else
{
/* Save registers that must be protected while the signal handler
* runs. These will be restored by the signal trampoline after
* the signals have been delivered.
/* 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 = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR];
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
*/
tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver;
tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK;
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
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
else
{
/* Save registers that must be protected while the signal handler
* runs. These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver;
tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK;
}
}

View File

@ -72,139 +72,130 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
DEBUGASSERT(tcb != NULL && sigdeliver != NULL);
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 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
* to task that is currently executing on any CPU.
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
if (tcb->task_state == TSTATE_TASK_RUNNING)
if (cpu == me && !up_current_regs())
{
uint8_t me = this_cpu();
#ifdef CONFIG_SMP
uint8_t cpu = tcb->cpu;
#else
uint8_t cpu = 0;
#endif
/* In this case just deliver the signal now. */
/* 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. */
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
}
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running from an
* interrupt handler or (2) we are not in an interrupt handler and the
* running task is signaling some other non-running task.
/* 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 = tcb->xcp.regs;
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.
/* 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);
up_current_regs() -= XCPTCONTEXT_REGS;
memcpy(up_current_regs(), up_current_regs() +
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
* unchanged. We must already be in privileged thread mode to be
* here.
* unchanged. We must already be in privileged thread mode
* to be here.
*/
tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver;
up_current_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;
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
* 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 */

View File

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

View File

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

View File

@ -76,103 +76,95 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task())
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
*/
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
if (tcb == this_task())
if (!up_current_regs())
{
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
*/
/* In this case just deliver the signal now. */
if (!up_current_regs())
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: We are in an interrupt handler AND the interrupted task
* is the same as the one that must receive the signal, then we
* will have to modify the return state as well as the state in
* the TCB.
*
* Hmmm... there looks like a latent bug here: The following logic
* would fail in the strange case where we are in an interrupt
* handler, the thread is signalling itself, but a context switch
* to another task has occurred so that g_current_regs does not
* refer to the thread of this_task()!
*/
else
{
/* Save the return 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]);
}
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running from an
* interrupt handler or (2) we are not in an interrupt handler and the
* running task is signalling some non-running task.
/* CASE 2: We are in an interrupt handler AND the interrupted task
* is the same as the one that must receive the signal, then we
* will have to modify the return state as well as the state in
* the TCB.
*
* Hmmm... there looks like a latent bug here: The following logic
* would fail in the strange case where we are in an interrupt
* handler, the thread is signalling itself, but a context switch
* to another task has occurred so that g_current_regs does not
* refer to the thread of this_task()!
*/
else
{
/* Save the return EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have been
* delivered.
* 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];
tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC];
/* 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_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,
tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]);
up_current_regs()[REG_CSR_MEPC],
up_current_regs()[REG_CSR_MSTATUS]);
}
}
/* Otherwise, we are (1) signaling a task is not running from an
* interrupt handler or (2) we are not in an interrupt handler and the
* running task is signalling some non-running task.
*/
else
{
/* Save the return EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have been
* delivered.
*/
tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver;
up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE;
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]);
}
}

View File

@ -74,80 +74,39 @@
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task())
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
if (tcb == this_task())
if (!up_current_regs())
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
/* In this case just deliver the signal now. */
if (!up_current_regs())
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* 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);
}
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* current_regs does not refer to the thread of this_task()!
*/
else
@ -157,17 +116,50 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
/* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */
/* 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
*/
/* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver;
* tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
/* 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
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
else
{
/* Save the return lr and cpsr and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
/* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver;
* tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT;
*/
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -72,245 +72,39 @@
****************************************************************************/
#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 */
flags = enter_critical_section();
/* Refuse to handle nested signal actions */
if (!tcb->sigdeliver)
if (tcb == this_task())
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
if (tcb == this_task())
if (!up_current_regs())
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
/* In this case just deliver the signal now. */
if (!up_current_regs())
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
tcb->sigdeliver = NULL;
}
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* 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);
}
(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
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;
}
}
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.
/* 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
@ -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];
/* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be
* here.
* 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;
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);
}
}
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 */

View File

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

View File

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

View File

@ -71,54 +71,173 @@
****************************************************************************/
#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("rtcb=%p g_current_regs=%p\n", this_task(), up_current_regs());
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
/* Refuse to handle nested signal actions */
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/
if (!tcb->sigdeliver)
if (tcb == this_task())
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
*/
if (tcb == this_task())
if (!up_current_regs())
{
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
/* In this case just deliver the signal with a function call
* 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
* now.
/* 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.
*/
sigdeliver(tcb);
tcb->sigdeliver = NULL;
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;
}
/* 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 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];
@ -139,184 +258,46 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
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.
/* 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
*/
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];
/* RESUME the other CPU if it was PAUSED */
/* 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;
if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
{
up_cpu_resume(cpu);
}
}
}
}
#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 */
if (tcb->sigdeliver == NULL)
else
{
tcb->sigdeliver = sigdeliver;
/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any 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.
*/
sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(),
up_current_regs());
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];
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 && 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.
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
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_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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