Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

percpu reg store this_task #13726

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion arch/arm64/include/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

/****************************************************************************
GUIDINGLI marked this conversation as resolved.
Show resolved Hide resolved
* Name:
* read_/write_/zero_ sysreg
* read_/write_/zero_/modify_ sysreg
*
* Description:
*
Expand Down Expand Up @@ -84,6 +84,10 @@
::: "memory"); \
})

#define modify_sysreg(v,m,a) \
write_sysreg((read_sysreg(a) & ~(m)) | \
((uintptr_t)(v) & (m)), a)

/****************************************************************************
* Inline functions
****************************************************************************/
Expand Down
43 changes: 8 additions & 35 deletions arch/arm64/include/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,31 +382,17 @@ static inline void up_irq_restore(irqstate_t flags)
#endif /* CONFIG_ARCH_HAVE_MULTICPU */

/****************************************************************************
* Name:
* up_current_regs/up_set_current_regs
*
* Description:
* We use the following code to manipulate the tpidr_el1 register,
* which exists uniquely for each CPU and is primarily designed to store
* current thread information. Currently, we leverage it to store interrupt
* information, with plans to further optimize its use for storing both
* thread and interrupt information in the future.
* Schedule acceleration macros
*
* The lsbit of tpidr_el1 stores information about whether the current
* execution is in an interrupt context, where 1 indicates being in an
* interrupt context and 0 indicates being in a thread context.
****************************************************************************/

noinstrument_function
static inline_function uint64_t *up_current_regs(void)
{
uint64_t *regs;
__asm__ volatile ("mrs %0, " "tpidr_el1" : "=r" (regs));
return regs;
}

noinstrument_function
static inline_function void up_set_current_regs(uint64_t *regs)
{
__asm__ volatile ("msr " "tpidr_el1" ", %0" : : "r" (regs));
}
#define up_current_regs() (this_task()->xcp.regs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove up_current_regs from common code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next PR

#define up_this_task() ((struct tcb_s *)(read_sysreg(tpidr_el1) & ~1ul))
xiaoxiang781216 marked this conversation as resolved.
Show resolved Hide resolved
#define up_update_task(t) modify_sysreg(t, ~1ul, tpidr_el1)
#define up_interrupt_context() (read_sysreg(tpidr_el1) & 1)

#define up_switch_context(tcb, rtcb) \
do { \
Expand All @@ -417,19 +403,6 @@ static inline_function void up_set_current_regs(uint64_t *regs)
} \
} while (0)

/****************************************************************************
* Name: up_interrupt_context
*
* Description: Return true is we are currently executing in
* the interrupt handler context.
*
****************************************************************************/

static inline bool up_interrupt_context(void)
{
return up_current_regs() != NULL;
}

/****************************************************************************
* Name: up_getusrpc
****************************************************************************/
Expand Down
8 changes: 7 additions & 1 deletion arch/arm64/src/common/arm64_cpustart.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static inline void local_delay(void)

static void arm64_smp_init_top(void)
{
struct tcb_s *tcb = this_task();
struct tcb_s *tcb = current_task(this_cpu());

#ifndef CONFIG_SUPPRESS_INTERRUPTS
/* And finally, enable interrupts */
Expand Down Expand Up @@ -222,6 +222,12 @@ int up_cpu_start(int cpu)

void arm64_boot_secondary_c_routine(void)
{
struct tcb_s *tcb = current_task(this_cpu());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think most places use this_task(), does it not work here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it not work here,
Because we need to complete the initialization percpu before using percpu, and this is where the initialization takes place.


/* Init idle task to percpu reg */

up_update_task(tcb);

#ifdef CONFIG_ARCH_HAVE_MPU
arm64_mpu_init(false);
#endif
Expand Down
15 changes: 6 additions & 9 deletions arch/arm64/src/common/arm64_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)

/* Nested interrupts are not supported */

DEBUGASSERT(up_current_regs() == NULL);
DEBUGASSERT(!up_interrupt_context());

/* Current regs non-zero indicates that we are processing an interrupt;
* current_regs is also used to manage interrupt level context switches.
*/
/* Set irq flag */

write_sysreg((uintptr_t)tcb | 1, tpidr_el1);
xiaoxiang781216 marked this conversation as resolved.
Show resolved Hide resolved

up_set_current_regs(regs);
tcb->xcp.regs = regs;

/* Deliver the IRQ */
Expand Down Expand Up @@ -110,11 +109,9 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
regs = tcb->xcp.regs;
}

