mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 06:42:32 +08:00
sched/signal: Optimize code logic
Adjust the up_schedule_sigaction function to facilitate subsequent spinlock optimization work. Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
@@ -82,26 +82,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
/* Save the return lr and cpsr and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
* the signals have been delivered.
|
* the signals have been delivered.
|
||||||
@@ -133,5 +113,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#ifdef CONFIG_ARM_THUMB
|
#ifdef CONFIG_ARM_THUMB
|
||||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,16 +90,7 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && ipsr == 0)
|
if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
|
||||||
{
|
{
|
||||||
/* Context switch should be done in pendsv, for exception directly
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
* last regs is not saved tcb->xcp.regs.
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
|||||||
@@ -84,21 +84,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the return lr and cpsr and one scratch register. These
|
/* Save the return lr and cpsr and one scratch register. These
|
||||||
* will be restored by the signal trampoline after the signals
|
* will be restored by the signal trampoline after the signals
|
||||||
* have been delivered.
|
* have been delivered.
|
||||||
@@ -130,5 +115,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#ifdef CONFIG_ARM_THUMB
|
#ifdef CONFIG_ARM_THUMB
|
||||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,16 +91,7 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && ipsr == 0)
|
if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
|
||||||
{
|
{
|
||||||
/* Context switch should be done in pendsv, for exception directly
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
* last regs is not saved tcb->xcp.regs.
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
|||||||
@@ -82,21 +82,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the return lr and cpsr and one scratch register. These
|
/* Save the return lr and cpsr and one scratch register. These
|
||||||
* will be restored by the signal trampoline after the signals
|
* will be restored by the signal trampoline after the signals
|
||||||
* have been delivered.
|
* have been delivered.
|
||||||
@@ -128,5 +113,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#ifdef CONFIG_ARM_THUMB
|
#ifdef CONFIG_ARM_THUMB
|
||||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,16 +91,7 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && ipsr == 0)
|
if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
|
||||||
{
|
{
|
||||||
/* Context switch should be done in pendsv, for exception directly
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
* last regs is not saved tcb->xcp.regs.
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
|||||||
@@ -82,21 +82,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the return lr and cpsr and one scratch register. These
|
/* Save the return lr and cpsr and one scratch register. These
|
||||||
* will be restored by the signal trampoline after the signals
|
* will be restored by the signal trampoline after the signals
|
||||||
* have been delivered.
|
* have been delivered.
|
||||||
@@ -128,5 +113,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#ifdef CONFIG_ARM_THUMB
|
#ifdef CONFIG_ARM_THUMB
|
||||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,26 +82,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
/* Save the return lr and cpsr and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
* the signals have been delivered.
|
* the signals have been delivered.
|
||||||
@@ -130,5 +110,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
|
tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
|
||||||
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
|
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
|
||||||
tcb->xcp.regs[REG_IRQ_EN] = 0;
|
tcb->xcp.regs[REG_IRQ_EN] = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,21 +126,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the return lr and cpsr and one scratch register. These
|
/* Save the return lr and cpsr and one scratch register. These
|
||||||
* will be restored by the signal trampoline after the signals
|
* will be restored by the signal trampoline after the signals
|
||||||
* have been delivered.
|
* have been delivered.
|
||||||
@@ -151,5 +136,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
/* create signal process context */
|
/* create signal process context */
|
||||||
|
|
||||||
arm64_init_signal_process(tcb, NULL);
|
arm64_init_signal_process(tcb, NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,32 +89,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
* g_current_regs does not refer to the thread of this_task()!
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save registers that must be protected while the signal
|
/* Save registers that must be protected while the signal
|
||||||
* handler runs. These will be restored by the signal
|
* handler runs. These will be restored by the signal
|
||||||
@@ -151,7 +125,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
avr_savestate(tcb->xcp.regs);
|
avr_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -87,32 +87,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
* g_current_regs does not refer to the thread of this_task()!
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save registers that must be protected while the signal
|
/* Save registers that must be protected while the signal
|
||||||
* handler runs. These will be restored by the signal
|
* handler runs. These will be restored by the signal
|
||||||
@@ -135,7 +109,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
avr_savestate(tcb->xcp.regs);
|
avr_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -84,35 +84,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||||
{
|
|
||||||
uint8_t me = this_cpu();
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
uint8_t cpu = tcb->cpu;
|
|
||||||
#else
|
|
||||||
uint8_t cpu = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signaling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (cpu == me && !up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
{
|
{
|
||||||
/* Save the current register context location */
|
/* Save the current register context location */
|
||||||
|
|
||||||
@@ -140,7 +111,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
up_current_regs()[REG_OM] |= REG_OM_KERNEL;
|
up_current_regs()[REG_OM] |= REG_OM_KERNEL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running from an
|
/* 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
|
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||||
|
|||||||
@@ -90,32 +90,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
* 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 return EPC and STATUS registers. These will be
|
||||||
* restored by the signal trampoline after the signals have
|
* restored by the signal trampoline after the signals have
|
||||||
@@ -147,7 +121,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
up_current_regs()[REG_EPC],
|
up_current_regs()[REG_EPC],
|
||||||
up_current_regs()[REG_STATUS]);
|
up_current_regs()[REG_STATUS]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -87,32 +87,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
* 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 return EPC and STATUS registers. These will be
|
||||||
* restored by the signal trampoline after the signals have
|
* restored by the signal trampoline after the signals have
|
||||||
@@ -139,7 +113,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
up_current_regs()[REG_EPC],
|
up_current_regs()[REG_EPC],
|
||||||
up_current_regs()[REG_STATUS]);
|
up_current_regs()[REG_STATUS]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -88,32 +88,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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 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 return EPC and STATUS registers. These will be
|
||||||
* restored by the signal trampoline after the signals have
|
* restored by the signal trampoline after the signals have
|
||||||
@@ -141,7 +115,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
up_current_regs()[REG_CSR_MEPC],
|
up_current_regs()[REG_CSR_MEPC],
|
||||||
up_current_regs()[REG_CSR_MSTATUS]);
|
up_current_regs()[REG_CSR_MSTATUS]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running from an
|
/* 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
|
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||||
|
|||||||
@@ -86,32 +86,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
/* Save the return lr and cpsr and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
@@ -137,7 +111,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
or1k_savestate(tcb->xcp.regs);
|
or1k_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -86,26 +86,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save the return PC and SR and one scratch register
|
/* Save the return PC and SR and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
@@ -130,7 +110,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -86,26 +86,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save the return PC and SR and one scratch register
|
/* Save the return PC and SR and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
@@ -128,7 +108,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -86,26 +86,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save the return PC and SR and one scratch register
|
/* Save the return PC and SR and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
@@ -128,7 +108,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
renesas_copystate(tcb->xcp.regs, up_current_regs());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -85,21 +85,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is being delivered
|
|
||||||
* to task that is currently executing on any CPU.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the return EPC and STATUS registers. These will be
|
/* Save the return EPC and STATUS registers. These will be
|
||||||
* by the signal trampoline after the signal has been delivered.
|
* by the signal trampoline after the signal has been delivered.
|
||||||
*/
|
*/
|
||||||
@@ -136,5 +121,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
|
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,32 +84,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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 registers that must be protected while the signal
|
/* Save registers that must be protected while the signal
|
||||||
* handler runs. These will be restored by the signal
|
* handler runs. These will be restored by the signal
|
||||||
@@ -134,7 +108,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
sparc_savestate(tcb->xcp.regs);
|
sparc_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
@@ -167,9 +140,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
int cpu;
|
|
||||||
int me;
|
|
||||||
|
|
||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
|
||||||
this_task(), up_current_regs());
|
this_task(), up_current_regs());
|
||||||
|
|
||||||
@@ -179,35 +149,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
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
|
|
||||||
{
|
|
||||||
/* tcb is running on the same CPU */
|
|
||||||
|
|
||||||
/* Save registers that must be protected while the signal
|
/* Save registers that must be protected while the signal
|
||||||
* handler runs. These will be restored by the signal
|
* handler runs. These will be restored by the signal
|
||||||
* trampoline after the signal(s) have been delivered.
|
* trampoline after the signal(s) have been delivered.
|
||||||
@@ -233,7 +174,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
sparc_savestate(tcb->xcp.regs);
|
sparc_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running from an
|
/* 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
|
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||||
|
|||||||
@@ -80,38 +80,6 @@
|
|||||||
|
|
||||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
/* First, handle some special cases when the signal is
|
|
||||||
* being delivered to the currently executing task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task())
|
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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
|
|
||||||
* g_current_regs does not refer to the thread of this_task()!
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the context registers. These will be
|
/* Save the context registers. These will be
|
||||||
* restored by the signal trampoline after the signals have
|
* restored by the signal trampoline after the signals have
|
||||||
* been delivered.
|
* been delivered.
|
||||||
@@ -123,38 +91,8 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* will borrow the process stack of the current tcb.
|
* will borrow the process stack of the current tcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.regs =
|
tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
|
||||||
tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
|
|
||||||
STACKFRAME_ALIGN_DOWN
|
STACKFRAME_ALIGN_DOWN
|
||||||
(up_getusrsp(tcb->xcp.regs)),
|
(up_getusrsp(tcb->xcp.regs)),
|
||||||
PSW_IO_SUPERVISOR | PSW_CDE, true);
|
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,
|
|
||||||
STACKFRAME_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
|
|
||||||
PSW_IO_SUPERVISOR | PSW_CDE, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,32 +82,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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 g_current_regs does not
|
|
||||||
* refer to the thread of this_task()!
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Save the return lr and cpsr and one scratch register. These
|
/* Save the return lr and cpsr and one scratch register. These
|
||||||
* will be restored by the signal trampoline after the signals
|
* will be restored by the signal trampoline after the signals
|
||||||
@@ -130,7 +104,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
x86_savestate(tcb->xcp.regs);
|
x86_savestate(tcb->xcp.regs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -77,23 +77,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
|
||||||
this_task(), this_task()->xcp.regs);
|
this_task(), this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is being delivered
|
|
||||||
* to task that is currently executing on any CPU.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 return lr and cpsr and one scratch register
|
/* Save the return lr and cpsr and one scratch register
|
||||||
* These will be restored by the signal trampoline after
|
* These will be restored by the signal trampoline after
|
||||||
* the signals have been delivered.
|
* the signals have been delivered.
|
||||||
@@ -110,5 +93,4 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
|
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_RSP] = tcb->xcp.regs[REG_RSP] - 8;
|
||||||
tcb->xcp.regs[REG_RFLAGS] = 0;
|
tcb->xcp.regs[REG_RFLAGS] = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,21 +85,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||||
this_task()->xcp.regs);
|
this_task()->xcp.regs);
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is being delivered
|
|
||||||
* to task that is currently executing on any CPU.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tcb == this_task() && !up_interrupt_context())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now.
|
|
||||||
* REVISIT: Signal handler will run in a critical section!
|
|
||||||
*/
|
|
||||||
|
|
||||||
(tcb->sigdeliver)(tcb);
|
|
||||||
tcb->sigdeliver = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save the context registers. These will be restored by the
|
/* Save the context registers. These will be restored by the
|
||||||
* signal trampoline after the signals have been delivered.
|
* signal trampoline after the signals have been delivered.
|
||||||
*
|
*
|
||||||
@@ -132,15 +117,12 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
|
|
||||||
tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver;
|
tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver;
|
||||||
#ifdef __XTENSA_CALL0_ABI__
|
#ifdef __XTENSA_CALL0_ABI__
|
||||||
tcb->xcp.regs[REG_PS] = (uint32_t)
|
tcb->xcp.regs[REG_PS] = (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
|
||||||
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
|
|
||||||
#else
|
#else
|
||||||
tcb->xcp.regs[REG_PS] = (uint32_t)
|
tcb->xcp.regs[REG_PS] = (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
|
||||||
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
|
|
||||||
PS_WOE | PS_CALLINC(1));
|
PS_WOE | PS_CALLINC(1));
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_BUILD_FLAT
|
#ifndef CONFIG_BUILD_FLAT
|
||||||
xtensa_raiseprivilege(tcb->xcp.regs);
|
xtensa_raiseprivilege(tcb->xcp.regs);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,26 +86,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and
|
|
||||||
* a task is signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!up_current_regs())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
FAR uint32_t *current_pc =
|
FAR uint32_t *current_pc =
|
||||||
(FAR uint32_t *)&up_current_regs()[REG_PC];
|
(FAR uint32_t *)&up_current_regs()[REG_PC];
|
||||||
@@ -131,7 +111,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
z16_copystate(tcb->xcp.regs, up_current_regs());
|
z16_copystate(tcb->xcp.regs, up_current_regs());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running from an
|
/* Otherwise, we are (1) signaling a task is not running from an
|
||||||
* interrupt handler or (2) we are not in an interrupt handler
|
* interrupt handler or (2) we are not in an interrupt handler
|
||||||
|
|||||||
@@ -110,26 +110,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!IN_INTERRUPT())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Set up to vector to the trampoline with interrupts
|
/* Set up to vector to the trampoline with interrupts
|
||||||
* disabled.
|
* disabled.
|
||||||
@@ -143,7 +123,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
SAVE_IRQCONTEXT(tcb);
|
SAVE_IRQCONTEXT(tcb);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running from an
|
/* 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
|
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||||
|
|||||||
@@ -113,26 +113,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!IN_INTERRUPT())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Set up to vector to the trampoline with interrupts
|
/* Set up to vector to the trampoline with interrupts
|
||||||
* disabled.
|
* disabled.
|
||||||
@@ -146,7 +126,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
SAVE_IRQCONTEXT(tcb);
|
SAVE_IRQCONTEXT(tcb);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -110,26 +110,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!IN_INTERRUPT())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Set up to vector to the trampoline with interrupts
|
/* Set up to vector to the trampoline with interrupts
|
||||||
* disabled.
|
* disabled.
|
||||||
@@ -143,7 +123,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
SAVE_IRQCONTEXT(tcb);
|
SAVE_IRQCONTEXT(tcb);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -111,26 +111,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == this_task())
|
if (tcb == this_task())
|
||||||
{
|
|
||||||
/* CASE 1: We are not in an interrupt handler and a task is
|
|
||||||
* signalling itself for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!IN_INTERRUPT())
|
|
||||||
{
|
|
||||||
/* In this case just deliver the signal now. */
|
|
||||||
|
|
||||||
(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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Set up to vector to the trampoline with interrupts
|
/* Set up to vector to the trampoline with interrupts
|
||||||
* disabled.
|
* disabled.
|
||||||
@@ -144,7 +124,6 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb)
|
|||||||
|
|
||||||
SAVE_IRQCONTEXT(tcb);
|
SAVE_IRQCONTEXT(tcb);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, we are (1) signaling a task is not running
|
/* Otherwise, we are (1) signaling a task is not running
|
||||||
* from an interrupt handler or (2) we are not in an
|
* from an interrupt handler or (2) we are not in an
|
||||||
|
|||||||
@@ -185,11 +185,21 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
stcb->sigdeliver = nxsig_deliver;
|
stcb->sigdeliver = nxsig_deliver;
|
||||||
|
if (stcb == this_task() && !up_interrupt_context())
|
||||||
|
{
|
||||||
|
/* In this case just deliver the signal now. */
|
||||||
|
|
||||||
|
(stcb->sigdeliver)(stcb);
|
||||||
|
stcb->sigdeliver = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
up_schedule_sigaction(stcb);
|
up_schedule_sigaction(stcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user