Skip to content

Commit f17f994

Browse files
authored
[arm64] add hw thread self (#8942)
* [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 <[email protected]> * 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 <[email protected]>
1 parent b45fb59 commit f17f994

File tree

12 files changed

+211
-80
lines changed

12 files changed

+211
-80
lines changed

include/rtdef.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,10 @@ struct rt_cpu
740740
struct rt_thread *current_thread;
741741

742742
rt_uint8_t irq_switch_flag:1;
743-
rt_uint8_t critical_switch_flag:1;
744743
rt_uint8_t sched_lock_flag:1;
744+
#ifndef ARCH_USING_HW_THREAD_SELF
745+
rt_uint8_t critical_switch_flag:1;
746+
#endif /* ARCH_USING_HW_THREAD_SELF */
745747

746748
rt_uint8_t current_priority;
747749
rt_list_t priority_table[RT_THREAD_PRIORITY_MAX];
@@ -763,10 +765,19 @@ struct rt_cpu
763765
struct rt_cpu_usage_stats cpu_stat;
764766
#endif
765767
};
766-
typedef struct rt_cpu *rt_cpu_t;
768+
769+
#else /* !RT_USING_SMP */
770+
struct rt_cpu
771+
{
772+
struct rt_thread *current_thread;
773+
};
767774

768775
#endif /* RT_USING_SMP */
769776

777+
typedef struct rt_cpu *rt_cpu_t;
778+
/* Noted: As API to reject writing to this variable from application codes */
779+
#define rt_current_thread rt_thread_self()
780+
770781
struct rt_thread;
771782

772783
#ifdef RT_USING_SMART

include/rtsched.h

+5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ struct rt_sched_thread_ctx
5656
rt_uint8_t sched_flag_locked:1; /**< calling thread have the scheduler locked */
5757
rt_uint8_t sched_flag_ttmr_set:1; /**< thread timer is start */
5858

59+
#ifdef ARCH_USING_HW_THREAD_SELF
60+
rt_uint8_t critical_switch_flag:1; /**< critical switch pending */
61+
#endif /* ARCH_USING_HW_THREAD_SELF */
62+
5963
#ifdef RT_USING_SMP
6064
rt_uint8_t bind_cpu; /**< thread is bind to cpu */
6165
rt_uint8_t oncpu; /**< process on cpu */
@@ -170,6 +174,7 @@ rt_err_t rt_sched_thread_timer_stop(struct rt_thread *thread);
170174
rt_err_t rt_sched_thread_timer_start(struct rt_thread *thread);
171175
void rt_sched_insert_thread(struct rt_thread *thread);
172176
void rt_sched_remove_thread(struct rt_thread *thread);
177+
struct rt_thread *rt_sched_thread_self(void);
173178

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

include/rtthread.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,12 @@ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg);
669669
void rt_interrupt_enter(void);
670670
void rt_interrupt_leave(void);
671671

672+
/**
673+
* CPU object
674+
*/
675+
struct rt_cpu *rt_cpu_self(void);
676+
struct rt_cpu *rt_cpu_index(int index);
677+
672678
#ifdef RT_USING_SMP
673679

674680
/*
@@ -679,9 +685,6 @@ rt_base_t rt_cpus_lock(void);
679685
void rt_cpus_unlock(rt_base_t level);
680686
void rt_cpus_lock_status_restore(struct rt_thread *thread);
681687

682-
struct rt_cpu *rt_cpu_self(void);
683-
struct rt_cpu *rt_cpu_index(int index);
684-
685688
#ifdef RT_USING_DEBUG
686689
rt_base_t rt_cpu_get_id(void);
687690
#else /* !RT_USING_DEBUG */

libcpu/Kconfig

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ if ARCH_ARMV8 && ARCH_CPU_64BIT
1414
default y
1515
config ARCH_USING_GENERIC_CPUID
1616
bool "Using generic cpuid implemenation"
17+
select ARCH_USING_HW_THREAD_SELF
18+
default y if RT_USING_OFW
1719
default n
1820
endmenu
1921
endif
@@ -270,3 +272,7 @@ config ARCH_HOST_SIMULATOR
270272
config ARCH_CPU_STACK_GROWS_UPWARD
271273
bool
272274
default n
275+
276+
config ARCH_USING_HW_THREAD_SELF
277+
bool
278+
default n

