Skip to content

Commit

Permalink
[arm64] add hw thread self (#8942)
Browse files Browse the repository at this point in the history
* [libcpu] arm64: Add hardware thread_self support

This patch introduces hardware-based thread self-identification
for the AArch64 architecture. It optimizes thread management by
using hardware registers to store and access the current thread's
pointer, reducing overhead and improving overall performance.

Changes include:
- Added `ARCH_USING_HW_THREAD_SELF` configuration option.
- Modified `rtdef.h`, `rtsched.h` to conditionally include
  `critical_switch_flag` based on the new config.
- Updated context management in `context_gcc.S`, `cpuport.h`
  to support hardware-based thread self.
- Enhanced `scheduler_mp.c` and `thread.c` to leverage the new
  hardware thread self feature.

These modifications ensure better scheduling and thread handling,
particularly in multi-core environments, by minimizing the
software overhead associated with thread management.

Signed-off-by: Shell <smokewood@qq.com>

* fixup: address suggestion

* fixup: rt_current_thread as global

* scheduler: add cpu object for UP scheduler

Also, maintain the rt_current_thread in cpu object on UP scheduler.

---------

Signed-off-by: Shell <smokewood@qq.com>
  • Loading branch information
polarvid committed May 28, 2024
1 parent b45fb59 commit f17f994
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 80 deletions.
15 changes: 13 additions & 2 deletions include/rtdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -740,8 +740,10 @@ struct rt_cpu
struct rt_thread *current_thread;

rt_uint8_t irq_switch_flag:1;
rt_uint8_t critical_switch_flag:1;
rt_uint8_t sched_lock_flag:1;
#ifndef ARCH_USING_HW_THREAD_SELF
rt_uint8_t critical_switch_flag:1;
#endif /* ARCH_USING_HW_THREAD_SELF */

rt_uint8_t current_priority;
rt_list_t priority_table[RT_THREAD_PRIORITY_MAX];
Expand All @@ -763,10 +765,19 @@ struct rt_cpu
struct rt_cpu_usage_stats cpu_stat;
#endif
};
typedef struct rt_cpu *rt_cpu_t;

#else /* !RT_USING_SMP */
struct rt_cpu
{
struct rt_thread *current_thread;
};

#endif /* RT_USING_SMP */

typedef struct rt_cpu *rt_cpu_t;
/* Noted: As API to reject writing to this variable from application codes */
#define rt_current_thread rt_thread_self()

struct rt_thread;

#ifdef RT_USING_SMART
Expand Down
5 changes: 5 additions & 0 deletions include/rtsched.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ struct rt_sched_thread_ctx
rt_uint8_t sched_flag_locked:1; /**< calling thread have the scheduler locked */
rt_uint8_t sched_flag_ttmr_set:1; /**< thread timer is start */

#ifdef ARCH_USING_HW_THREAD_SELF
rt_uint8_t critical_switch_flag:1; /**< critical switch pending */
#endif /* ARCH_USING_HW_THREAD_SELF */

#ifdef RT_USING_SMP
rt_uint8_t bind_cpu; /**< thread is bind to cpu */
rt_uint8_t oncpu; /**< process on cpu */
Expand Down Expand Up @@ -170,6 +174,7 @@ rt_err_t rt_sched_thread_timer_stop(struct rt_thread *thread);
rt_err_t rt_sched_thread_timer_start(struct rt_thread *thread);
void rt_sched_insert_thread(struct rt_thread *thread);
void rt_sched_remove_thread(struct rt_thread *thread);
struct rt_thread *rt_sched_thread_self(void);

#endif /* defined(__RT_KERNEL_SOURCE__) || defined(__RT_IPC_SOURCE__) */

Expand Down
9 changes: 6 additions & 3 deletions include/rtthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,12 @@ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg);
void rt_interrupt_enter(void);
void rt_interrupt_leave(void);

/**
* CPU object
*/
struct rt_cpu *rt_cpu_self(void);
struct rt_cpu *rt_cpu_index(int index);

#ifdef RT_USING_SMP

