kernel: expose struct k_thread implementation
Historically, space for struct k_thread was always carved out of the thread's stack region. However, we want more control on where this data will reside; in memory protection scenarios the stack may only be used for actual stack data and nothing else. On some platforms (particularly ARM), including kernel_arch_data.h from the toplevel kernel.h exposes intractable circular dependency issues. We create a new per-arch header "kernel_arch_thread.h" with very limited scope; it only defines the three data structures necessary to instantiate the arch-specific bits of a struct k_thread. Change-Id: I3a55b4ed4270512e58cf671f327bb033ad7f4a4f Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
94b44f03e1
commit
73abd32a7d
|
@ -28,6 +28,7 @@ extern "C" {
|
|||
#include <sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <vector_table.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
|
@ -38,16 +39,6 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Saved on the stack as part of handling a regular IRQ or by the
|
||||
* kernel when calling the FIRQ return code.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _irq_stack_frame {
|
||||
u32_t r0;
|
||||
u32_t r1;
|
||||
|
@ -83,11 +74,6 @@ struct _irq_stack_frame {
|
|||
|
||||
typedef struct _irq_stack_frame _isf_t;
|
||||
|
||||
struct _callee_saved {
|
||||
u32_t sp; /* r28 */
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
/* callee-saved registers pushed on the stack, not in k_thread */
|
||||
struct _callee_saved_stack {
|
||||
u32_t r13;
|
||||
|
@ -116,45 +102,6 @@ struct _callee_saved_stack {
|
|||
|
||||
typedef struct _callee_saved_stack _callee_saved_stack_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
/* stacks */
|
||||
|
||||
#define STACK_ALIGN_SIZE 4
|
||||
|
||||
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
||||
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
||||
|
||||
/*
|
||||
* Reason a thread has relinquished control: fibers can only be in the NONE
|
||||
* or COOP state, tasks can be one in the four.
|
||||
*/
|
||||
#define _CAUSE_NONE 0
|
||||
#define _CAUSE_COOP 1
|
||||
#define _CAUSE_RIRQ 2
|
||||
#define _CAUSE_FIRQ 3
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
/* interrupt key when relinquishing control */
|
||||
u32_t intlock_key;
|
||||
|
||||
/* one of the _CAUSE_xxxx definitions above */
|
||||
int relinquish_cause;
|
||||
|
||||
/* return value from _Swap */
|
||||
unsigned int return_value;
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* top of stack for hardware stack checking */
|
||||
u32_t stack_top;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
|
||||
char *rirq_sp; /* regular IRQ stack pointer base */
|
||||
|
@ -170,6 +117,13 @@ typedef struct _kernel_arch _kernel_arch_t;
|
|||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
/* stacks */
|
||||
|
||||
#define STACK_ALIGN_SIZE 4
|
||||
|
||||
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
||||
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
70
arch/arc/include/kernel_arch_thread.h
Normal file
70
arch/arc/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
/*
|
||||
* Reason a thread has relinquished control: fibers can only be in the NONE
|
||||
* or COOP state, tasks can be one in the four.
|
||||
*/
|
||||
#define _CAUSE_NONE 0
|
||||
#define _CAUSE_COOP 1
|
||||
#define _CAUSE_RIRQ 2
|
||||
#define _CAUSE_FIRQ 3
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Saved on the stack as part of handling a regular IRQ or by the
|
||||
* kernel when calling the FIRQ return code.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
u32_t sp; /* r28 */
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
/* interrupt key when relinquishing control */
|
||||
u32_t intlock_key;
|
||||
|
||||
/* one of the _CAUSE_xxxx definitions above */
|
||||
int relinquish_cause;
|
||||
|
||||
/* return value from _Swap */
|
||||
unsigned int return_value;
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* top of stack for hardware stack checking */
|
||||
u32_t stack_top;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
|
@ -27,6 +27,7 @@ extern "C" {
|
|||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
|
@ -38,40 +39,6 @@ extern "C" {
|
|||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Unused for Cortex-M, which automatically saves the necessary
|
||||
* registers in its exception stack frame.
|
||||
*
|
||||
* For Cortex-A, this may be:
|
||||
*
|
||||
* u32_t a1; // r0
|
||||
* u32_t a2; // r1
|
||||
* u32_t a3; // r2
|
||||
* u32_t a4; // r3
|
||||
* u32_t ip; // r12
|
||||
* u32_t lr; // r14
|
||||
* u32_t pc; // r15
|
||||
* u32_t xpsr;
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
u32_t v1; /* r4 */
|
||||
u32_t v2; /* r5 */
|
||||
u32_t v3; /* r6 */
|
||||
u32_t v4; /* r7 */
|
||||
u32_t v5; /* r8 */
|
||||
u32_t v6; /* r9 */
|
||||
u32_t v7; /* r10 */
|
||||
u32_t v8; /* r11 */
|
||||
u32_t psp; /* r13 */
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
typedef struct __esf _esf_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
@ -88,47 +55,6 @@ typedef struct __esf _esf_t;
|
|||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#ifdef CONFIG_FLOAT
|
||||
struct _preempt_float {
|
||||
float s16;
|
||||
float s17;
|
||||
float s18;
|
||||
float s19;
|
||||
float s20;
|
||||
float s21;
|
||||
float s22;
|
||||
float s23;
|
||||
float s24;
|
||||
float s25;
|
||||
float s26;
|
||||
float s27;
|
||||
float s28;
|
||||
float s29;
|
||||
float s30;
|
||||
float s31;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
/* interrupt locking key */
|
||||
u32_t basepri;
|
||||
|
||||
/* r0 in stack frame cannot be written to reliably */
|
||||
u32_t swap_return_value;
|
||||
|
||||
#ifdef CONFIG_FLOAT
|
||||
/*
|
||||
* No cooperative floating point register set structure exists for
|
||||
* the Cortex-M as it automatically saves the necessary registers
|
||||
* in its exception stack frame.
|
||||
*/
|
||||
struct _preempt_float preempt_float;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
/* empty */
|
||||
};
|
||||
|
|
103
arch/arm/include/kernel_arch_thread.h
Normal file
103
arch/arm/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread_h_
|
||||
#define _kernel_arch_thread_h_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Unused for Cortex-M, which automatically saves the necessary
|
||||
* registers in its exception stack frame.
|
||||
*
|
||||
* For Cortex-A, this may be:
|
||||
*
|
||||
* u32_t a1; // r0
|
||||
* u32_t a2; // r1
|
||||
* u32_t a3; // r2
|
||||
* u32_t a4; // r3
|
||||
* u32_t ip; // r12
|
||||
* u32_t lr; // r14
|
||||
* u32_t pc; // r15
|
||||
* u32_t xpsr;
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
u32_t v1; /* r4 */
|
||||
u32_t v2; /* r5 */
|
||||
u32_t v3; /* r6 */
|
||||
u32_t v4; /* r7 */
|
||||
u32_t v5; /* r8 */
|
||||
u32_t v6; /* r9 */
|
||||
u32_t v7; /* r10 */
|
||||
u32_t v8; /* r11 */
|
||||
u32_t psp; /* r13 */
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
#ifdef CONFIG_FLOAT
|
||||
struct _preempt_float {
|
||||
float s16;
|
||||
float s17;
|
||||
float s18;
|
||||
float s19;
|
||||
float s20;
|
||||
float s21;
|
||||
float s22;
|
||||
float s23;
|
||||
float s24;
|
||||
float s25;
|
||||
float s26;
|
||||
float s27;
|
||||
float s28;
|
||||
float s29;
|
||||
float s30;
|
||||
float s31;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
/* interrupt locking key */
|
||||
u32_t basepri;
|
||||
|
||||
/* r0 in stack frame cannot be written to reliably */
|
||||
u32_t swap_return_value;
|
||||
|
||||
#ifdef CONFIG_FLOAT
|
||||
/*
|
||||
* No cooperative floating point register set structure exists for
|
||||
* the Cortex-M as it automatically saves the necessary registers
|
||||
* in its exception stack frame.
|
||||
*/
|
||||
struct _preempt_float preempt_float;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
|
@ -28,6 +28,7 @@ extern "C" {
|
|||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
|
@ -46,52 +47,6 @@ extern "C" {
|
|||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Nothing here, the exception code puts all the caller-saved
|
||||
* registers onto the stack.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
/* General purpose callee-saved registers */
|
||||
u32_t r16;
|
||||
u32_t r17;
|
||||
u32_t r18;
|
||||
u32_t r19;
|
||||
u32_t r20;
|
||||
u32_t r21;
|
||||
u32_t r22;
|
||||
u32_t r23;
|
||||
|
||||
/* Normally used for the frame pointer but also a general purpose
|
||||
* register if frame pointers omitted
|
||||
*/
|
||||
u32_t r28;
|
||||
|
||||
/* Return address */
|
||||
u32_t ra;
|
||||
|
||||
/* Stack pointer */
|
||||
u32_t sp;
|
||||
|
||||
/* IRQ status before irq_lock() and call to _Swap() */
|
||||
u32_t key;
|
||||
|
||||
/* Return value of _Swap() */
|
||||
u32_t retval;
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
/* nothing for now */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
/* nothing for now */
|
||||
};
|
||||
|
|
75
arch/nios2/include/kernel_arch_thread.h
Normal file
75
arch/nios2/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Nothing here, the exception code puts all the caller-saved
|
||||
* registers onto the stack.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
/* General purpose callee-saved registers */
|
||||
u32_t r16;
|
||||
u32_t r17;
|
||||
u32_t r18;
|
||||
u32_t r19;
|
||||
u32_t r20;
|
||||
u32_t r21;
|
||||
u32_t r22;
|
||||
u32_t r23;
|
||||
|
||||
/* Normally used for the frame pointer but also a general purpose
|
||||
* register if frame pointers omitted
|
||||
*/
|
||||
u32_t r28;
|
||||
|
||||
/* Return address */
|
||||
u32_t ra;
|
||||
|
||||
/* Stack pointer */
|
||||
u32_t sp;
|
||||
|
||||
/* IRQ status before irq_lock() and call to _Swap() */
|
||||
u32_t key;
|
||||
|
||||
/* Return value of _Swap() */
|
||||
u32_t retval;
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
/* nothing for now */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
||||
|
|
@ -22,6 +22,7 @@ extern "C" {
|
|||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
|
@ -30,43 +31,6 @@ extern "C" {
|
|||
#include <misc/dlist.h>
|
||||
#include <nano_internal.h>
|
||||
|
||||
/*
|
||||
* The following structure defines the list of registers that need to be
|
||||
* saved/restored when a cooperative context switch occurs.
|
||||
*/
|
||||
struct _callee_saved {
|
||||
u32_t sp; /* Stack pointer, (x2 register) */
|
||||
|
||||
u32_t s0; /* saved register/frame pointer */
|
||||
u32_t s1; /* saved register */
|
||||
u32_t s2; /* saved register */
|
||||
u32_t s3; /* saved register */
|
||||
u32_t s4; /* saved register */
|
||||
u32_t s5; /* saved register */
|
||||
u32_t s6; /* saved register */
|
||||
u32_t s7; /* saved register */
|
||||
u32_t s8; /* saved register */
|
||||
u32_t s9; /* saved register */
|
||||
u32_t s10; /* saved register */
|
||||
u32_t s11; /* saved register */
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Nothing here, the exception code puts all the caller-saved
|
||||
* registers onto the stack.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
u32_t swap_return_value; /* Return value of _Swap() */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
/* nothing for now */
|
||||
};
|
||||
|
|
66
arch/riscv32/include/kernel_arch_thread.h
Normal file
66
arch/riscv32/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/*
|
||||
* The following structure defines the list of registers that need to be
|
||||
* saved/restored when a cooperative context switch occurs.
|
||||
*/
|
||||
struct _callee_saved {
|
||||
u32_t sp; /* Stack pointer, (x2 register) */
|
||||
|
||||
u32_t s0; /* saved register/frame pointer */
|
||||
u32_t s1; /* saved register */
|
||||
u32_t s2; /* saved register */
|
||||
u32_t s3; /* saved register */
|
||||
u32_t s4; /* saved register */
|
||||
u32_t s5; /* saved register */
|
||||
u32_t s6; /* saved register */
|
||||
u32_t s7; /* saved register */
|
||||
u32_t s8; /* saved register */
|
||||
u32_t s9; /* saved register */
|
||||
u32_t s10; /* saved register */
|
||||
u32_t s11; /* saved register */
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Nothing here, the exception code puts all the caller-saved
|
||||
* registers onto the stack.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
u32_t swap_return_value; /* Return value of _Swap() */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <sections.h>
|
||||
#include <asm_inline.h>
|
||||
#include <exception.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
|
@ -390,243 +391,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' integer registers.
|
||||
* These registers need not be preserved by a called C function. Given that
|
||||
* they are not preserved across function calls, they must be save/restored
|
||||
* (along with the struct _caller_saved) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
struct _caller_saved {
|
||||
|
||||
/*
|
||||
* The volatile registers 'eax', 'ecx' and 'edx' area not included in
|
||||
* the definition of 'tPreempReg' since the interrupt and exception
|
||||
* handling routunes use the stack to save and restore the values of
|
||||
* these registers in order to support interrupt nesting. The stubs
|
||||
* do _not_ copy the saved values from the stack into the TCS.
|
||||
*
|
||||
* unsigned long eax;
|
||||
* unsigned long ecx;
|
||||
* unsigned long edx;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' integer registers.
|
||||
* These registers must be preserved by a called C function. These are the
|
||||
* only registers that need to be saved/restored when a cooperative context
|
||||
* switch occurs.
|
||||
*/
|
||||
|
||||
struct _callee_saved {
|
||||
unsigned long esp;
|
||||
|
||||
/*
|
||||
* The following registers are considered non-volatile, i.e.
|
||||
* callee-save,
|
||||
* but their values are pushed onto the stack rather than stored in the
|
||||
* TCS
|
||||
* structure:
|
||||
*
|
||||
* unsigned long ebp;
|
||||
* unsigned long ebx;
|
||||
* unsigned long esi;
|
||||
* unsigned long edi;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
/*
|
||||
* The macro CONFIG_FP_SHARING shall be set to indicate that the
|
||||
* saving/restoring of the traditional x87 floating point (and MMX) registers
|
||||
* are supported by the kernel's context swapping code. The macro
|
||||
* CONFIG_SSE shall _also_ be set if saving/restoring of the XMM
|
||||
* registers is also supported in the kernel's context swapping code.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
|
||||
/* definition of a single x87 (floating point / MMX) register */
|
||||
|
||||
typedef struct s_FpReg {
|
||||
unsigned char reg[10]; /* 80 bits: ST[0-7] */
|
||||
} tFpReg;
|
||||
|
||||
/*
|
||||
* The following is the "normal" floating point register save area, or
|
||||
* more accurately the save area required by the 'fnsave' and 'frstor'
|
||||
* instructions. The structure matches the layout described in the
|
||||
* "Intel® 64 and IA-32 Architectures Software Developer’s Manual
|
||||
* Volume 1: Basic Architecture": Protected Mode x87 FPU State Image in
|
||||
* Memory, 32-Bit Format.
|
||||
*/
|
||||
|
||||
typedef struct s_FpRegSet { /* # of bytes: name of register */
|
||||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||||
unsigned short pad1; /* 2 : N/A */
|
||||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||||
unsigned short pad2; /* 2 : N/A */
|
||||
unsigned short ftw; /* 2 : x87 FPU tag word */
|
||||
unsigned short pad3; /* 2 : N/A */
|
||||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||||
unsigned short fop : 11; /* 2 : x87 FPU opcode */
|
||||
unsigned short pad4 : 5; /* : 5 bits = 00000 */
|
||||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||||
unsigned short pad5; /* 2 : N/A */
|
||||
tFpReg fpReg[8]; /* 80 : ST0 -> ST7 */
|
||||
} tFpRegSet __aligned(FP_REG_SET_ALIGN);
|
||||
|
||||
#ifdef CONFIG_SSE
|
||||
|
||||
/* definition of a single x87 (floating point / MMX) register */
|
||||
|
||||
typedef struct s_FpRegEx {
|
||||
unsigned char reg[10]; /* 80 bits: ST[0-7] or MM[0-7] */
|
||||
unsigned char rsrvd[6]; /* 48 bits: reserved */
|
||||
} tFpRegEx;
|
||||
|
||||
/* definition of a single XMM register */
|
||||
|
||||
typedef struct s_XmmReg {
|
||||
unsigned char reg[16]; /* 128 bits: XMM[0-7] */
|
||||
} tXmmReg;
|
||||
|
||||
/*
|
||||
* The following is the "extended" floating point register save area, or
|
||||
* more accurately the save area required by the 'fxsave' and 'fxrstor'
|
||||
* instructions. The structure matches the layout described in the
|
||||
* "Intel 64 and IA-32 Architectures Software Developer's Manual
|
||||
* Volume 2A: Instruction Set Reference, A-M", except for the bytes from offset
|
||||
* 464 to 511 since these "are available to software use. The processor does
|
||||
* not write to bytes 464:511 of an FXSAVE area".
|
||||
*
|
||||
* This structure must be aligned on a 16 byte boundary when the instructions
|
||||
* fxsave/fxrstor are used to write/read the data to/from the structure.
|
||||
*/
|
||||
|
||||
typedef struct s_FpRegSetEx /* # of bytes: name of register */
|
||||
{
|
||||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||||
unsigned char ftw; /* 1 : x87 FPU abridged tag word */
|
||||
unsigned char rsrvd0; /* 1 : reserved */
|
||||
unsigned short fop; /* 2 : x87 FPU opcode */
|
||||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||||
unsigned short rsrvd1; /* 2 : reserved */
|
||||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||||
unsigned short rsrvd2; /* 2 : reserved */
|
||||
unsigned int mxcsr; /* 4 : MXCSR register state */
|
||||
unsigned int mxcsrMask; /* 4 : MXCSR register mask */
|
||||
tFpRegEx fpReg[8]; /* 128 : x87 FPU/MMX registers */
|
||||
tXmmReg xmmReg[8]; /* 128 : XMM registers */
|
||||
unsigned char rsrvd3[176]; /* 176 : reserved */
|
||||
} tFpRegSetEx __aligned(FP_REG_SET_ALIGN);
|
||||
|
||||
#else /* CONFIG_SSE == 0 */
|
||||
|
||||
typedef struct s_FpRegSetEx {
|
||||
} tFpRegSetEx;
|
||||
|
||||
#endif /* CONFIG_SSE == 0 */
|
||||
|
||||
#else /* CONFIG_FP_SHARING == 0 */
|
||||
|
||||
/* empty floating point register definition */
|
||||
|
||||
typedef struct s_FpRegSet {
|
||||
} tFpRegSet;
|
||||
|
||||
typedef struct s_FpRegSetEx {
|
||||
} tFpRegSetEx;
|
||||
|
||||
#endif /* CONFIG_FP_SHARING == 0 */
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers must be preserved by a called C function.
|
||||
* These are the only registers that need to be saved/restored when a
|
||||
* cooperative context switch occurs.
|
||||
*/
|
||||
|
||||
typedef struct s_coopFloatReg {
|
||||
|
||||
/*
|
||||
* This structure intentionally left blank, i.e. the ST[0] -> ST[7] and
|
||||
* XMM0 -> XMM7 registers are all 'volatile'.
|
||||
*/
|
||||
|
||||
} tCoopFloatReg;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers need not be preserved by a called C function.
|
||||
* Given that they are not preserved across function calls, they must be
|
||||
* save/restored (along with s_coopFloatReg) when a preemptive context
|
||||
* switch occurs.
|
||||
*/
|
||||
|
||||
typedef struct s_preempFloatReg {
|
||||
union {
|
||||
/* threads with K_FP_REGS utilize this format */
|
||||
tFpRegSet fpRegs;
|
||||
/* threads with K_SSE_REGS utilize this format */
|
||||
tFpRegSetEx fpRegsEx;
|
||||
} floatRegsUnion;
|
||||
} tPreempFloatReg;
|
||||
|
||||
/*
|
||||
* The thread control stucture definition. It contains the
|
||||
* various fields to manage a _single_ thread. The TCS will be aligned
|
||||
* to the appropriate architecture specific boundary via the
|
||||
* _new_thread() call.
|
||||
*/
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
#ifdef CONFIG_GDB_INFO
|
||||
/* pointer to ESF saved by outermost exception wrapper */
|
||||
void *esf;
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO))
|
||||
/*
|
||||
* Nested exception count to maintain setting of EXC_ACTIVE flag across
|
||||
* outermost exception. EXC_ACTIVE is used by _Swap() lazy FP
|
||||
* save/restore and by debug tools.
|
||||
*/
|
||||
unsigned excNestCount; /* nested exception count */
|
||||
#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */
|
||||
|
||||
/*
|
||||
* The location of all floating point related structures/fields MUST be
|
||||
* located at the end of struct tcs. This way only the
|
||||
* fibers/tasks that actually utilize non-integer capabilities need to
|
||||
* account for the increased memory required for storing FP state when
|
||||
* sizing stacks.
|
||||
*
|
||||
* Given that stacks "grow down" on IA-32, and the TCS is located
|
||||
* at the start of a thread's "workspace" memory, the stacks of
|
||||
* fibers/tasks that do not utilize floating point instruction can
|
||||
* effectively consume the memory occupied by the 'tCoopFloatReg' and
|
||||
* 'tPreempFloatReg' structures without ill effect.
|
||||
*/
|
||||
|
||||
tCoopFloatReg coopFloatReg; /* non-volatile float register storage */
|
||||
tPreempFloatReg preempFloatReg; /* volatile float register storage */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
#if defined(CONFIG_DEBUG_INFO)
|
||||
|
|
280
arch/x86/include/kernel_arch_thread.h
Normal file
280
arch/x86/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
/**
|
||||
* Floating point register set alignment.
|
||||
*
|
||||
* If support for SSEx extensions is enabled a 16 byte boundary is required,
|
||||
* since the 'fxsave' and 'fxrstor' instructions require this. In all other
|
||||
* cases a 4 byte boundary is sufficient.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SSE
|
||||
#define FP_REG_SET_ALIGN 16
|
||||
#else
|
||||
#define FP_REG_SET_ALIGN 4
|
||||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' integer registers.
|
||||
* These registers need not be preserved by a called C function. Given that
|
||||
* they are not preserved across function calls, they must be save/restored
|
||||
* (along with the struct _caller_saved) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
struct _caller_saved {
|
||||
|
||||
/*
|
||||
* The volatile registers 'eax', 'ecx' and 'edx' area not included in
|
||||
* the definition of 'tPreempReg' since the interrupt and exception
|
||||
* handling routunes use the stack to save and restore the values of
|
||||
* these registers in order to support interrupt nesting. The stubs
|
||||
* do _not_ copy the saved values from the stack into the TCS.
|
||||
*
|
||||
* unsigned long eax;
|
||||
* unsigned long ecx;
|
||||
* unsigned long edx;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' integer registers.
|
||||
* These registers must be preserved by a called C function. These are the
|
||||
* only registers that need to be saved/restored when a cooperative context
|
||||
* switch occurs.
|
||||
*/
|
||||
|
||||
struct _callee_saved {
|
||||
unsigned long esp;
|
||||
|
||||
/*
|
||||
* The following registers are considered non-volatile, i.e.
|
||||
* callee-save,
|
||||
* but their values are pushed onto the stack rather than stored in the
|
||||
* TCS
|
||||
* structure:
|
||||
*
|
||||
* unsigned long ebp;
|
||||
* unsigned long ebx;
|
||||
* unsigned long esi;
|
||||
* unsigned long edi;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
/*
|
||||
* The macro CONFIG_FP_SHARING shall be set to indicate that the
|
||||
* saving/restoring of the traditional x87 floating point (and MMX) registers
|
||||
* are supported by the kernel's context swapping code. The macro
|
||||
* CONFIG_SSE shall _also_ be set if saving/restoring of the XMM
|
||||
* registers is also supported in the kernel's context swapping code.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
|
||||
/* definition of a single x87 (floating point / MMX) register */
|
||||
|
||||
typedef struct s_FpReg {
|
||||
unsigned char reg[10]; /* 80 bits: ST[0-7] */
|
||||
} tFpReg;
|
||||
|
||||
/*
|
||||
* The following is the "normal" floating point register save area, or
|
||||
* more accurately the save area required by the 'fnsave' and 'frstor'
|
||||
* instructions. The structure matches the layout described in the
|
||||
* "Intel® 64 and IA-32 Architectures Software Developer’s Manual
|
||||
* Volume 1: Basic Architecture": Protected Mode x87 FPU State Image in
|
||||
* Memory, 32-Bit Format.
|
||||
*/
|
||||
|
||||
typedef struct s_FpRegSet { /* # of bytes: name of register */
|
||||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||||
unsigned short pad1; /* 2 : N/A */
|
||||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||||
unsigned short pad2; /* 2 : N/A */
|
||||
unsigned short ftw; /* 2 : x87 FPU tag word */
|
||||
unsigned short pad3; /* 2 : N/A */
|
||||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||||
unsigned short fop : 11; /* 2 : x87 FPU opcode */
|
||||
unsigned short pad4 : 5; /* : 5 bits = 00000 */
|
||||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||||
unsigned short pad5; /* 2 : N/A */
|
||||
tFpReg fpReg[8]; /* 80 : ST0 -> ST7 */
|
||||
} tFpRegSet __aligned(FP_REG_SET_ALIGN);
|
||||
|
||||
#ifdef CONFIG_SSE
|
||||
|
||||
/* definition of a single x87 (floating point / MMX) register */
|
||||
|
||||
typedef struct s_FpRegEx {
|
||||
unsigned char reg[10]; /* 80 bits: ST[0-7] or MM[0-7] */
|
||||
unsigned char rsrvd[6]; /* 48 bits: reserved */
|
||||
} tFpRegEx;
|
||||
|
||||
/* definition of a single XMM register */
|
||||
|
||||
typedef struct s_XmmReg {
|
||||
unsigned char reg[16]; /* 128 bits: XMM[0-7] */
|
||||
} tXmmReg;
|
||||
|
||||
/*
|
||||
* The following is the "extended" floating point register save area, or
|
||||
* more accurately the save area required by the 'fxsave' and 'fxrstor'
|
||||
* instructions. The structure matches the layout described in the
|
||||
* "Intel 64 and IA-32 Architectures Software Developer's Manual
|
||||
* Volume 2A: Instruction Set Reference, A-M", except for the bytes from offset
|
||||
* 464 to 511 since these "are available to software use. The processor does
|
||||
* not write to bytes 464:511 of an FXSAVE area".
|
||||
*
|
||||
* This structure must be aligned on a 16 byte boundary when the instructions
|
||||
* fxsave/fxrstor are used to write/read the data to/from the structure.
|
||||
*/
|
||||
|
||||
typedef struct s_FpRegSetEx /* # of bytes: name of register */
|
||||
{
|
||||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||||
unsigned char ftw; /* 1 : x87 FPU abridged tag word */
|
||||
unsigned char rsrvd0; /* 1 : reserved */
|
||||
unsigned short fop; /* 2 : x87 FPU opcode */
|
||||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||||
unsigned short rsrvd1; /* 2 : reserved */
|
||||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||||
unsigned short rsrvd2; /* 2 : reserved */
|
||||
unsigned int mxcsr; /* 4 : MXCSR register state */
|
||||
unsigned int mxcsrMask; /* 4 : MXCSR register mask */
|
||||
tFpRegEx fpReg[8]; /* 128 : x87 FPU/MMX registers */
|
||||
tXmmReg xmmReg[8]; /* 128 : XMM registers */
|
||||
unsigned char rsrvd3[176]; /* 176 : reserved */
|
||||
} tFpRegSetEx __aligned(FP_REG_SET_ALIGN);
|
||||
|
||||
#else /* CONFIG_SSE == 0 */
|
||||
|
||||
typedef struct s_FpRegSetEx {
|
||||
} tFpRegSetEx;
|
||||
|
||||
#endif /* CONFIG_SSE == 0 */
|
||||
|
||||
#else /* CONFIG_FP_SHARING == 0 */
|
||||
|
||||
/* empty floating point register definition */
|
||||
|
||||
typedef struct s_FpRegSet {
|
||||
} tFpRegSet;
|
||||
|
||||
typedef struct s_FpRegSetEx {
|
||||
} tFpRegSetEx;
|
||||
|
||||
#endif /* CONFIG_FP_SHARING == 0 */
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers must be preserved by a called C function.
|
||||
* These are the only registers that need to be saved/restored when a
|
||||
* cooperative context switch occurs.
|
||||
*/
|
||||
|
||||
typedef struct s_coopFloatReg {
|
||||
|
||||
/*
|
||||
* This structure intentionally left blank, i.e. the ST[0] -> ST[7] and
|
||||
* XMM0 -> XMM7 registers are all 'volatile'.
|
||||
*/
|
||||
|
||||
} tCoopFloatReg;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers need not be preserved by a called C function.
|
||||
* Given that they are not preserved across function calls, they must be
|
||||
* save/restored (along with s_coopFloatReg) when a preemptive context
|
||||
* switch occurs.
|
||||
*/
|
||||
|
||||
typedef struct s_preempFloatReg {
|
||||
union {
|
||||
/* threads with K_FP_REGS utilize this format */
|
||||
tFpRegSet fpRegs;
|
||||
/* threads with K_SSE_REGS utilize this format */
|
||||
tFpRegSetEx fpRegsEx;
|
||||
} floatRegsUnion;
|
||||
} tPreempFloatReg;
|
||||
|
||||
/*
|
||||
* The thread control stucture definition. It contains the
|
||||
* various fields to manage a _single_ thread. The TCS will be aligned
|
||||
* to the appropriate architecture specific boundary via the
|
||||
* _new_thread() call.
|
||||
*/
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
#ifdef CONFIG_GDB_INFO
|
||||
/* pointer to ESF saved by outermost exception wrapper */
|
||||
void *esf;
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO))
|
||||
/*
|
||||
* Nested exception count to maintain setting of EXC_ACTIVE flag across
|
||||
* outermost exception. EXC_ACTIVE is used by _Swap() lazy FP
|
||||
* save/restore and by debug tools.
|
||||
*/
|
||||
unsigned excNestCount; /* nested exception count */
|
||||
#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */
|
||||
|
||||
/*
|
||||
* The location of all floating point related structures/fields MUST be
|
||||
* located at the end of struct tcs. This way only the
|
||||
* fibers/tasks that actually utilize non-integer capabilities need to
|
||||
* account for the increased memory required for storing FP state when
|
||||
* sizing stacks.
|
||||
*
|
||||
* Given that stacks "grow down" on IA-32, and the TCS is located
|
||||
* at the start of a thread's "workspace" memory, the stacks of
|
||||
* fibers/tasks that do not utilize floating point instruction can
|
||||
* effectively consume the memory occupied by the 'tCoopFloatReg' and
|
||||
* 'tPreempFloatReg' structures without ill effect.
|
||||
*/
|
||||
|
||||
tCoopFloatReg coopFloatReg; /* non-volatile float register storage */
|
||||
tPreempFloatReg preempFloatReg; /* volatile float register storage */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <xtensa_context.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)
|
||||
#include <kernel.h> /* public kernel API */
|
||||
|
@ -45,130 +45,8 @@ extern "C" {
|
|||
/* thread uses floating point unit */
|
||||
#define USE_FP 0x010
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' integer registers.
|
||||
* These registers need not be preserved by a called C function. Given that
|
||||
* they are not preserved across function calls, they must be save/restored
|
||||
* (along with the struct _caller_saved) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
struct _caller_saved {
|
||||
|
||||
/*
|
||||
* The volatile registers area not included in the definition of
|
||||
* 'tPreempReg' since the interrupt stubs (_IntEnt/_IntExit)
|
||||
* and exception stubs (_ExcEnt/_ExcEnter) use the stack to save and
|
||||
* restore the values of these registers in order to support interrupt
|
||||
* nesting. The stubs do _not_ copy the saved values from the stack
|
||||
* into the k_thread.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' integer registers.
|
||||
* These registers must be preserved by a called C function. These are the
|
||||
* only registers that need to be saved/restored when a cooperative context
|
||||
* switch occurs.
|
||||
*/
|
||||
struct _callee_saved {
|
||||
/*
|
||||
* The following registers are considered non-volatile, i.e.
|
||||
* callee-saved, but their values are pushed onto the stack rather than
|
||||
* stored in the k_thread structure:
|
||||
*/
|
||||
u32_t retval; /* a2 */
|
||||
XtExcFrame *topOfStack; /* a1 = sp */
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
typedef struct __esf __esf_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers must be preserved by a called C function.
|
||||
* These are the only registers that need to be saved/restored when a
|
||||
* cooperative context switch occurs.
|
||||
*/
|
||||
typedef struct s_coopCoprocReg {
|
||||
|
||||
/*
|
||||
* This structure intentionally left blank. Coprocessor's registers are
|
||||
* all 'volatile' and saved using the lazy context switch mechanism.
|
||||
*/
|
||||
|
||||
} tCoopCoprocReg;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' coprocessor
|
||||
* registers. These registers need not be preserved by a called C function.
|
||||
* Given that they are not preserved across function calls, they must be
|
||||
* save/restored (along with s_coopCoprocReg) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
typedef struct s_preempCoprocReg {
|
||||
/*
|
||||
* This structure reserves coprocessor control and save area memory.
|
||||
*/
|
||||
#if XCHAL_CP_NUM > 0
|
||||
char __aligned(4) cpStack[XT_CP_SIZE];
|
||||
#endif
|
||||
} tPreempCoprocReg;
|
||||
|
||||
/*
|
||||
* The thread control stucture definition. It contains the
|
||||
* various fields to manage a _single_ thread.
|
||||
*/
|
||||
struct _thread_arch {
|
||||
/*
|
||||
* See the above flag definitions above for valid bit settings. This
|
||||
* field must remain near the start of struct k_thread, specifically
|
||||
* before any #ifdef'ed fields since the host tools currently use a
|
||||
* fixed offset to read the 'flags' field.
|
||||
*/
|
||||
u32_t flags;
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
void *custom_data; /* available for custom use */
|
||||
#endif
|
||||
#if defined(CONFIG_THREAD_MONITOR)
|
||||
/* thread entry and parameters description */
|
||||
struct __thread_entry *entry;
|
||||
|
||||
/* next item in list of ALL threads n*/
|
||||
struct k_thread *next_thread;
|
||||
#endif
|
||||
#ifdef CONFIG_ERRNO
|
||||
int errno_var;
|
||||
#endif
|
||||
/*
|
||||
* The location of all floating point related structures/fields MUST be
|
||||
* located at the end of struct k_thread. This way only the threads
|
||||
* that actually utilize non-integer capabilities need to account for
|
||||
* the increased memory required for storing FP state when sizing
|
||||
* stacks.
|
||||
*
|
||||
* Given that stacks "grow down" on Xtensa, and the k_thread is located
|
||||
* at the start of a thread's "workspace" memory, the stacks of threads
|
||||
* that do not utilize floating point instruction can effectively
|
||||
* consume the memory occupied by the 'tCoopCoprocReg' and
|
||||
* 'tPreempCoprocReg' structures without ill effect.
|
||||
*
|
||||
* TODO: Move Xtensa coprocessor's stack here to get rid of extra
|
||||
* indirection
|
||||
*/
|
||||
|
||||
/* non-volatile coprocessor's register storage */
|
||||
tCoopCoprocReg coopCoprocReg;
|
||||
|
||||
/* volatile coprocessor's register storage */
|
||||
tPreempCoprocReg preempCoprocReg;
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
struct _kernel_arch {
|
||||
#if defined(CONFIG_DEBUG_INFO)
|
||||
NANO_ISF *isf; /* ptr to interrupt stack frame */
|
||||
|
|
153
arch/xtensa/include/kernel_arch_thread.h
Normal file
153
arch/xtensa/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
#include <xtensa_context.h>
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' integer registers.
|
||||
* These registers need not be preserved by a called C function. Given that
|
||||
* they are not preserved across function calls, they must be save/restored
|
||||
* (along with the struct _caller_saved) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
struct _caller_saved {
|
||||
|
||||
/*
|
||||
* The volatile registers area not included in the definition of
|
||||
* 'tPreempReg' since the interrupt stubs (_IntEnt/_IntExit)
|
||||
* and exception stubs (_ExcEnt/_ExcEnter) use the stack to save and
|
||||
* restore the values of these registers in order to support interrupt
|
||||
* nesting. The stubs do _not_ copy the saved values from the stack
|
||||
* into the k_thread.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' integer registers.
|
||||
* These registers must be preserved by a called C function. These are the
|
||||
* only registers that need to be saved/restored when a cooperative context
|
||||
* switch occurs.
|
||||
*/
|
||||
struct _callee_saved {
|
||||
/*
|
||||
* The following registers are considered non-volatile, i.e.
|
||||
* callee-saved, but their values are pushed onto the stack rather than
|
||||
* stored in the k_thread structure:
|
||||
*/
|
||||
u32_t retval; /* a2 */
|
||||
XtExcFrame *topOfStack; /* a1 = sp */
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers must be preserved by a called C function.
|
||||
* These are the only registers that need to be saved/restored when a
|
||||
* cooperative context switch occurs.
|
||||
*/
|
||||
typedef struct s_coopCoprocReg {
|
||||
|
||||
/*
|
||||
* This structure intentionally left blank. Coprocessor's registers are
|
||||
* all 'volatile' and saved using the lazy context switch mechanism.
|
||||
*/
|
||||
|
||||
} tCoopCoprocReg;
|
||||
|
||||
/*
|
||||
* The following structure defines the set of 'volatile' x87 FPU/MMX/SSE
|
||||
* registers. These registers need not be preserved by a called C function.
|
||||
* Given that they are not preserved across function calls, they must be
|
||||
* save/restored (along with s_coopCoprocReg) when a preemptive context switch
|
||||
* occurs.
|
||||
*/
|
||||
typedef struct s_preempCoprocReg {
|
||||
/*
|
||||
* This structure intentionally left blank, as for now coprocessor's
|
||||
* stack is positioned at top of the stack.
|
||||
*/
|
||||
#if XCHAL_CP_NUM > 0
|
||||
char *cpStack;
|
||||
#endif
|
||||
} tPreempCoprocReg;
|
||||
|
||||
/*
|
||||
* The thread control stucture definition. It contains the
|
||||
* various fields to manage a _single_ thread.
|
||||
*/
|
||||
struct _thread_arch {
|
||||
/*
|
||||
* See the above flag definitions above for valid bit settings. This
|
||||
* field must remain near the start of struct k_thread, specifically
|
||||
* before any #ifdef'ed fields since the host tools currently use a
|
||||
* fixed offset to read the 'flags' field.
|
||||
*/
|
||||
u32_t flags;
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
void *custom_data; /* available for custom use */
|
||||
#endif
|
||||
#if defined(CONFIG_THREAD_MONITOR)
|
||||
/* thread entry and parameters description */
|
||||
struct __thread_entry *entry;
|
||||
|
||||
/* next item in list of ALL threads n*/
|
||||
struct k_thread *next_thread;
|
||||
#endif
|
||||
#ifdef CONFIG_ERRNO
|
||||
int errno_var;
|
||||
#endif
|
||||
/*
|
||||
* The location of all floating point related structures/fields MUST be
|
||||
* located at the end of struct k_thread. This way only the threads
|
||||
* that actually utilize non-integer capabilities need to account for
|
||||
* the increased memory required for storing FP state when sizing
|
||||
* stacks.
|
||||
*
|
||||
* Given that stacks "grow down" on Xtensa, and the k_thread is located
|
||||
* at the start of a thread's "workspace" memory, the stacks of threads
|
||||
* that do not utilize floating point instruction can effectively
|
||||
* consume the memory occupied by the 'tCoopCoprocReg' and
|
||||
* 'tPreempCoprocReg' structures without ill effect.
|
||||
*
|
||||
* TODO: Move Xtensa coprocessor's stack here to get rid of extra
|
||||
* indirection
|
||||
*/
|
||||
|
||||
/* non-volatile coprocessor's register storage */
|
||||
tCoopCoprocReg coopCoprocReg;
|
||||
|
||||
/* volatile coprocessor's register storage */
|
||||
tPreempCoprocReg preempCoprocReg;
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <irq.h>
|
||||
#include <arch/x86/irq_controller.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <arch/x86/asm_inline.h>
|
||||
|
@ -49,20 +50,6 @@ void _int_latency_stop(void);
|
|||
|
||||
/* interrupt/exception/error related definitions */
|
||||
|
||||
/**
|
||||
* Floating point register set alignment.
|
||||
*
|
||||
* If support for SSEx extensions is enabled a 16 byte boundary is required,
|
||||
* since the 'fxsave' and 'fxrstor' instructions require this. In all other
|
||||
* cases a 4 byte boundary is sufficient.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SSE
|
||||
#define FP_REG_SET_ALIGN 16
|
||||
#else
|
||||
#define FP_REG_SET_ALIGN 4
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The TCS must be aligned to the same boundary as that used by the floating
|
||||
* point register set. This applies even for threads that don't initially
|
||||
|
|
156
include/kernel.h
156
include/kernel.h
|
@ -27,6 +27,7 @@
|
|||
#include <misc/util.h>
|
||||
#include <kernel_version.h>
|
||||
#include <drivers/rand32.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -105,7 +106,6 @@ typedef sys_dlist_t _wait_q_t;
|
|||
#define _POLL_EVENT
|
||||
#endif
|
||||
|
||||
#define tcs k_thread
|
||||
struct k_thread;
|
||||
struct k_mutex;
|
||||
struct k_sem;
|
||||
|
@ -123,7 +123,138 @@ struct k_timer;
|
|||
struct k_poll_event;
|
||||
struct k_poll_signal;
|
||||
|
||||
/* timeouts */
|
||||
|
||||
struct _timeout;
|
||||
typedef void (*_timeout_func_t)(struct _timeout *t);
|
||||
|
||||
struct _timeout {
|
||||
sys_dnode_t node;
|
||||
struct k_thread *thread;
|
||||
sys_dlist_t *wait_q;
|
||||
s32_t delta_ticks_from_prev;
|
||||
_timeout_func_t func;
|
||||
};
|
||||
|
||||
extern s32_t _timeout_remaining_get(struct _timeout *timeout);
|
||||
|
||||
/* Threads */
|
||||
typedef void (*_thread_entry_t)(void *, void *, void *);
|
||||
|
||||
#ifdef CONFIG_THREAD_MONITOR
|
||||
struct __thread_entry {
|
||||
_thread_entry_t pEntry;
|
||||
void *parameter1;
|
||||
void *parameter2;
|
||||
void *parameter3;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* can be used for creating 'dummy' threads, e.g. for pending on objects */
|
||||
struct _thread_base {
|
||||
|
||||
/* this thread's entry in a ready/wait queue */
|
||||
sys_dnode_t k_q_node;
|
||||
|
||||
/* user facing 'thread options'; values defined in include/kernel.h */
|
||||
u8_t user_options;
|
||||
|
||||
/* thread state */
|
||||
u8_t thread_state;
|
||||
|
||||
/*
|
||||
* scheduler lock count and thread priority
|
||||
*
|
||||
* These two fields control the preemptibility of a thread.
|
||||
*
|
||||
* When the scheduler is locked, sched_locked is decremented, which
|
||||
* means that the scheduler is locked for values from 0xff to 0x01. A
|
||||
* thread is coop if its prio is negative, thus 0x80 to 0xff when
|
||||
* looked at the value as unsigned.
|
||||
*
|
||||
* By putting them end-to-end, this means that a thread is
|
||||
* non-preemptible if the bundled value is greater than or equal to
|
||||
* 0x0080.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
u8_t sched_locked;
|
||||
s8_t prio;
|
||||
#else /* LITTLE and PDP */
|
||||
s8_t prio;
|
||||
u8_t sched_locked;
|
||||
#endif
|
||||
};
|
||||
u16_t preempt;
|
||||
};
|
||||
|
||||
/* data returned by APIs */
|
||||
void *swap_data;
|
||||
|
||||
#ifdef CONFIG_SYS_CLOCK_EXISTS
|
||||
/* this thread's entry in a timeout queue */
|
||||
struct _timeout timeout;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef struct _thread_base _thread_base_t;
|
||||
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* Contains the stack information of a thread */
|
||||
struct _thread_stack_info {
|
||||
/* Stack Start */
|
||||
u32_t start;
|
||||
/* Stack Size */
|
||||
u32_t size;
|
||||
};
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
struct k_thread {
|
||||
|
||||
struct _thread_base base;
|
||||
|
||||
/* defined by the architecture, but all archs need these */
|
||||
struct _caller_saved caller_saved;
|
||||
struct _callee_saved callee_saved;
|
||||
|
||||
/* static thread init data */
|
||||
void *init_data;
|
||||
|
||||
/* abort function */
|
||||
void (*fn_abort)(void);
|
||||
|
||||
#if defined(CONFIG_THREAD_MONITOR)
|
||||
/* thread entry and parameters description */
|
||||
struct __thread_entry *entry;
|
||||
|
||||
/* next item in list of all threads */
|
||||
struct k_thread *next_thread;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
/* crude thread-local storage */
|
||||
void *custom_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ERRNO
|
||||
/* per-thread errno variable */
|
||||
int errno_var;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* Stack Info */
|
||||
struct _thread_stack_info stack_info;
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
/* arch-specifics: must always be at the end */
|
||||
struct _thread_arch arch;
|
||||
};
|
||||
|
||||
typedef struct k_thread _thread_t;
|
||||
typedef struct k_thread *k_tid_t;
|
||||
#define tcs k_thread
|
||||
|
||||
enum execution_context_types {
|
||||
K_ISR = 0,
|
||||
|
@ -751,29 +882,6 @@ static inline s64_t __ticks_to_ms(s64_t ticks)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* timeouts */
|
||||
|
||||
struct _timeout;
|
||||
typedef void (*_timeout_func_t)(struct _timeout *t);
|
||||
|
||||
struct _timeout {
|
||||
sys_dnode_t node;
|
||||
struct k_thread *thread;
|
||||
sys_dlist_t *wait_q;
|
||||
s32_t delta_ticks_from_prev;
|
||||
_timeout_func_t func;
|
||||
};
|
||||
|
||||
extern s32_t _timeout_remaining_get(struct _timeout *timeout);
|
||||
|
||||
/**
|
||||
* INTERNAL_HIDDEN @endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cond INTERNAL_HIDDEN
|
||||
*/
|
||||
|
||||
struct k_timer {
|
||||
/*
|
||||
* _timeout structure must be first here if we want to use
|
||||
|
|
|
@ -56,119 +56,6 @@
|
|||
|
||||
#if !defined(_ASMLANGUAGE)
|
||||
|
||||
#ifdef CONFIG_THREAD_MONITOR
|
||||
struct __thread_entry {
|
||||
_thread_entry_t pEntry;
|
||||
void *parameter1;
|
||||
void *parameter2;
|
||||
void *parameter3;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* Contains the stack information of a thread */
|
||||
struct _thread_stack_info {
|
||||
/* Stack Start */
|
||||
u32_t start;
|
||||
/* Stack Size */
|
||||
u32_t size;
|
||||
};
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
/* can be used for creating 'dummy' threads, e.g. for pending on objects */
|
||||
struct _thread_base {
|
||||
|
||||
/* this thread's entry in a ready/wait queue */
|
||||
sys_dnode_t k_q_node;
|
||||
|
||||
/* user facing 'thread options'; values defined in include/kernel.h */
|
||||
u8_t user_options;
|
||||
|
||||
/* thread state */
|
||||
u8_t thread_state;
|
||||
|
||||
/*
|
||||
* scheduler lock count and thread priority
|
||||
*
|
||||
* These two fields control the preemptibility of a thread.
|
||||
*
|
||||
* When the scheduler is locked, sched_locked is decremented, which
|
||||
* means that the scheduler is locked for values from 0xff to 0x01. A
|
||||
* thread is coop if its prio is negative, thus 0x80 to 0xff when
|
||||
* looked at the value as unsigned.
|
||||
*
|
||||
* By putting them end-to-end, this means that a thread is
|
||||
* non-preemptible if the bundled value is greater than or equal to
|
||||
* 0x0080.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
u8_t sched_locked;
|
||||
s8_t prio;
|
||||
#else /* LITTLE and PDP */
|
||||
s8_t prio;
|
||||
u8_t sched_locked;
|
||||
#endif
|
||||
};
|
||||
u16_t preempt;
|
||||
};
|
||||
|
||||
/* data returned by APIs */
|
||||
void *swap_data;
|
||||
|
||||
#ifdef CONFIG_SYS_CLOCK_EXISTS
|
||||
/* this thread's entry in a timeout queue */
|
||||
struct _timeout timeout;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef struct _thread_base _thread_base_t;
|
||||
|
||||
struct k_thread {
|
||||
|
||||
struct _thread_base base;
|
||||
|
||||
/* defined by the architecture, but all archs need these */
|
||||
struct _caller_saved caller_saved;
|
||||
struct _callee_saved callee_saved;
|
||||
|
||||
/* static thread init data */
|
||||
void *init_data;
|
||||
|
||||
/* abort function */
|
||||
void (*fn_abort)(void);
|
||||
|
||||
#if defined(CONFIG_THREAD_MONITOR)
|
||||
/* thread entry and parameters description */
|
||||
struct __thread_entry *entry;
|
||||
|
||||
/* next item in list of all threads */
|
||||
struct k_thread *next_thread;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
/* crude thread-local storage */
|
||||
void *custom_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ERRNO
|
||||
/* per-thread errno variable */
|
||||
int errno_var;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* Stack Info */
|
||||
struct _thread_stack_info stack_info;
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
/* arch-specifics: must always be at the end */
|
||||
struct _thread_arch arch;
|
||||
};
|
||||
|
||||
typedef struct k_thread _thread_t;
|
||||
|
||||
struct _ready_q {
|
||||
|
||||
/* always contains next thread to run: cannot be NULL */
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#ifndef _NANO_INTERNAL__H_
|
||||
#define _NANO_INTERNAL__H_
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#define K_NUM_PRIORITIES \
|
||||
(CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES + 1)
|
||||
|
||||
|
@ -38,10 +40,6 @@ static inline void _data_copy(void)
|
|||
#endif
|
||||
FUNC_NORETURN void _Cstart(void);
|
||||
|
||||
/* helper type alias for thread control structure */
|
||||
|
||||
typedef void (*_thread_entry_t)(void *, void *, void *);
|
||||
|
||||
extern void _thread_entry(void (*)(void *, void *, void *),
|
||||
void *, void *, void *);
|
||||
|
||||
|
|
44
tests/ztest/include/kernel_arch_thread.h
Normal file
44
tests/ztest/include/kernel_arch_thread.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains defintions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _kernel_arch_thread__h_
|
||||
#define _kernel_arch_thread__h_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
struct _caller_saved {
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
};
|
||||
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _kernel_arch_thread__h_ */
|
||||
|
Loading…
Reference in a new issue