libcpu/aarch64/common/context_gcc.S

+27-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* 2021-05-18 Jesven the first version
99
* 2023-06-24 WangXiaoyao Support backtrace for user thread
1010
* 2024-01-06 Shell Fix barrier on irq_disable/enable
11+
* 2024-01-18 Shell fix implicit dependency of cpuid management
1112
*/
1213

1314
#ifndef __ASSEMBLY__
@@ -27,15 +28,35 @@ rt_thread_switch_interrupt_flag: .zero 8
2728
#endif
2829

2930
.text
30-
.weak rt_hw_cpu_id_set
31+
32+
/**
33+
* #ifdef RT_USING_OFW
34+
* void rt_hw_cpu_id_set(long cpuid)
35+
* #else
36+
* void rt_hw_cpu_id_set(void)
37+
* #endif
38+
*/
3139
.type rt_hw_cpu_id_set, @function
3240
rt_hw_cpu_id_set:
33-
mrs x0, mpidr_el1 /* MPIDR_EL1: Multi-Processor Affinity Register */
41+
#ifdef ARCH_USING_GENERIC_CPUID
42+
.globl rt_hw_cpu_id_set
43+
#else /* !ARCH_USING_GENERIC_CPUID */
44+
.weak rt_hw_cpu_id_set
45+
#endif /* ARCH_USING_GENERIC_CPUID */
46+
47+
#ifndef RT_USING_OFW
48+
mrs x0, mpidr_el1 /* MPIDR_EL1: Multi-Processor Affinity Register */
3449
#ifdef ARCH_ARM_CORTEX_A55
35-
lsr x0, x0, #8
36-
#endif
37-
and x0, x0, #15
38-
msr tpidr_el1, x0
50+
lsr x0, x0, #8
51+
#endif /* ARCH_ARM_CORTEX_A55 */
52+
and x0, x0, #15
53+
#endif /* !RT_USING_OFW */
54+
55+
#ifdef ARCH_USING_HW_THREAD_SELF
56+
msr tpidrro_el0, x0
57+
#else /* !ARCH_USING_HW_THREAD_SELF */
58+
msr tpidr_el1, x0
59+
#endif /* ARCH_USING_HW_THREAD_SELF */
3960
ret
4061

4162
/*

libcpu/aarch64/common/cpu.c

+18
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,24 @@ int rt_hw_cpu_boot_secondary(int num_cpus, rt_uint64_t *cpu_hw_ids, struct cpu_o
231231

232232
#endif /*RT_USING_SMP*/
233233

234+
/**
235+
* Generic hw-cpu-id
236+
*/
237+
#ifdef ARCH_USING_GENERIC_CPUID
238+
239+
int rt_hw_cpu_id(void)
240+
{
241+
#if RT_CPUS_NR > 1
242+
long cpuid;
243+
__asm__ volatile("mrs %0, tpidrro_el0":"=r"(cpuid));
244+
return cpuid;
245+
#else
246+
return 0;
247+
#endif /* RT_CPUS_NR > 1 */
248+
}
249+
250+
#endif /* ARCH_USING_GENERIC_CPUID */
251+
234252
/**
235253
* @addtogroup ARM CPU
236254
*/

libcpu/aarch64/common/cpuport.h

+17-25
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Date Author Notes
88
* 2023-10-25 Shell Move ffs to cpuport, add general implementation
99
* by inline assembly
10+
* 2024-01-18 Shell support rt_hw_thread_self to improve overall performance
1011
*/
1112

1213
#ifndef CPUPORT_H__
@@ -27,31 +28,6 @@ typedef struct
2728
rt_uint32_t value;
2829
} rt_hw_spinlock_t;
2930