/*
Expand All @@ -679,9 +685,6 @@ rt_base_t rt_cpus_lock(void);
void rt_cpus_unlock(rt_base_t level);
void rt_cpus_lock_status_restore(struct rt_thread *thread);

struct rt_cpu *rt_cpu_self(void);
struct rt_cpu *rt_cpu_index(int index);

#ifdef RT_USING_DEBUG
rt_base_t rt_cpu_get_id(void);
#else /* !RT_USING_DEBUG */
Expand Down
6 changes: 6 additions & 0 deletions libcpu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ if ARCH_ARMV8 && ARCH_CPU_64BIT
default y
config ARCH_USING_GENERIC_CPUID
bool "Using generic cpuid implemenation"
select ARCH_USING_HW_THREAD_SELF
default y if RT_USING_OFW
default n
endmenu
endif
Expand Down Expand Up @@ -270,3 +272,7 @@ config ARCH_HOST_SIMULATOR
config ARCH_CPU_STACK_GROWS_UPWARD
bool
default n

config ARCH_USING_HW_THREAD_SELF
bool
default n
33 changes: 27 additions & 6 deletions libcpu/aarch64/common/context_gcc.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* 2021-05-18 Jesven the first version
* 2023-06-24 WangXiaoyao Support backtrace for user thread
* 2024-01-06 Shell Fix barrier on irq_disable/enable
* 2024-01-18 Shell fix implicit dependency of cpuid management
*/

#ifndef __ASSEMBLY__
Expand All @@ -27,15 +28,35 @@ rt_thread_switch_interrupt_flag: .zero 8
#endif

.text
.weak rt_hw_cpu_id_set

/**
* #ifdef RT_USING_OFW
* void rt_hw_cpu_id_set(long cpuid)
* #else
* void rt_hw_cpu_id_set(void)
* #endif
*/
.type rt_hw_cpu_id_set, @function
rt_hw_cpu_id_set:
mrs x0, mpidr_el1 /* MPIDR_EL1: Multi-Processor Affinity Register */
#ifdef ARCH_USING_GENERIC_CPUID
.globl rt_hw_cpu_id_set
#else /* !ARCH_USING_GENERIC_CPUID */
.weak rt_hw_cpu_id_set
#endif /* ARCH_USING_GENERIC_CPUID */

#ifndef RT_USING_OFW
mrs x0, mpidr_el1 /* MPIDR_EL1: Multi-Processor Affinity Register */
#ifdef ARCH_ARM_CORTEX_A55
lsr x0, x0, #8
#endif
and x0, x0, #15
msr tpidr_el1, x0
lsr x0, x0, #8
#endif /* ARCH_ARM_CORTEX_A55 */
and x0, x0, #15
#endif /* !RT_USING_OFW */

#ifdef ARCH_USING_HW_THREAD_SELF
msr tpidrro_el0, x0
#else /* !ARCH_USING_HW_THREAD_SELF */
msr tpidr_el1, x0
#endif /* ARCH_USING_HW_THREAD_SELF */
ret

/*
Expand Down
18 changes: 18 additions & 0 deletions libcpu/aarch64/common/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,24 @@ int rt_hw_cpu_boot_secondary(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_o

#endif /*RT_USING_SMP*/

/**
* Generic hw-cpu-id
*/
#ifdef ARCH_USING_GENERIC_CPUID

int rt_hw_cpu_id(void)
{
#if RT_CPUS_NR > 1
long cpuid;
__asm__ volatile("mrs %0, tpidrro_el0":"=r"(cpuid));
return cpuid;
#else
return 0;
#endif /* RT_CPUS_NR > 1 */
}

#endif /* ARCH_USING_GENERIC_CPUID */

/**
* @addtogroup ARM CPU
*/
Expand Down
42 changes: 17 additions & 25 deletions libcpu/aarch64/common/cpuport.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Date Author Notes
* 2023-10-25 Shell Move ffs to cpuport, add general implementation
* by inline assembly
* 2024-01-18 Shell support rt_hw_thread_self to improve overall performance
*/