/* Set current_regs to NULL to indicate that we are no longer in an
* interrupt handler.
*/
/* Clear irq flag */

up_set_current_regs(NULL);
write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);

return regs;
}
Expand Down
15 changes: 9 additions & 6 deletions arch/arm64/src/common/arm64_fatal.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,18 @@ static int arm64_exception_handler(struct regs_context *regs)

void arm64_fatal_handler(struct regs_context *regs)
{
struct tcb_s *tcb = this_task();
int ret;

/* Nested exception are not supported */

DEBUGASSERT(up_current_regs() == NULL);
DEBUGASSERT(!up_interrupt_context());

up_set_current_regs((uint64_t *)regs);
tcb->xcp.regs = (uint64_t *)regs;

/* Set irq flag */

write_sysreg((uintptr_t)tcb | 1, tpidr_el1);

ret = arm64_exception_handler(regs);

Expand All @@ -561,11 +566,9 @@ void arm64_fatal_handler(struct regs_context *regs)
PANIC_WITH_REGS("panic", regs);
}

/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
* Exception handler.
*/
/* Clear irq flag */

up_set_current_regs(NULL);
write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
}

void arm64_register_debug_hook(int nr, fatal_handle_func_t fn)
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/src/common/arm64_registerdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>

#include "sched/sched.h"
#include "arm64_arch.h"
#include "arm64_internal.h"
#include "chip.h"
Expand Down
1 change: 1 addition & 0 deletions fs/procfs/fs_procfstcbinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <nuttx/fs/procfs.h>

#include "fs_heap.h"
#include "sched/sched.h"

#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \
defined(CONFIG_ARCH_HAVE_TCBINFO) && !defined(CONFIG_FS_PROCFS_EXCLUDE_TCBINFO)
Expand Down
37 changes: 37 additions & 0 deletions include/nuttx/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,43 @@ int up_copy_section(FAR void *dest, FAR const void *src, size_t n);
# define up_getpicbase(ppicbase)
#endif

/****************************************************************************
* Percpu support
****************************************************************************/

/****************************************************************************
* Name: up_update_task
*
* Description:
* We can utilize percpu storage to hold information about the
* current running task. If we intend to implement this feature, we would
* need to define two macros that help us manage this percpu information
* effectively.
*
* up_this_task: This macro is designed to read the contents of the percpu
* register to retrieve information about the current
* running task.This allows us to quickly access
* task-specific data without having to disable interrupts,
* access global variables and obtain the current cpu index.
*
* up_update_task: This macro is responsible for updating the contents of
* the percpu register.It is typically called during
* initialization or when a context switch occurs to ensure
* that the percpu register reflects the information of the
* newly running task.
*
* Input Parameters:
* current tcb
*
* Returned Value:
* current tcb
*
****************************************************************************/

#ifndef up_update_task
GUIDINGLI marked this conversation as resolved.
Show resolved Hide resolved
# define up_update_task(t)
#endif

/****************************************************************************
* Address Environment Interfaces
*
Expand Down
1 change: 1 addition & 0 deletions libs/libc/time/lib_localtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#include <sys/param.h>

#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/init.h>
#include <nuttx/fs/fs.h>
Expand Down
1 change: 1 addition & 0 deletions net/utils/net_snoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include <sys/param.h>

#include <nuttx/arch.h>
#include <nuttx/net/snoop.h>

/****************************************************************************
Expand Down
5 changes: 5 additions & 0 deletions sched/init/nx_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ static void idle_task_initialize(void)
/* Mark the idle task as the running task */

g_running_tasks[i] = tcb;

if (i == 0)
{
up_update_task(&g_idletcb[0]); /* Init idle task to percpu reg */
}
}
}

