You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
6.3 KiB
264 lines
6.3 KiB
/* |
|
* Copyright (c) 2016 Wind River Systems, Inc. |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_STRUCTS_H_ |
|
#define ZEPHYR_KERNEL_INCLUDE_KERNEL_STRUCTS_H_ |
|
|
|
#include <kernel.h> |
|
|
|
#if !defined(_ASMLANGUAGE) |
|
#include <sys/atomic.h> |
|
#include <sys/dlist.h> |
|
#include <sys/rb.h> |
|
#include <sys/util.h> |
|
#include <string.h> |
|
#endif |
|
|
|
#define K_NUM_PRIORITIES \ |
|
(CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES + 1) |
|
|
|
#define K_NUM_PRIO_BITMAPS ((K_NUM_PRIORITIES + 31) >> 5) |
|
|
|
/* |
|
* Bitmask definitions for the struct k_thread.thread_state field. |
|
* |
|
* Must be before kerneL_arch_data.h because it might need them to be already |
|
* defined. |
|
*/ |
|
|
|
/* states: common uses low bits, arch-specific use high bits */ |
|
|
|
/* Not a real thread */ |
|
#define _THREAD_DUMMY (BIT(0)) |
|
|
|
/* Thread is waiting on an object */ |
|
#define _THREAD_PENDING (BIT(1)) |
|
|
|
/* Thread has not yet started */ |
|
#define _THREAD_PRESTART (BIT(2)) |
|
|
|
/* Thread has terminated */ |
|
#define _THREAD_DEAD (BIT(3)) |
|
|
|
/* Thread is suspended */ |
|
#define _THREAD_SUSPENDED (BIT(4)) |
|
|
|
/* Thread is being aborted (SMP only) */ |
|
#define _THREAD_ABORTING (BIT(5)) |
|
|
|
/* Thread is present in the ready queue */ |
|
#define _THREAD_QUEUED (BIT(6)) |
|
|
|
/* end - states */ |
|
|
|
#ifdef CONFIG_STACK_SENTINEL |
|
/* Magic value in lowest bytes of the stack */ |
|
#define STACK_SENTINEL 0xF0F0F0F0 |
|
#endif |
|
|
|
/* lowest value of _thread_base.preempt at which a thread is non-preemptible */ |
|
#define _NON_PREEMPT_THRESHOLD 0x0080 |
|
|
|
/* highest value of _thread_base.preempt at which a thread is preemptible */ |
|
#define _PREEMPT_THRESHOLD (_NON_PREEMPT_THRESHOLD - 1) |
|
|
|
#include <kernel_arch_data.h> |
|
|
|
#if !defined(_ASMLANGUAGE) |
|
|
|
struct _ready_q { |
|
#ifndef CONFIG_SMP |
|
/* always contains next thread to run: cannot be NULL */ |
|
struct k_thread *cache; |
|
#endif |
|
|
|
#if defined(CONFIG_SCHED_DUMB) |
|
sys_dlist_t runq; |
|
#elif defined(CONFIG_SCHED_SCALABLE) |
|
struct _priq_rb runq; |
|
#elif defined(CONFIG_SCHED_MULTIQ) |
|
struct _priq_mq runq; |
|
#endif |
|
}; |
|
|
|
typedef struct _ready_q _ready_q_t; |
|
|
|
struct _cpu { |
|
/* nested interrupt count */ |
|
u32_t nested; |
|
|
|
/* interrupt stack pointer base */ |
|
char *irq_stack; |
|
|
|
/* currently scheduled thread */ |
|
struct k_thread *current; |
|
|
|
/* one assigned idle thread per CPU */ |
|
struct k_thread *idle_thread; |
|
|
|
#ifdef CONFIG_USERSPACE |
|
/* current syscall frame pointer */ |
|
void *syscall_frame; |
|
#endif |
|
|
|
#ifdef CONFIG_TIMESLICING |
|
/* number of ticks remaining in current time slice */ |
|
int slice_ticks; |
|
#endif |
|
|
|
u8_t id; |
|
|
|
#ifdef CONFIG_SMP |
|
/* True when _current is allowed to context switch */ |
|
u8_t swap_ok; |
|
#endif |
|
}; |
|
|
|
typedef struct _cpu _cpu_t; |
|
|
|
struct z_kernel { |
|
/* For compatibility with pre-SMP code, union the first CPU |
|
* record with the legacy fields so code can continue to use |
|
* the "_kernel.XXX" expressions and assembly offsets. |
|
*/ |
|
union { |
|
struct _cpu cpus[CONFIG_MP_NUM_CPUS]; |
|
#ifndef CONFIG_SMP |
|
struct { |
|
/* nested interrupt count */ |
|
u32_t nested; |
|
|
|
/* interrupt stack pointer base */ |
|
char *irq_stack; |
|
|
|
/* currently scheduled thread */ |
|
struct k_thread *current; |
|
}; |
|
#endif |
|
}; |
|
|
|
#ifdef CONFIG_SYS_CLOCK_EXISTS |
|
/* queue of timeouts */ |
|
sys_dlist_t timeout_q; |
|
#endif |
|
|
|
#ifdef CONFIG_SYS_POWER_MANAGEMENT |
|
s32_t idle; /* Number of ticks for kernel idling */ |
|
#endif |
|
|
|
/* |
|
* ready queue: can be big, keep after small fields, since some |
|
* assembly (e.g. ARC) are limited in the encoding of the offset |
|
*/ |
|
struct _ready_q ready_q; |
|
|
|
#ifdef CONFIG_FP_SHARING |
|
/* |
|
* A 'current_sse' field does not exist in addition to the 'current_fp' |
|
* field since it's not possible to divide the IA-32 non-integer |
|
* registers into 2 distinct blocks owned by differing threads. In |
|
* other words, given that the 'fxnsave/fxrstor' instructions |
|
* save/restore both the X87 FPU and XMM registers, it's not possible |
|
* for a thread to only "own" the XMM registers. |
|
*/ |
|
|
|
/* thread that owns the FP regs */ |
|
struct k_thread *current_fp; |
|
#endif |
|
|
|
#if defined(CONFIG_THREAD_MONITOR) |
|
struct k_thread *threads; /* singly linked list of ALL threads */ |
|
#endif |
|
}; |
|
|
|
typedef struct z_kernel _kernel_t; |
|
|
|
extern struct z_kernel _kernel; |
|
|
|
#ifdef CONFIG_SMP |
|
#define _current_cpu (z_arch_curr_cpu()) |
|
#define _current (z_arch_curr_cpu()->current) |
|
#else |
|
#define _current_cpu (&_kernel.cpus[0]) |
|
#define _current _kernel.current |
|
#endif |
|
|
|
#define _timeout_q _kernel.timeout_q |
|
|
|
#include <kernel_arch_func.h> |
|
|
|
#ifdef CONFIG_USE_SWITCH |
|
/* This is a arch function traditionally, but when the switch-based |
|
* z_swap() is in use it's a simple inline provided by the kernel. |
|
*/ |
|
static ALWAYS_INLINE void |
|
z_arch_thread_return_value_set(struct k_thread *thread, unsigned int value) |
|
{ |
|
thread->swap_retval = value; |
|
} |
|
#endif |
|
|
|
static ALWAYS_INLINE void |
|
z_thread_return_value_set_with_data(struct k_thread *thread, |
|
unsigned int value, |
|
void *data) |
|
{ |
|
z_arch_thread_return_value_set(thread, value); |
|
thread->base.swap_data = data; |
|
} |
|
|
|
extern void z_init_thread_base(struct _thread_base *thread_base, |
|
int priority, u32_t initial_state, |
|
unsigned int options); |
|
|
|
static ALWAYS_INLINE void z_new_thread_init(struct k_thread *thread, |
|
char *pStack, size_t stackSize, |
|
int prio, unsigned int options) |
|
{ |
|
#if !defined(CONFIG_INIT_STACKS) && !defined(CONFIG_THREAD_STACK_INFO) |
|
ARG_UNUSED(pStack); |
|
ARG_UNUSED(stackSize); |
|
#endif |
|
|
|
#ifdef CONFIG_INIT_STACKS |
|
memset(pStack, 0xaa, stackSize); |
|
#endif |
|
#ifdef CONFIG_STACK_SENTINEL |
|
/* Put the stack sentinel at the lowest 4 bytes of the stack area. |
|
* We periodically check that it's still present and kill the thread |
|
* if it isn't. |
|
*/ |
|
*((u32_t *)pStack) = STACK_SENTINEL; |
|
#endif /* CONFIG_STACK_SENTINEL */ |
|
/* Initialize various struct k_thread members */ |
|
z_init_thread_base(&thread->base, prio, _THREAD_PRESTART, options); |
|
|
|
/* static threads overwrite it afterwards with real value */ |
|
thread->init_data = NULL; |
|
thread->fn_abort = NULL; |
|
|
|
#ifdef CONFIG_THREAD_CUSTOM_DATA |
|
/* Initialize custom data field (value is opaque to kernel) */ |
|
thread->custom_data = NULL; |
|
#endif |
|
|
|
#ifdef CONFIG_THREAD_NAME |
|
thread->name[0] = '\0'; |
|
#endif |
|
|
|
#if defined(CONFIG_USERSPACE) |
|
thread->mem_domain_info.mem_domain = NULL; |
|
#endif /* CONFIG_USERSPACE */ |
|
|
|
#if defined(CONFIG_THREAD_STACK_INFO) |
|
thread->stack_info.start = (uintptr_t)pStack; |
|
thread->stack_info.size = (u32_t)stackSize; |
|
#endif /* CONFIG_THREAD_STACK_INFO */ |
|
} |
|
|
|
#endif /* _ASMLANGUAGE */ |
|
|
|
#endif /* ZEPHYR_KERNEL_INCLUDE_KERNEL_STRUCTS_H_ */
|
|
|