30-
/**
31-
* Generic hw-cpu-id
32-
*/
33-
#ifdef ARCH_USING_GENERIC_CPUID
34-
35-
#if RT_CPUS_NR > 1
36-
37-
rt_inline int rt_hw_cpu_id(void)
38-
{
39-
long cpuid;
40-
__asm__ volatile("mrs %0, tpidr_el1":"=r"(cpuid));
41-
return cpuid;
42-
}
43-
44-
#else
45-
46-
rt_inline int rt_hw_cpu_id(void)
47-
{
48-
return 0;
49-
}
50-
51-
#endif /* RT_CPUS_NR > 1 */
52-
53-
#endif /* ARCH_USING_GENERIC_CPUID */
54-
5531
#endif /* RT_USING_SMP */
5632

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

10884
#endif /* RT_USING_CPU_FFS */
10985

86+
#ifdef ARCH_USING_HW_THREAD_SELF
87+
rt_inline struct rt_thread *rt_hw_thread_self(void)
88+
{
89+
struct rt_thread *thread;
90+
__asm__ volatile ("mrs %0, tpidr_el1":"=r"(thread));
91+
92+
return thread;
93+
}
94+
95+
rt_inline void rt_hw_thread_set_self(struct rt_thread *thread)
96+
{
97+
__asm__ volatile ("msr tpidr_el1, %0"::"r"(thread));
98+
}
99+
100+
#endif /* ARCH_USING_HW_THREAD_SELF */
101+
110102
#endif /*CPUPORT_H__*/

libcpu/aarch64/cortex-a/entry_point.S

+8-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* 2020-01-15 bigmagic the first version
88
* 2020-08-10 SummerGift support clang compiler
99
* 2023-04-29 GuEe-GUI support kernel's ARM64 boot header
10+
* 2024-01-18 Shell fix implicit dependency of cpuid management
1011
*/
1112

1213
#ifndef __ASSEMBLY__
@@ -95,6 +96,10 @@ _start:
9596
/* Save cpu stack */
9697
get_phy stack_top, .boot_cpu_stack_top
9798
/* Save cpu id temp */
99+
#ifdef ARCH_USING_HW_THREAD_SELF
100+
msr tpidrro_el0, xzr
101+
/* Save thread self */
102+
#endif /* ARCH_USING_HW_THREAD_SELF */
98103
msr tpidr_el1, xzr
99104

100105
bl init_cpu_el
@@ -149,11 +154,10 @@ _secondary_cpu_entry:
149154

150155
/* Get cpu id success */
151156
sub x0, x2, #1
152-
msr tpidr_el1, x0 /* Save cpu id global */
153-
#else
154-
bl rt_hw_cpu_id_set
155-
mrs x0, tpidr_el1
156157
#endif /* RT_USING_OFW */
158+
/* Save cpu id global */
159+
bl rt_hw_cpu_id_set
160+
bl rt_hw_cpu_id
157161

158162
/* Set current cpu's stack top */
159163
sub x0, x0, #1

src/cpu_up.c

+26
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
* Change Logs:
77
* Date Author Notes
88
* 2024-04-19 Shell Fixup UP irq spinlock
9+
* 2024-05-22 Shell Add UP cpu object and
10+
* maintain the rt_current_thread inside it
911
*/
1012
#include <rthw.h>
1113
#include <rtthread.h>
1214

15+
static struct rt_cpu _cpu;
16+
1317
/**
1418
* @brief Initialize a static spinlock object.
1519
*
@@ -80,3 +84,25 @@ void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
8084
rt_exit_critical_safe(critical_level);
8185
rt_hw_interrupt_enable(level);
8286
}
87+
88+
/**
89+
* @brief This fucntion will return current cpu object.
90+
*
91+
* @return Return a pointer to the current cpu object.
92+
*/
93+
struct rt_cpu *rt_cpu_self(void)
94+
{
95+
return &_cpu;
96+
}
97+
98+
/**
99+
* @brief This fucntion will return the cpu object corresponding to index.
100+
*
101+
* @param index is the index of target cpu object.
102+
*
103+
* @return Return a pointer to the cpu object corresponding to index.
104+
*/
105+
struct rt_cpu *rt_cpu_index(int index)
106+
{
107+
return index == 0 ? &_cpu : RT_NULL;
108+
}

0 commit comments

Comments
 (0)