#ifndef CPUPORT_H__
Expand All @@ -27,31 +28,6 @@ typedef struct
rt_uint32_t value;
} rt_hw_spinlock_t;

/**
* Generic hw-cpu-id
*/
#ifdef ARCH_USING_GENERIC_CPUID

#if RT_CPUS_NR > 1

rt_inline int rt_hw_cpu_id(void)
{
long cpuid;
__asm__ volatile("mrs %0, tpidr_el1":"=r"(cpuid));
return cpuid;
}

#else

rt_inline int rt_hw_cpu_id(void)
{
return 0;
}

#endif /* RT_CPUS_NR > 1 */

#endif /* ARCH_USING_GENERIC_CPUID */

#endif /* RT_USING_SMP */

#define rt_hw_barrier(cmd, ...) \
Expand Down Expand Up @@ -107,4 +83,20 @@ rt_inline int __rt_ffs(int value)

#endif /* RT_USING_CPU_FFS */

#ifdef ARCH_USING_HW_THREAD_SELF
rt_inline struct rt_thread *rt_hw_thread_self(void)
{
struct rt_thread *thread;
__asm__ volatile ("mrs %0, tpidr_el1":"=r"(thread));

return thread;
}

rt_inline void rt_hw_thread_set_self(struct rt_thread *thread)
{
__asm__ volatile ("msr tpidr_el1, %0"::"r"(thread));
}

#endif /* ARCH_USING_HW_THREAD_SELF */

#endif /*CPUPORT_H__*/
12 changes: 8 additions & 4 deletions libcpu/aarch64/cortex-a/entry_point.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* 2020-01-15 bigmagic the first version
* 2020-08-10 SummerGift support clang compiler
* 2023-04-29 GuEe-GUI support kernel's ARM64 boot header
* 2024-01-18 Shell fix implicit dependency of cpuid management
*/

#ifndef __ASSEMBLY__
Expand Down Expand Up @@ -95,6 +96,10 @@ _start:
/* Save cpu stack */
get_phy stack_top, .boot_cpu_stack_top
/* Save cpu id temp */
#ifdef ARCH_USING_HW_THREAD_SELF
msr tpidrro_el0, xzr
/* Save thread self */
#endif /* ARCH_USING_HW_THREAD_SELF */
msr tpidr_el1, xzr

bl init_cpu_el
Expand Down Expand Up @@ -149,11 +154,10 @@ _secondary_cpu_entry:

/* Get cpu id success */
sub x0, x2, #1
msr tpidr_el1, x0 /* Save cpu id global */
#else
bl rt_hw_cpu_id_set
mrs x0, tpidr_el1
#endif /* RT_USING_OFW */
/* Save cpu id global */
bl rt_hw_cpu_id_set
bl rt_hw_cpu_id

/* Set current cpu's stack top */
sub x0, x0, #1
Expand Down
26 changes: 26 additions & 0 deletions src/cpu_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
* Change Logs:
* Date Author Notes
* 2024-04-19 Shell Fixup UP irq spinlock
* 2024-05-22 Shell Add UP cpu object and
* maintain the rt_current_thread inside it
*/
#include <rthw.h>
#include <rtthread.h>

static struct rt_cpu _cpu;

/**
* @brief Initialize a static spinlock object.
*
Expand Down Expand Up @@ -80,3 +84,25 @@ void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
rt_exit_critical_safe(critical_level);
rt_hw_interrupt_enable(level);
}

/**
* @brief This fucntion will return current cpu object.
*
* @return Return a pointer to the current cpu object.
*/
struct rt_cpu *rt_cpu_self(void)
{
return &_cpu;
}

/**
* @brief This fucntion will return the cpu object corresponding to index.
*
* @param index is the index of target cpu object.
*
* @return Return a pointer to the cpu object corresponding to index.
*/
struct rt_cpu *rt_cpu_index(int index)
{
return index == 0 ? &_cpu : RT_NULL;
}
Loading

0 comments on commit f17f994

Please sign in to comment.