Skip to content

Commit

Permalink
kernel/arch: optimize memory use of some thread fields
Browse files Browse the repository at this point in the history
Some thread fields were 32-bit wide, when they are not even close to
using that full range of values. They are instead changed to 8-bit fields.

- prio can fit in one byte, limiting the priorities range to -128 to 127

- recursive scheduler locking can be limited to 255; a rollover results
  most probably from a logic error

- flags are split into execution flags and thread states; 8 bits is
  enough for each of them currently, with at worst two states and four
  flags to spare (on x86, on other archs, there are six flags to spare)

Doing this saves 8 bytes per stack. It also sets up an incoming
enhancement when checking if the current thread is preemptible on
interrupt exit.

Change-Id: Ieb5321a5b99f99173b0605dd4a193c3bc7ddabf4
Signed-off-by: Benjamin Walsh <[email protected]>
  • Loading branch information
benwrs authored and Anas Nashif committed Jan 9, 2017
1 parent 7e18ab7 commit f955476
Show file tree
Hide file tree
Showing 22 changed files with 116 additions and 83 deletions.
4 changes: 2 additions & 2 deletions arch/arc/core/fast_irq.S
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ SECTION_FUNC(TEXT, _firq_exit)
.balign 4
_firq_check_for_swap:
/* coop thread ? do not schedule */
ld_s r0, [r2, _thread_offset_to_prio]
ldb.x r0, [r2, _thread_offset_to_prio]
brlt r0, 0, _firq_no_reschedule

/* scheduler locked ? do not schedule */
ld_s r0, [r2, _thread_offset_to_sched_locked]
ldb_s r0, [r2, _thread_offset_to_sched_locked]
brne r0, 0, _firq_no_reschedule

/* Check if the current thread (in r2) is the cached thread */
Expand Down
4 changes: 2 additions & 2 deletions arch/arc/core/fault_s.S
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ _trap_return:
.balign 4
_trap_check_for_swap:
/* coop thread ? do not schedule */
ld_s r0, [r2, _thread_offset_to_prio]
ldb.x r0, [r2, _thread_offset_to_prio]
brlt r0, 0, _trap_return

/* scheduler locked ? do not schedule */
ld_s r0, [r2, _thread_offset_to_sched_locked]
ldb_s r0, [r2, _thread_offset_to_sched_locked]
brne r0, 0, _trap_return

/* check if the current thread needs to be rescheduled */
Expand Down
4 changes: 2 additions & 2 deletions arch/arc/core/regular_irq.S
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ SECTION_FUNC(TEXT, _rirq_exit)
*/

/* coop thread ? do not schedule */
ld_s r0, [r2, _thread_offset_to_prio]
ldb.x r0, [r2, _thread_offset_to_prio]
cmp_s r0, 0
blt.d _rirq_no_reschedule
ld sp, [r2, _thread_offset_to_sp]

/* scheduler locked ? do not schedule */
ld_s r0, [r2, _thread_offset_to_sched_locked]
ldb_s r0, [r2, _thread_offset_to_sched_locked]
#ifdef CONFIG_ARC_STACK_CHECKING
breq.d r0, 0, _rirq_reschedule_check
ld sp, [r2, _thread_offset_to_sp]
Expand Down
9 changes: 7 additions & 2 deletions arch/arm/core/exc_exit.S
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,13 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, _ExcExit)
ldr r0, =_kernel

