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:
wangzhi16
2025-03-17 17:49:43 +08:00
committed by Xiang Xiao
parent 5775037da6
commit 364a633ec3
31 changed files with 436 additions and 1120 deletions
+20 -41
View File
@@ -82,56 +82,35 @@ 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 /* Save the return lr and cpsr and one scratch register
* being delivered to the currently executing task. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running /* Duplicate the register context. These will be
* from an interrupt handler or (2) we are not in an * restored by the signal trampoline after the signal has been
* interrupt handler and the running task is signalling * delivered.
* some non-running task.
*/ */
else tcb->xcp.regs = (void *)
{ ((uint32_t)tcb->xcp.regs -
/* Save the return lr and cpsr and one scratch register XCPTCONTEXT_SIZE);
* These will be restored by the signal trampoline after memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
* the signals have been delivered.
*/
/* Save the current register context location */ tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
tcb->xcp.saved_regs = tcb->xcp.regs; /* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* Duplicate the register context. These will be tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
* restored by the signal trampoline after the signal has been tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
* delivered.
*/
tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
}
} }
+1 -10
View File
@@ -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.
+21 -37
View File
@@ -84,51 +84,35 @@ 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 /* Save the return lr and cpsr and one scratch register. These
* being delivered to the currently executing task. * will be restored by the signal trampoline after the signals
* have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
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 current register context location */ /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* Duplicate the register context. These will be tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
* restored by the signal trampoline after the signal has been XCPTCONTEXT_SIZE;
* delivered.
*/
tcb->xcp.regs = (void *) /* Then set up to vector to the trampoline with interrupts
((uint32_t)tcb->xcp.regs - * disabled
XCPTCONTEXT_SIZE); */
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
XCPTCONTEXT_SIZE; tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
}
} }
+1 -10
View File
@@ -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.
+21 -37
View File
@@ -82,51 +82,35 @@ 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 /* Save the return lr and cpsr and one scratch register. These
* being delivered to the currently executing task. * will be restored by the signal trampoline after the signals
* have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
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 current register context location */ /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* Duplicate the register context. These will be tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
* restored by the signal trampoline after the signal has been XCPTCONTEXT_SIZE;
* delivered.
*/
tcb->xcp.regs = (void *) /* Then set up to vector to the trampoline with interrupts
((uint32_t)tcb->xcp.regs - * disabled
XCPTCONTEXT_SIZE); */
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
XCPTCONTEXT_SIZE; tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
}
} }
+1 -10
View File
@@ -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.
+21 -37
View File
@@ -82,51 +82,35 @@ 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 /* Save the return lr and cpsr and one scratch register. These
* being delivered to the currently executing task. * will be restored by the signal trampoline after the signals
* have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
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 current register context location */ /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.regs = (void *)
((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* Duplicate the register context. These will be tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
* restored by the signal trampoline after the signal has been XCPTCONTEXT_SIZE;
* delivered.
*/
tcb->xcp.regs = (void *) /* Then set up to vector to the trampoline with interrupts
((uint32_t)tcb->xcp.regs - * disabled
XCPTCONTEXT_SIZE); */
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
XCPTCONTEXT_SIZE; tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
#ifdef CONFIG_ARM_THUMB #ifdef CONFIG_ARM_THUMB
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
#endif #endif
}
} }
@@ -82,53 +82,32 @@ 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 /* Save the return lr and cpsr and one scratch register
* being delivered to the currently executing task. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running /* Duplicate the register context. These will be
* from an interrupt handler or (2) we are not in an * restored by the signal trampoline after the signal has been
* interrupt handler and the running task is signalling * delivered.
* some non-running task.
*/ */
else tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs -
{ XCPTCONTEXT_SIZE);
/* Save the return lr and cpsr and one scratch register memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
/* Save the current register context location */ tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
tcb->xcp.saved_regs = tcb->xcp.regs; /* Then set up to vector to the trampoline with interrupts
* disabled
*/
/* Duplicate the register context. These will be tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
* restored by the signal trampoline after the signal has been tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
* delivered. tcb->xcp.regs[REG_IRQ_EN] = 0;
*/
tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver;
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
tcb->xcp.regs[REG_IRQ_EN] = 0;
}
} }
@@ -126,30 +126,14 @@ 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 /* Save the return lr and cpsr and one scratch register. These
* being delivered to the currently executing task. * will be restored by the signal trampoline after the signals
* have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) tcb->xcp.saved_regs = tcb->xcp.regs;
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); /* create signal process context */
tcb->sigdeliver = NULL;
}
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_regs = tcb->xcp.regs; arm64_init_signal_process(tcb, NULL);
/* create signal process context */
arm64_init_signal_process(tcb, NULL);
}
} }
+21 -48
View File
@@ -90,67 +90,40 @@ 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 /* Save registers that must be protected while the signal
* a task is signalling itself for some reason. * handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0];
{ tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1];
/* 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
* 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) #if defined(REG_PC2)
tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2]; tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2];
#endif #endif
#if defined(REG_RAMPZ) #if defined(REG_RAMPZ)
tcb->xcp.saved_rampz = up_current_regs()[REG_RAMPZ]; tcb->xcp.saved_rampz = up_current_regs()[REG_RAMPZ];
#endif #endif
tcb->xcp.saved_sreg = up_current_regs()[REG_SREG]; tcb->xcp.saved_sreg = up_current_regs()[REG_SREG];
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled * disabled
*/ */
#if !defined(REG_PC2) #if !defined(REG_PC2)
up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8; up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8;
up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff; up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff;
#else #else
up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16; up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16;
up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8; up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8;
up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff; up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff;
#endif #endif
up_current_regs()[REG_SREG] &= ~(1 << SREG_I); up_current_regs()[REG_SREG] &= ~(1 << SREG_I);
/* And make sure that the saved context in the TCB /* And make sure that the saved context in the TCB
* is the same as the interrupt return context. * is the same as the interrupt return context.
*/ */
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
+13 -40
View File
@@ -88,53 +88,26 @@ 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 /* Save registers that must be protected while the signal
* a task is signalling itself for some reason. * handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver;
{ up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK;
/* 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]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_sr = up_current_regs()[REG_SR]; * is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts avr_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver;
up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
avr_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
+16 -46
View File
@@ -85,61 +85,31 @@ 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(); /* Save the current register context location */
#ifdef CONFIG_SMP
uint8_t cpu = tcb->cpu;
#else
uint8_t cpu = 0;
#endif
/* CASE 1: We are not in an interrupt handler and a task is tcb->xcp.saved_regs = up_current_regs();
* signaling itself for some reason.
/* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/ */
if (cpu == me && !up_current_regs()) up_current_regs() -= XCPTCONTEXT_REGS;
{ memcpy(up_current_regs(), up_current_regs() +
/* In this case just deliver the signal now. */ XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE);
(tcb->sigdeliver)(tcb); up_current_regs()[REG_SP] = (uint32_t)up_current_regs();
tcb->sigdeliver = NULL;
}
/* CASE 2: The task that needs to receive the signal is running. /* Then set up to vector to the trampoline with interrupts
* This could happen if the task is running on another CPU OR if * unchanged. We must already be in privileged thread mode
* we are in an interrupt handler and the task is running on this * to be here.
* 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 up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver;
{
/* 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 #ifdef REG_OM
up_current_regs()[REG_OM] &= ~REG_OM_MASK; up_current_regs()[REG_OM] &= ~REG_OM_MASK;
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
+21 -48
View File
@@ -91,62 +91,35 @@ 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 /* Save the return EPC and STATUS registers. These will be
* a task is signalling itself for some reason. * restored by the signal trampoline after the signals have
* been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
{ tcb->xcp.saved_status = up_current_regs()[REG_STATUS];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver;
{ status = up_current_regs()[REG_STATUS];
/* Save the return EPC and STATUS registers. These will be status &= ~CP0_STATUS_INT_MASK;
* restored by the signal trampoline after the signals have status |= CP0_STATUS_INT_SW0;
* been delivered. up_current_regs()[REG_STATUS] = status;
*/
tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_status = up_current_regs()[REG_STATUS]; * is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts mips_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver; sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
status = up_current_regs()[REG_STATUS]; " New: %08" PRIx32 "/%08" PRIx32 "\n",
status &= ~CP0_STATUS_INT_MASK; tcb->xcp.saved_epc, tcb->xcp.saved_status,
status |= CP0_STATUS_INT_SW0; up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS] = status; up_current_regs()[REG_STATUS]);
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
mips_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
" New: %08" PRIx32 "/%08" PRIx32 "\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
+16 -43
View File
@@ -88,57 +88,30 @@ 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 /* Save the return EPC and STATUS registers. These will be
* a task is signalling itself for some reason. * restored by the signal trampoline after the signals have
* been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver;
{ up_current_regs()[REG_INT_CTX] = 0;
/* 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]; /* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts misoc_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver; sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
up_current_regs()[REG_INT_CTX] = 0; tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_EPC],
/* And make sure that the saved context in the TCB up_current_regs()[REG_STATUS]);
* is the same as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_EPC],
up_current_regs()[REG_STATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
@@ -89,58 +89,31 @@ 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 /* Save the return EPC and STATUS registers. These will be
* signalling itself for some reason. * restored by the signal trampoline after the signals have
* been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC];
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_CSR_MEPC] =
{ (uint32_t)minerva_sigdeliver;
/* Save the return EPC and STATUS registers. These will be up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE;
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC]; /* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts misoc_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_CSR_MEPC] = sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
(uint32_t)minerva_sigdeliver; tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; up_current_regs()[REG_CSR_MEPC],
up_current_regs()[REG_CSR_MSTATUS]);
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
misoc_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
up_current_regs()[REG_CSR_MEPC],
up_current_regs()[REG_CSR_MSTATUS]);
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* Otherwise, we are (1) signaling a task is not running from an
+16 -43
View File
@@ -87,56 +87,29 @@ 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 /* Save the return lr and cpsr and one scratch register
* a task is signalling itself for some reason. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (!up_current_regs()) /* tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ * tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR];
/* 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 /* Then set up to vector to the trampoline with interrupts
{ * disabled
/* 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]; /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver;
* tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR]; * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT |
*/ * PSR_F_BIT;
*/
/* Then set up to vector to the trampoline with interrupts /* And make sure that the saved context in the TCB
* disabled * is the same as the interrupt return context.
*/ */
/* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver; or1k_savestate(tcb->xcp.regs);
* 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 /* Otherwise, we are (1) signaling a task is not running
+15 -36
View File
@@ -87,49 +87,28 @@ 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 /* Save the return PC and SR and one scratch register
* a task is signalling itself for some reason. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC];
{ tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1];
/* In this case just deliver the signal now. */ tcb->xcp.saved_flg = up_current_regs()[REG_FLG];
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8;
{ up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver;
/* Save the return PC and SR and one scratch register up_current_regs()[REG_FLG] &= ~M16C_FLG_I;
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1]; * is the same as the interrupt return context.
tcb->xcp.saved_flg = up_current_regs()[REG_FLG]; */
/* Then set up to vector to the trampoline with interrupts renesas_copystate(tcb->xcp.regs, up_current_regs());
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8;
up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_FLG] &= ~M16C_FLG_I;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
@@ -87,47 +87,26 @@ 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 /* Save the return PC and SR and one scratch register
* a task is signalling itself for some reason. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ tcb->xcp.saved_sr = up_current_regs()[REG_PSW];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
{ up_current_regs()[REG_PSW] |= 0x00030000;
/* 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]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_sr = up_current_regs()[REG_PSW]; * is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts renesas_copystate(tcb->xcp.regs, up_current_regs());
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_PSW] |= 0x00030000;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
+13 -34
View File
@@ -87,47 +87,26 @@ 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 /* Save the return PC and SR and one scratch register
* a task is signalling itself for some reason. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ tcb->xcp.saved_sr = up_current_regs()[REG_SR];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
{ up_current_regs()[REG_SR] |= 0x000000f0;
/* 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]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_sr = up_current_regs()[REG_SR]; * is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts renesas_copystate(tcb->xcp.regs, up_current_regs());
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver;
up_current_regs()[REG_SR] |= 0x000000f0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
renesas_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
@@ -85,56 +85,40 @@ 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 /* Save the return EPC and STATUS registers. These will be
* to task that is currently executing on any CPU. * by the signal trampoline after the signal has been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) /* Save the current register context location */
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); tcb->xcp.saved_regs = tcb->xcp.regs;
tcb->sigdeliver = NULL;
}
else
{
/* 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 */ /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
tcb->xcp.saved_regs = tcb->xcp.regs; tcb->xcp.regs = (uintreg_t *)
((uintptr_t)tcb->xcp.regs -
XCPTCONTEXT_SIZE);
/* Duplicate the register context. These will be memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
* restored by the signal trampoline after the signal has been
* delivered.
*/
tcb->xcp.regs = (uintreg_t *) tcb->xcp.regs[REG_SP] = (uintptr_t)tcb->xcp.regs +
((uintptr_t)tcb->xcp.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; XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts /* Then set up to vector to the trampoline with interrupts
* disabled. We must already be in privileged thread mode to be * disabled. We must already be in privileged thread mode to be
* here. * here.
*/ */
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
int_ctx = tcb->xcp.regs[REG_INT_CTX]; int_ctx = tcb->xcp.regs[REG_INT_CTX];
int_ctx &= ~STATUS_PIE; int_ctx &= ~STATUS_PIE;
#ifndef CONFIG_BUILD_FLAT #ifndef CONFIG_BUILD_FLAT
int_ctx |= STATUS_PPP; int_ctx |= STATUS_PPP;
#endif #endif
tcb->xcp.regs[REG_INT_CTX] = int_ctx; tcb->xcp.regs[REG_INT_CTX] = int_ctx;
}
} }
@@ -85,55 +85,28 @@ 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 /* Save registers that must be protected while the signal
* a task is signalling itself for some reason. * handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
/* In this case just deliver the signal now. */ tcb->xcp.saved_status = up_current_regs()[REG_PSR];
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
{ up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
/* Save registers that must be protected while the signal up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
* 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]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; * is the same as the interrupt return context.
tcb->xcp.saved_status = up_current_regs()[REG_PSR]; */
/* Then set up to vector to the trampoline with interrupts sparc_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
sparc_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
@@ -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,60 +149,30 @@ 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(); /* Save registers that must be protected while the signal
cpu = tcb->cpu; * handler runs. These will be restored by the signal
* trampoline after the signal(s) have been delivered.
/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/ */
if (cpu == me && !up_current_regs()) tcb->xcp.saved_pc = up_current_regs()[REG_PC];
{ tcb->xcp.saved_npc = up_current_regs()[REG_NPC];
/* In this case just deliver the signal now. tcb->xcp.saved_status = up_current_regs()[REG_PSR];
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); /* Then set up vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled. The kernel-space trampoline must run in
} * privileged thread mode.
/* 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 up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver;
{ up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver
/* 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; + 4;
up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK; up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
/* And make sure that the saved context in the TCB is the /* And make sure that the saved context in the TCB is the
* same as the interrupt return context. * same as the interrupt return context.
*/ */
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
@@ -80,81 +80,19 @@
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 /* Save the context registers. These will be
* being delivered to the currently executing task. * restored by the signal trampoline after the signals have
* been delivered.
*/ */
if (tcb == this_task()) tcb->xcp.saved_regs = tcb->xcp.regs;
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
if (!up_interrupt_context()) /* Create a new CSA for signal delivery. The new context
{ * will borrow the process stack of the current tcb.
/* 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
* restored by the signal trampoline after the signals have
* been delivered.
*/
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);
}
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/ */
else tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
{ STACKFRAME_ALIGN_DOWN
/* Save the return EPC and STATUS registers. These will be (up_getusrsp(tcb->xcp.regs)),
* restored by the signal trampoline after the signals have PSW_IO_SUPERVISOR | PSW_CDE, true);
* 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);
}
} }
+13 -40
View File
@@ -83,53 +83,26 @@ 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 /* Save the return lr and cpsr and one scratch register. These
* signalling itself for some reason. * will be restored by the signal trampoline after the signals
* have been delivered.
*/ */
if (!up_current_regs()) tcb->xcp.saved_eip = up_current_regs()[REG_EIP];
{ tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver;
{ up_current_regs()[REG_EFLAGS] = 0;
/* 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]; /* And make sure that the saved context in the TCB
tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS]; * is the same as the interrupt return context.
*/
/* Then set up to vector to the trampoline with interrupts x86_savestate(tcb->xcp.regs);
* disabled
*/
up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver;
up_current_regs()[REG_EFLAGS] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
x86_savestate(tcb->xcp.regs);
}
} }
/* Otherwise, we are (1) signaling a task is not running /* Otherwise, we are (1) signaling a task is not running
@@ -77,38 +77,20 @@ 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 /* Save the return lr and cpsr and one scratch register
* to task that is currently executing on any CPU. * These will be restored by the signal trampoline after
* the signals have been delivered.
*/ */
if (tcb == this_task() && !up_interrupt_context()) tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
{ tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
(tcb->sigdeliver)(tcb); tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
tcb->sigdeliver = NULL;
}
/* Otherwise, we are (1) signaling a task is not running from an /* Then set up to vector to the trampoline with interrupts
* interrupt handler or (2) we are not in an interrupt handler and the * disabled
* running task is signaling some other non-running task.
*/ */
else tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
{ tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
/* Save the return lr and cpsr and one scratch register tcb->xcp.regs[REG_RFLAGS] = 0;
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/
tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
} }
+26 -44
View File
@@ -85,62 +85,44 @@ 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 /* Save the context registers. These will be restored by the
* to task that is currently executing on any CPU. * signal trampoline after the signals have been delivered.
*
* NOTE: that hi-priority interrupts are not disabled.
*/ */
if (tcb == this_task() && !up_interrupt_context()) tcb->xcp.saved_regs = tcb->xcp.regs;
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
(tcb->sigdeliver)(tcb); if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0)
tcb->sigdeliver = NULL; {
tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK;
} }
else
{
/* 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; /* Duplicate the register context. These will be
* restored by the signal trampoline after the signal has been
* delivered.
*/
if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) tcb->xcp.regs = (void *)
{ ((uint32_t)tcb->xcp.regs -
tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; XCPTCONTEXT_SIZE);
} memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
/* Duplicate the register context. These will be tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs +
* restored by the signal trampoline after the signal has been XCPTCONTEXT_SIZE;
* delivered.
*/
tcb->xcp.regs = (void *) /* Then set up to vector to the trampoline with interrupts
((uint32_t)tcb->xcp.regs - * disabled
XCPTCONTEXT_SIZE); */
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver;
XCPTCONTEXT_SIZE;
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
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
}
} }
+16 -37
View File
@@ -87,50 +87,29 @@ 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 FAR uint32_t *current_pc =
* a task is signalling itself for some reason. (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.
*/ */
if (!up_current_regs()) tcb->xcp.saved_pc = *current_pc;
{ tcb->xcp.saved_i = up_current_regs()[REG_FLAGS];
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* Then set up to vector to the trampoline with interrupts
tcb->sigdeliver = NULL; * disabled
}
/* 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 *current_pc = (uint32_t)z16_sigdeliver;
{ up_current_regs()[REG_FLAGS] = 0;
FAR uint32_t *current_pc =
(FAR uint32_t *)&up_current_regs()[REG_PC];
/* Save the return address and interrupt state. These will be /* And make sure that the saved context in the TCB is the
* restored by the signal trampoline after the signals have * same as the interrupt return context.
* been delivered. */
*/
tcb->xcp.saved_pc = *current_pc; z16_copystate(tcb->xcp.regs, up_current_regs());
tcb->xcp.saved_i = up_current_regs()[REG_FLAGS];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
*current_pc = (uint32_t)z16_sigdeliver;
up_current_regs()[REG_FLAGS] = 0;
/* And make sure that the saved context in the TCB is the
* same as the interrupt return context.
*/
z16_copystate(tcb->xcp.regs, up_current_regs());
}
} }
/* Otherwise, we are (1) signaling a task is not running from an /* Otherwise, we are (1) signaling a task is not running from an
+6 -27
View File
@@ -111,38 +111,17 @@ 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 /* Set up to vector to the trampoline with interrupts
* signalling itself for some reason. * disabled.
*/ */
if (!IN_INTERRUPT()) ez80_sigsetup(tcb, (chipreg_t *)IRQ_STATE());
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* And make sure that the saved context in the TCB
tcb->sigdeliver = NULL; * is the same as the interrupt return context.
}
/* 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_IRQCONTEXT(tcb);
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
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 /* Otherwise, we are (1) signaling a task is not running from an
+6 -27
View File
@@ -114,38 +114,17 @@ 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 /* Set up to vector to the trampoline with interrupts
* signalling itself for some reason. * disabled.
*/ */
if (!IN_INTERRUPT()) z180_sigsetup(tcb, IRQ_STATE());
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* And make sure that the saved context in the TCB
tcb->sigdeliver = NULL; * is the same as the interrupt return context.
}
/* 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_IRQCONTEXT(tcb);
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
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 /* Otherwise, we are (1) signaling a task is not running
+6 -27
View File
@@ -111,38 +111,17 @@ 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 /* Set up to vector to the trampoline with interrupts
* signalling itself for some reason. * disabled.
*/ */
if (!IN_INTERRUPT()) z8_sigsetup(tcb, IRQ_STATE());
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* And make sure that the saved context in the TCB
tcb->sigdeliver = NULL; * is the same as the interrupt return context.
}
/* 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_IRQCONTEXT(tcb);
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
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 /* Otherwise, we are (1) signaling a task is not running
+6 -27
View File
@@ -112,38 +112,17 @@ 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 /* Set up to vector to the trampoline with interrupts
* signalling itself for some reason. * disabled.
*/ */
if (!IN_INTERRUPT()) z80_sigsetup(tcb, IRQ_STATE());
{
/* In this case just deliver the signal now. */
(tcb->sigdeliver)(tcb); /* And make sure that the saved context in the TCB
tcb->sigdeliver = NULL; * is the same as the interrupt return context.
}
/* 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_IRQCONTEXT(tcb);
{
/* Set up to vector to the trampoline with interrupts
* disabled.
*/
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 /* Otherwise, we are (1) signaling a task is not running
+11 -1
View File
@@ -185,7 +185,17 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb,
#endif #endif
{ {
stcb->sigdeliver = nxsig_deliver; stcb->sigdeliver = nxsig_deliver;
up_schedule_sigaction(stcb); 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);
}
} }
} }
} }