From 3944b0cfc7f9f7a9d31479f2a2bd5a89e6ca82a5 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Fri, 9 Jan 2026 13:42:26 -0800 Subject: [PATCH] kernel: Extend thread user_options to 16 bits Upgrades the thread user_options to 16 bits from an 8-bit value to provide more space for future values. Also, as the size of this field has changed, the values for the existing architecture specific thread options have also shifted from the upper end of the old 8-bit field, to the upper end of the new 16-bit field. Fixes #101034 Signed-off-by: Peter Mitsis --- arch/arc/core/thread.c | 4 ++-- arch/arm/core/cortex_a_r/swap_helper.S | 4 ++-- arch/riscv/core/switch.S | 2 +- arch/x86/core/ia32/float.c | 2 +- arch/x86/core/ia32/swap.S | 8 ++++---- include/zephyr/kernel.h | 6 +++--- include/zephyr/kernel/thread.h | 12 ++++-------- kernel/thread.c | 2 +- scripts/coredump/gdbstubs/gdbstub.py | 8 ++++---- 9 files changed, 22 insertions(+), 26 deletions(-) diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 387f983780b..38aee491202 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -318,7 +318,7 @@ void arc_dsp_disable(struct k_thread *thread, unsigned int options) k_spinlock_key_t key = k_spin_lock(&lock); /* Disable DSP or AGU capabilities for the thread */ - thread->base.user_options &= ~(uint8_t)options; + thread->base.user_options &= ~(uint16_t)options; k_spin_unlock(&lock, key); } @@ -329,7 +329,7 @@ void arc_dsp_enable(struct k_thread *thread, unsigned int options) k_spinlock_key_t key = k_spin_lock(&lock); /* Enable dsp or agu capabilities for the thread */ - thread->base.user_options |= (uint8_t)options; + thread->base.user_options |= (uint16_t)options; k_spin_unlock(&lock, key); } diff --git a/arch/arm/core/cortex_a_r/swap_helper.S b/arch/arm/core/cortex_a_r/swap_helper.S index 04b19f0b046..9417073f311 100644 --- a/arch/arm/core/cortex_a_r/swap_helper.S +++ b/arch/arm/core/cortex_a_r/swap_helper.S @@ -69,7 +69,7 @@ SECTION_FUNC(TEXT, z_arm_do_swap) cps #MODE_SVC #if defined(CONFIG_FPU_SHARING) - ldrb r0, [r2, #_thread_offset_to_user_options] + ldrh r0, [r2, #_thread_offset_to_user_options] tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ beq out_fp_inactive @@ -151,7 +151,7 @@ out_fp_inactive: cps #MODE_SVC #if defined(CONFIG_FPU_SHARING) - ldrb r0, [r2, #_thread_offset_to_user_options] + ldrh r0, [r2, #_thread_offset_to_user_options] tst r0, #K_FP_REGS /* _current->base.user_options & K_FP_REGS */ beq in_fp_inactive diff --git a/arch/riscv/core/switch.S b/arch/riscv/core/switch.S index 81292748f83..b78289af68b 100644 --- a/arch/riscv/core/switch.S +++ b/arch/riscv/core/switch.S @@ -73,7 +73,7 @@ SECTION_FUNC(TEXT, z_riscv_switch) * in effect while in m-mode. (it is done on every exception return * otherwise). */ - lb t0, _thread_offset_to_user_options(a0) + lh t0, _thread_offset_to_user_options(a0) andi t0, t0, K_USER beqz t0, not_user_task mv s0, a0 diff --git a/arch/x86/core/ia32/float.c b/arch/x86/core/ia32/float.c index 9b6f4daa18e..8219dc7593b 100644 --- a/arch/x86/core/ia32/float.c +++ b/arch/x86/core/ia32/float.c @@ -179,7 +179,7 @@ void z_float_enable(struct k_thread *thread, unsigned int options) /* Indicate thread requires floating point context saving */ - thread->base.user_options |= (uint8_t)options; + thread->base.user_options |= (uint16_t)options; /* * The current thread might not allow FP instructions, so clear CR0[TS] * so we can use them. (CR0[TS] gets restored later on, if necessary.) diff --git a/arch/x86/core/ia32/swap.S b/arch/x86/core/ia32/swap.S index 4baa0070b9b..f3433bfd0f0 100644 --- a/arch/x86/core/ia32/swap.S +++ b/arch/x86/core/ia32/swap.S @@ -175,7 +175,7 @@ SECTION_FUNC(PINNED_TEXT, arch_swap) * _and_ whether the thread was context switched out preemptively. */ - testb $_FP_USER_MASK, _thread_offset_to_user_options(%eax) + testw $_FP_USER_MASK, _thread_offset_to_user_options(%eax) je restoreContext_NoFloatSwap @@ -216,7 +216,7 @@ SECTION_FUNC(PINNED_TEXT, arch_swap) #ifdef CONFIG_X86_SSE - testb $K_SSE_REGS, _thread_offset_to_user_options(%ebx) + testw $K_SSE_REGS, _thread_offset_to_user_options(%ebx) je x87FloatSave /* @@ -255,7 +255,7 @@ restoreContext_NoFloatSave: je restoreContext_NoFloatRestore #ifdef CONFIG_X86_SSE - testb $K_SSE_REGS, _thread_offset_to_user_options(%eax) + testw $K_SSE_REGS, _thread_offset_to_user_options(%eax) je x87FloatRestore fxrstor _thread_offset_to_preempFloatReg(%eax) @@ -290,7 +290,7 @@ restoreContext_NoFloatSwap: * registers */ - testb $_FP_USER_MASK, _thread_offset_to_user_options(%eax) + testw $_FP_USER_MASK, _thread_offset_to_user_options(%eax) jne CROHandlingDone /* diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index a27a4049242..bfde2db1100 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -322,7 +322,7 @@ void k_thread_foreach_unlocked_filter_by_cpu(unsigned int cpu, * restore the contents of these registers when scheduling the thread. * No effect if @kconfig{CONFIG_DSP_SHARING} is not enabled. */ -#define K_DSP_IDX 6 +#define K_DSP_IDX 13 #define K_DSP_REGS (BIT(K_DSP_IDX)) /** @@ -333,7 +333,7 @@ void k_thread_foreach_unlocked_filter_by_cpu(unsigned int cpu, * memory and DSP feature. Often used with @kconfig{CONFIG_ARC_AGU_SHARING}. * No effect if @kconfig{CONFIG_ARC_AGU_SHARING} is not enabled. */ -#define K_AGU_IDX 7 +#define K_AGU_IDX 14 #define K_AGU_REGS (BIT(K_AGU_IDX)) /** @@ -345,7 +345,7 @@ void k_thread_foreach_unlocked_filter_by_cpu(unsigned int cpu, * save and restore the contents of these registers when scheduling * the thread. No effect if @kconfig{CONFIG_X86_SSE} is not enabled. */ -#define K_SSE_REGS (BIT(7)) +#define K_SSE_REGS (BIT(15)) /* end - thread options */ diff --git a/include/zephyr/kernel/thread.h b/include/zephyr/kernel/thread.h index 3dd40355bc2..46d32a388d4 100644 --- a/include/zephyr/kernel/thread.h +++ b/include/zephyr/kernel/thread.h @@ -57,10 +57,7 @@ struct _thread_base { _wait_q_t *pended_on; /* user facing 'thread options'; values defined in include/zephyr/kernel.h */ - uint8_t user_options; - - /* thread state */ - uint8_t thread_state; + uint16_t user_options; /* * scheduler lock count and thread priority @@ -97,6 +94,9 @@ struct _thread_base { uint32_t order_key; #endif + /* thread state */ + uint8_t thread_state; + #ifdef CONFIG_SMP /* True for the per-CPU idle threads */ uint8_t is_idle; @@ -111,11 +111,7 @@ struct _thread_base { #ifdef CONFIG_SCHED_CPU_MASK /* "May run on" bits for each CPU */ -#if CONFIG_MP_MAX_NUM_CPUS <= 8 - uint8_t cpu_mask; -#else uint16_t cpu_mask; -#endif /* CONFIG_MP_MAX_NUM_CPUS */ #endif /* CONFIG_SCHED_CPU_MASK */ /* data returned by APIs */ diff --git a/kernel/thread.c b/kernel/thread.c index 97efd493c9c..a9dc945a12e 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -881,7 +881,7 @@ void z_init_thread_base(struct _thread_base *thread_base, int priority, { /* k_q_node is initialized upon first insertion in a list */ thread_base->pended_on = NULL; - thread_base->user_options = (uint8_t)options; + thread_base->user_options = (uint16_t)options; thread_base->thread_state = (uint8_t)initial_state; thread_base->prio = priority; diff --git a/scripts/coredump/gdbstubs/gdbstub.py b/scripts/coredump/gdbstubs/gdbstub.py index e5499607389..b277bd2d163 100644 --- a/scripts/coredump/gdbstubs/gdbstub.py +++ b/scripts/coredump/gdbstubs/gdbstub.py @@ -279,11 +279,11 @@ class GdbStub(abc.ABC): t_user_options_offset = self.elffile.get_kernel_thread_info_offset( ThreadInfoOffset.THREAD_INFO_OFFSET_T_USER_OPTIONS ) - thread_user_options_byte = self.get_memory( - thread_ptr + t_user_options_offset, 1 + thread_user_options_halfword = self.get_memory( + thread_ptr + t_user_options_offset, 2 ) - if thread_user_options_byte is not None: - thread_user_options = int.from_bytes(thread_user_options_byte, "little") + if thread_user_options_halfword is not None: + thread_user_options = int.from_bytes(thread_user_options_halfword, "little") thread_info_bytes += b', user_options: ' + bytes( hex(thread_user_options), 'ascii' )