ldr r1, [r0, #_kernel_offset_to_current]
ldr r2, [r1, #_thread_offset_to_prio]
ldr r3, [r1, #_thread_offset_to_sched_locked]
#ifdef CONFIG_CPU_CORTEX_M0_M0PLUS
movs r3, #_thread_offset_to_prio
ldrsb r2, [r1, r3]
#else
ldrsb r2, [r1, #_thread_offset_to_prio]
#endif
ldrb r3, [r1, #_thread_offset_to_sched_locked]

/* coop thread ? do not schedule */
cmp r2, #0
Expand Down
4 changes: 2 additions & 2 deletions arch/nios2/core/exception.S
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,11 @@ on_irq_stack:
*/

/* Do not reschedule coop threads (threads that have negative prio) */
ldw r12, _thread_offset_to_prio(r11)
ldb r12, _thread_offset_to_prio(r11)
blt r12, zero, no_reschedule

/* Do not reschedule if scheduler is locked */
ldw r12, _thread_offset_to_sched_locked(r11)
ldb r12, _thread_offset_to_sched_locked(r11)
bne r12, zero, no_reschedule

/* Call into the kernel to see if a scheduling decision is necessary */
Expand Down
6 changes: 3 additions & 3 deletions arch/x86/core/excstub.S
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ SECTION_FUNC(TEXT, _exception_enter)
* registers and the stack of the preempted thread.
*/

testl $EXC_ACTIVE, _thread_offset_to_flags(%edx)
testb $EXC_ACTIVE, _thread_offset_to_execution_flags(%edx)
jne alreadyInException
movl %esp, _thread_offset_to_esf(%edx)

Expand All @@ -151,7 +151,7 @@ alreadyInException:
* handled in the event of a context switch.
*/

orl $EXC_ACTIVE, _thread_offset_to_flags(%edx)
orb $EXC_ACTIVE, _thread_offset_to_execution_flags(%edx)

#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */

Expand Down Expand Up @@ -210,7 +210,7 @@ allDone:
* outermost exception).
*/

andl $~EXC_ACTIVE, _thread_offset_to_flags (%ecx)
andb $~EXC_ACTIVE, _thread_offset_to_execution_flags (%ecx)

nestedException:
#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */
Expand Down
12 changes: 6 additions & 6 deletions arch/x86/core/float.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ extern uint32_t _sse_mxcsr_default_value;
static void _FpCtxSave(struct tcs *tcs)
{
#ifdef CONFIG_SSE
if (tcs->base.flags & K_SSE_REGS) {
if (tcs->base.execution_flags & K_SSE_REGS) {
_do_fp_and_sse_regs_save(&tcs->arch.preempFloatReg);
return;
}
Expand All @@ -88,7 +88,7 @@ static inline void _FpCtxInit(struct tcs *tcs)
{
_do_fp_regs_init();
#ifdef CONFIG_SSE
if (tcs->base.flags & K_SSE_REGS) {
if (tcs->base.execution_flags & K_SSE_REGS) {
_do_sse_regs_init();
}
#endif
Expand All @@ -114,7 +114,7 @@ void k_float_enable(struct tcs *tcs, unsigned int options)

/* Indicate thread requires floating point context saving */

tcs->base.flags |= options;
tcs->base.execution_flags |= (uint8_t)options;

/*
* The current thread might not allow FP instructions, so clear CR0[TS]
Expand All @@ -132,7 +132,7 @@ void k_float_enable(struct tcs *tcs, unsigned int options)

fp_owner = _kernel.current_fp;
if (fp_owner) {
if (fp_owner->base.flags & INT_OR_EXC_MASK) {
if (fp_owner->base.execution_flags & INT_OR_EXC_MASK) {
_FpCtxSave(fp_owner);
}
}
Expand All @@ -158,7 +158,7 @@ void k_float_enable(struct tcs *tcs, unsigned int options)
* of the FPU to them (unless we need it ourselves).
*/

if ((_current->base.flags & _FP_USER_MASK) == 0) {
if ((_current->base.execution_flags & _FP_USER_MASK) == 0) {
/*
* We are not FP-capable, so mark FPU as owned by the
* thread we've just enabled FP support for, then
Expand Down Expand Up @@ -212,7 +212,7 @@ void k_float_disable(struct tcs *tcs)

/* Disable all floating point capabilities for the thread */

tcs->base.flags &= ~_FP_USER_MASK;
tcs->base.execution_flags &= ~_FP_USER_MASK;

if (tcs == _current) {
_FpAccessDisable();
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/core/intstub.S
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,11 @@ alreadyOnIntStack:
*/

/* do not reschedule coop threads (negative priority) */
cmpl $0, _thread_offset_to_prio(%edx)
cmpb $0, _thread_offset_to_prio(%edx)
jl noReschedule

/* do not reschedule if scheduler is locked */
cmpl $0, _thread_offset_to_sched_locked(%edx)
cmpb $0, _thread_offset_to_sched_locked(%edx)
jne noReschedule


Expand All @@ -314,7 +314,7 @@ alreadyOnIntStack:
*/

#if defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO)
orl $INT_ACTIVE, _thread_offset_to_flags(%edx)
orb $INT_ACTIVE, _thread_offset_to_execution_flags(%edx)
#endif

/*
Expand Down Expand Up @@ -362,7 +362,7 @@ alreadyOnIntStack:
*/

movl _kernel + _kernel_offset_to_current, %eax
andl $~INT_ACTIVE, _thread_offset_to_flags (%eax)
andb $~INT_ACTIVE, _thread_offset_to_execution_flags(%eax)
#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */

/* Restore volatile registers and return to the interrupted thread */
Expand Down
18 changes: 9 additions & 9 deletions arch/x86/core/swap.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
* the non-volatile integer registers need to be saved in the TCS of the
* outgoing thread. The restoration of the integer registers of the incoming
* thread depends on whether that thread was preemptively context switched out.
* The INT_ACTIVE and EXC_ACTIVE bits in the k_thread->flags field will signify
* that the thread was preemptively context switched out, and thus both the
* volatile and non-volatile integer registers need to be restored.
* The INT_ACTIVE and EXC_ACTIVE bits in the k_thread->execution_flags field
* will signify that the thread was preemptively context switched out, and thus
* both the volatile and non-volatile integer registers need to be restored.
*
* The non-volatile registers need to be scrubbed to ensure they contain no
* sensitive information that could compromise system security. This is to
Expand Down Expand Up @@ -161,7 +161,7 @@ SECTION_FUNC(TEXT, _Swap)
* _and_ whether the thread was context switched out preemptively.
*/

testl $_FP_USER_MASK, _thread_offset_to_flags(%eax)
testb $_FP_USER_MASK, _thread_offset_to_execution_flags(%eax)
je restoreContext_NoFloatSwap


Expand Down Expand Up @@ -197,12 +197,12 @@ SECTION_FUNC(TEXT, _Swap)
* was preemptively context switched.
*/

testl $INT_OR_EXC_MASK, _thread_offset_to_flags(%ebx)
testb $INT_OR_EXC_MASK, _thread_offset_to_execution_flags(%ebx)
je restoreContext_NoFloatSave


#ifdef CONFIG_SSE
testl $K_SSE_REGS, _thread_offset_to_flags(%ebx)
testb $K_SSE_REGS, _thread_offset_to_execution_flags(%ebx)
je x87FloatSave

/*
Expand Down Expand Up @@ -237,11 +237,11 @@ restoreContext_NoFloatSave:
* was previously preemptively context switched out.
*/

testl $INT_OR_EXC_MASK, _thread_offset_to_flags(%eax)
testb $INT_OR_EXC_MASK, _thread_offset_to_execution_flags(%eax)
je restoreContext_NoFloatRestore

#ifdef CONFIG_SSE
testl $K_SSE_REGS, _thread_offset_to_flags(%eax)
testb $K_SSE_REGS, _thread_offset_to_execution_flags(%eax)
je x87FloatRestore

fxrstor _thread_offset_to_preempFloatReg(%eax)
Expand Down Expand Up @@ -276,7 +276,7 @@ restoreContext_NoFloatSwap:
* registers
*/

testl $_FP_USER_MASK, _thread_offset_to_flags(%eax)
testb $_FP_USER_MASK, _thread_offset_to_execution_flags(%eax)
jne CROHandlingDone

/*
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/include/kernel_arch_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@

#define STACK_ALIGN_SIZE 4

/* x86 Bitmask definitions for the struct k_thread->flags bit field */
/* x86 Bitmask definitions for struct k_thread->execution_flags */

/* executing context is interrupt handler */
#define INT_ACTIVE (1 << 31)
#define INT_ACTIVE (1 << 7)

/* executing context is exception handler */
#define EXC_ACTIVE (1 << 30)
#define EXC_ACTIVE (1 << 6)

#define INT_OR_EXC_MASK (INT_ACTIVE | EXC_ACTIVE)

#if defined(CONFIG_FP_SHARING) && defined(CONFIG_SSE)
/* thread uses SSEx (and also FP) registers */
#define K_SSE_REGS (1 << 29)
#define K_SSE_REGS (1 << 5)
#endif

#if defined(CONFIG_FP_SHARING) && defined(CONFIG_SSE)
Expand Down
2 changes: 2 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ config NUM_COOP_PRIORITIES
prompt "Number of coop priorities" if MULTITHREADING
default 16
default 1 if !MULTITHREADING
range 0 128
help
Number of cooperative priorities configured in the system. Gives access
to priorities:
Expand Down Expand Up @@ -66,6 +67,7 @@ config NUM_PREEMPT_PRIORITIES
prompt "Number of preemptible priorities" if MULTITHREADING
default 15
default 0 if !MULTITHREADING
range 0 128
help
Number of preemptible priorities available in the system. Gives access
to priorities 0 to CONFIG_NUM_PREEMPT_PRIORITIES - 1.
Expand Down
3 changes: 2 additions & 1 deletion kernel/include/kernel_offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ GEN_OFFSET_SYM(_kernel_t, current_fp);

GEN_ABSOLUTE_SYM(_STRUCT_KERNEL_SIZE, sizeof(struct _kernel));

GEN_OFFSET_SYM(_thread_base_t, flags);
GEN_OFFSET_SYM(_thread_base_t, execution_flags);
GEN_OFFSET_SYM(_thread_base_t, thread_state);
GEN_OFFSET_SYM(_thread_base_t, prio);
GEN_OFFSET_SYM(_thread_base_t, sched_locked);
GEN_OFFSET_SYM(_thread_base_t, swap_data);
Expand Down
33 changes: 23 additions & 10 deletions kernel/include/kernel_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@
#endif

/*
* Common bitmask definitions for the struct tcs->flags bit field.
* bitmask definitions for the execution_flags and state
*
* Must be before kerneL_arch_data.h because it might need them to be already
* defined.
*/

/* thread is defined statically */
#define K_STATIC (1 << 0)

/* states: common uses low bits, arch-specific use high bits */

/* system thread that must not abort */
#define K_ESSENTIAL (1 << 0)

/* Thread is waiting on an object */
#define K_PENDING (1 << 1)
Expand All @@ -48,13 +51,20 @@
/* Not a real thread */
#define K_DUMMY (1 << 5)

/* system thread that must not abort */
#define K_ESSENTIAL (1 << 6)
/* end - states */


/* execution flags: common uses low bits, arch-specific use high bits */

/* thread is defined statically */
#define K_STATIC (1 << 0)

#if defined(CONFIG_FP_SHARING)
/* thread uses floating point registers */
#define K_FP_REGS (1 << 7)
#define K_FP_REGS (1 << 1)
#endif
/* end - execution flags */


#include <kernel_arch_data.h>

Expand All @@ -76,13 +86,16 @@ struct _thread_base {
sys_dnode_t k_q_node;

/* execution flags */
uint32_t flags;
uint8_t execution_flags;

/* thread priority used to sort linked list */
int prio;
/* thread state */
uint8_t thread_state;

/* scheduler lock count */
volatile uint32_t sched_locked;
volatile uint8_t sched_locked;

/* thread priority used to sort linked list */
int8_t prio;

/* data returned by APIs */
void *swap_data;
Expand Down
Loading

0 comments on commit f955476

Please sign in to comment.