sched: replace sync pause with async pause for nxtask_terminate

reason:
In the kernel, we are planning to remove all occurrences of up_cpu_pause as one of the steps to
simplify the implementation of critical sections. The goal is to enable spin_lock_irqsave to encapsulate critical sections,
thereby facilitating the replacement of critical sections(big lock) with smaller spin_lock_irqsave(small lock)

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5 2024-09-29 19:52:57 +08:00 committed by Mateusz Szafoni
parent cdb5a7c6d4
commit 33e30239f1
23 changed files with 91 additions and 143 deletions

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -60,12 +60,6 @@ void up_exit(int status)
struct tcb_s *tcb = this_task();
UNUSED(status);
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -55,12 +55,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -54,12 +54,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts. The
* IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -54,12 +54,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -52,12 +52,6 @@ void up_exit(int status)
{
struct tcb_s *tcb;
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
(void)enter_critical_section();
/* Update scheduler parameters */
nxsched_suspend_scheduler(tcb);

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -55,12 +55,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -54,12 +54,6 @@ void up_exit(int status)
{
struct tcb_s *tcb;
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -54,12 +54,6 @@ void up_exit(int status)
{
FAR struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -56,12 +56,6 @@ void up_exit(int status)
{
FAR struct tcb_s *tcb = this_task();
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Destroy the task at the head of the ready to run list. */
nxtask_exit();

View File

@ -91,6 +91,12 @@ void nx_pthread_exit(FAR void *exit_value)
_exit(EXIT_FAILURE);
}
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Perform common task termination logic. This will get called again later
* through logic kicked off by up_exit().
*
@ -103,6 +109,8 @@ void nx_pthread_exit(FAR void *exit_value)
* once, or does something very naughty.
*/
tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
nxtask_exithook(tcb, status);
up_exit(EXIT_SUCCESS);

View File

@ -73,6 +73,12 @@ void _exit(int status)
#endif
/* Make sure that we are in a critical section with local interrupts.
* The IRQ state will be restored when the next task is started.
*/
enter_critical_section();
/* Perform common task termination logic. This will get called again later
* through logic kicked off by up_exit().
*
@ -85,6 +91,8 @@ void _exit(int status)
* once, or does something very naughty.
*/
tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
nxtask_exithook(tcb, status);
up_exit(status);

View File

@ -139,15 +139,6 @@ int nxtask_exit(void)
rtcb->task_state = TSTATE_TASK_READYTORUN;
/* Move the TCB to the specified blocked task list and delete it. Calling
* nxtask_terminate with non-blocking true will suppress atexit() and
* on-exit() calls and will cause buffered I/O to fail to be flushed. The
* former is required _exit() behavior; the latter is optional _exit()
* behavior.
*/
nxsched_add_blocked(dtcb, TSTATE_TASK_INACTIVE);
#ifdef CONFIG_SMP
/* NOTE:
* During nxtask_terminate(), enter_critical_section() will be called
@ -159,7 +150,8 @@ int nxtask_exit(void)
rtcb->irqcount++;
#endif
ret = nxtask_terminate(dtcb->pid);
dtcb->task_state = TSTATE_TASK_INACTIVE;
ret = nxsched_release_tcb(dtcb, dtcb->flags & TCB_FLAG_TTYPE_MASK);
#ifdef CONFIG_SMP
rtcb->irqcount--;

View File

@ -429,10 +429,7 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status)
* called. If that bit is set, then just exit doing nothing more..
*/
if ((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
{
return;
}
DEBUGASSERT((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0);
nxsched_dumponexit();
@ -442,12 +439,6 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status)
nxtask_recover(tcb);
/* NOTE: signal handling needs to be done in a criticl section */
#ifdef CONFIG_SMP
irqstate_t flags = enter_critical_section();
#endif
/* Disable the scheduling function to prevent other tasks from
* being deleted after they are awakened
*/
@ -484,15 +475,4 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status)
umm_memdump(&dump);
}
#endif
/* This function can be re-entered in certain cases. Set a flag
* bit in the TCB to not that we have already completed this exit
* processing.
*/
tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
#ifdef CONFIG_SMP
leave_critical_section(flags);
#endif
}

View File

@ -39,6 +39,40 @@
#include "signal/signal.h"
#include "task/task.h"
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_SMP
/****************************************************************************
* Private Functions
****************************************************************************/
static int terminat_handler(FAR void *cookie)
{
pid_t pid = (pid_t)(uintptr_t)cookie;
FAR struct tcb_s *tcb;
irqstate_t flags;
flags = enter_critical_section();
tcb = nxsched_get_tcb(pid);
if (!tcb)
{
/* There is no TCB with this pid or, if there is, it is not a task. */
leave_critical_section(flags);
return -ESRCH;
}
nxsched_remove_readytorun(tcb, false);
leave_critical_section(flags);
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -88,19 +122,52 @@ int nxtask_terminate(pid_t pid)
/* Find for the TCB associated with matching PID */
dtcb = nxsched_get_tcb(pid);
if (!dtcb)
if (!dtcb || dtcb->flags & TCB_FLAG_EXIT_PROCESSING)
{
leave_critical_section(flags);
return -ESRCH;
}
dtcb->flags |= TCB_FLAG_EXIT_PROCESSING;
/* Remove dtcb from tasklist, let remove_readtorun() do the job */
task_state = dtcb->task_state;
nxsched_remove_readytorun(dtcb, false);
dtcb->task_state = task_state;
#ifdef CONFIG_SMP
if (task_state == TSTATE_TASK_RUNNING &&
dtcb->cpu != this_cpu())
{
cpu_set_t affinity;
uint16_t tcb_flags;
int ret;
leave_critical_section(flags);
tcb_flags = dtcb->flags;
dtcb->flags |= TCB_FLAG_CPU_LOCKED;
affinity = dtcb->affinity;
CPU_SET(dtcb->cpu, &dtcb->affinity);
ret = nxsched_smp_call_single(dtcb->cpu, terminat_handler,
(FAR void *)(uintptr_t)pid,
true);
if (ret < 0)
{
/* Already terminate */
leave_critical_section(flags);
return ret;
}
dtcb->flags = tcb_flags;
dtcb->affinity = affinity;
}
else
#endif
{
nxsched_remove_readytorun(dtcb, false);
}
dtcb->task_state = task_state;
/* Perform common task termination logic. We need to do
* this as early as possible so that higher level clean-up logic
@ -111,6 +178,7 @@ int nxtask_terminate(pid_t pid)
nxtask_exithook(dtcb, EXIT_SUCCESS);
leave_critical_section(flags);
/* Since all tasks pass through this function as the final step in their
* exit sequence, this is an appropriate place to inform any
* instrumentation layer that the task no longer exists.