Expand Down
11 changes: 8 additions & 3 deletions sched/sched/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
# define current_task(cpu) ((FAR struct tcb_s *)list_assignedtasks(cpu)->head)
#else
# define current_task(cpu) ((FAR struct tcb_s *)list_readytorun()->head)
# define this_task() (current_task(this_cpu()))
#endif

#define is_idle_task(t) ((t)->pid < CONFIG_SMP_NCPUS)
Expand Down Expand Up @@ -375,7 +374,11 @@ void nxsched_sporadic_lowpriority(FAR struct tcb_s *tcb);
void nxsched_suspend(FAR struct tcb_s *tcb);
#endif

#ifdef CONFIG_SMP
#if defined(up_this_task)
# define this_task() up_this_task()
#elif !defined(CONFIG_SMP)
# define this_task() ((FAR struct tcb_s *)g_readytorun.head)
xiaoxiang781216 marked this conversation as resolved.
Show resolved Hide resolved
#else
noinstrument_function
static inline_function FAR struct tcb_s *this_task(void)
{
Expand All @@ -389,7 +392,7 @@ static inline_function FAR struct tcb_s *this_task(void)

flags = up_irq_save();

/* Obtain the TCB which is currently running on this CPU */
/* Obtain the TCB which is current running on this CPU */

tcb = current_task(this_cpu());

Expand All @@ -398,7 +401,9 @@ static inline_function FAR struct tcb_s *this_task(void)
up_irq_restore(flags);
return tcb;
}
#endif

#ifdef CONFIG_SMP
void nxsched_process_delivered(int cpu);
#else
# define nxsched_select_cpu(a) (0)
Expand Down
2 changes: 2 additions & 0 deletions sched/sched/sched_addreadytorun.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)

btcb->task_state = TSTATE_TASK_RUNNING;
btcb->flink->task_state = TSTATE_TASK_READYTORUN;
up_update_task(btcb);
ret = true;
}
else
Expand Down Expand Up @@ -269,6 +270,7 @@ bool nxsched_add_readytorun(FAR struct tcb_s *btcb)
*/

dq_addfirst_nonempty((FAR dq_entry_t *)btcb, tasklist);
up_update_task(btcb);

DEBUGASSERT(task_state == TSTATE_TASK_RUNNING);
btcb->cpu = cpu;
Expand Down
1 change: 1 addition & 0 deletions sched/sched/sched_mergepending.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ bool nxsched_merge_pending(void)
= (FAR dq_entry_t *)ptcb;
rtcb->task_state = TSTATE_TASK_READYTORUN;
ptcb->task_state = TSTATE_TASK_RUNNING;
up_update_task(ptcb);
ret = true;
}
else
Expand Down
1 change: 1 addition & 0 deletions sched/sched/sched_process_delivered.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void nxsched_process_delivered(int cpu)
dq_addfirst_nonempty((FAR dq_entry_t *)btcb, tasklist);
btcb->cpu = cpu;
btcb->task_state = TSTATE_TASK_RUNNING;
up_update_task(btcb);

DEBUGASSERT(btcb->flink != NULL);
DEBUGASSERT(next == btcb->flink);
Expand Down
1 change: 1 addition & 0 deletions sched/sched/sched_profil.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/spinlock.h>
#include "sched/sched.h"

/****************************************************************************
* Pre-processor Definitions
Expand Down
3 changes: 3 additions & 0 deletions sched/sched/sched_removereadytorun.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *rtcb)
DEBUGASSERT(nxttcb != NULL);

nxttcb->task_state = TSTATE_TASK_RUNNING;
up_update_task(nxttcb);
doswitch = true;
}

Expand Down Expand Up @@ -270,6 +271,8 @@ void nxsched_remove_running(FAR struct tcb_s *tcb)
/* Since the TCB is no longer in any list, it is now invalid */

tcb->task_state = TSTATE_TASK_INVALID;

up_update_task(nxttcb);
}

void nxsched_remove_self(FAR struct tcb_s *tcb)
Expand Down
Loading