diff options
| author | Shell <[email protected]> | 2024-02-23 17:49:15 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-23 17:49:15 +0800 |
| commit | 71560bafb5735220696ca24a42ba4a668b55949b (patch) | |
| tree | 236df5973a1fd5b6f0cc9f6c6b6a2d71fd069203 /include | |
| parent | 6fe69d7431ed54fcea863ed68d7c4f9746e771b0 (diff) | |
🎯 Sync smart & scheduler codes (#8537)
Signed-off-by: Shell <[email protected]>
Co-authored-by: xqyjlj <[email protected]>
Diffstat (limited to 'include')
| -rw-r--r-- | include/rtcompiler.h | 100 | ||||
| -rw-r--r-- | include/rtdef.h | 296 | ||||
| -rw-r--r-- | include/rtsched.h | 172 | ||||
| -rw-r--r-- | include/rtthread.h | 33 | ||||
| -rw-r--r-- | include/rttypes.h | 223 |
5 files changed, 577 insertions, 247 deletions
diff --git a/include/rtcompiler.h b/include/rtcompiler.h new file mode 100644 index 0000000000..5084ab0065 --- /dev/null +++ b/include/rtcompiler.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-18 Shell Separate the compiler porting from rtdef.h + */ +#ifndef __RT_COMPILER_H__ +#define __RT_COMPILER_H__ + +#include <rtconfig.h> + +#if defined(__ARMCC_VERSION) /* ARM Compiler */ +#define rt_section(x) __attribute__((section(x))) +#define rt_used __attribute__((used)) +#define rt_align(n) __attribute__((aligned(n))) +#define rt_weak __attribute__((weak)) +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static __inline +#define rt_always_inline rt_inline +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ +#define rt_section(x) @ x +#define rt_used __root +#define PRAGMA(x) _Pragma(#x) +#define rt_align(n) PRAGMA(data_alignment=n) +#define rt_weak __weak +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static inline +#define rt_always_inline rt_inline +#elif defined (__GNUC__) /* GNU GCC Compiler */ +#define __RT_STRINGIFY(x...) #x +#define RT_STRINGIFY(x...) __RT_STRINGIFY(x) +#define rt_section(x) __attribute__((section(x))) +#define rt_used __attribute__((used)) +#define rt_align(n) __attribute__((aligned(n))) +#define rt_weak __attribute__((weak)) +#define rt_typeof __typeof__ +#define rt_noreturn __attribute__ ((noreturn)) +#define rt_inline static __inline +#define rt_always_inline static inline __attribute__((always_inline)) +#elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */ +#define rt_section(x) __attribute__((section(x))) +#define rt_used __attribute__((used)) +#define rt_align(n) __attribute__((aligned(n))) +#define rt_weak __attribute__((weak)) +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static inline +#define rt_always_inline rt_inline +#elif defined (_MSC_VER) /* for Visual Studio Compiler */ +#define rt_section(x) +#define rt_used +#define rt_align(n) __declspec(align(n)) +#define rt_weak +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static __inline +#define rt_always_inline rt_inline +#elif defined (__TI_COMPILER_VERSION__) /* for TI CCS Compiler */ +/** + * The way that TI compiler set section is different from other(at least + * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more + * details. + */ +#define rt_section(x) __attribute__((section(x))) +#ifdef __TI_EABI__ +#define rt_used __attribute__((retain)) __attribute__((used)) +#else +#define rt_used __attribute__((used)) +#endif +#define PRAGMA(x) _Pragma(#x) +#define rt_align(n) __attribute__((aligned(n))) +#ifdef __TI_EABI__ +#define rt_weak __attribute__((weak)) +#else +#define rt_weak +#endif +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static inline +#define rt_always_inline rt_inline +#elif defined (__TASKING__) /* for TASKING Compiler */ +#define rt_section(x) __attribute__((section(x))) +#define rt_used __attribute__((used, protect)) +#define PRAGMA(x) _Pragma(#x) +#define rt_align(n) __attribute__((__align(n))) +#define rt_weak __attribute__((weak)) +#define rt_typeof typeof +#define rt_noreturn +#define rt_inline static inline +#define rt_always_inline rt_inline +#else /* Unkown Compiler */ + #error not supported tool chain +#endif /* __ARMCC_VERSION */ + +#endif /* __RT_COMPILER_H__ */ diff --git a/include/rtdef.h b/include/rtdef.h index 88b1f630a0..c3cfd90346 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2022, RT-Thread Development Team + * Copyright (c) 2006-2024, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -55,6 +55,8 @@ * 2023-11-21 Meco Man add RT_USING_NANO macro * 2023-12-18 xqyjlj add rt_always_inline * 2023-12-22 Shell Support hook list + * 2024-01-18 Shell Seperate basical types to a rttypes.h + * Seperate the compiler portings to rtcompiler.h */ #ifndef __RT_DEF_H__ @@ -96,71 +98,7 @@ extern "C" { /* RT-Thread basic data type definitions */ -typedef int rt_bool_t; /**< boolean type */ -typedef signed long rt_base_t; /**< Nbit CPU related date type */ -typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */ - -#ifndef RT_USING_ARCH_DATA_TYPE -#ifdef RT_USING_LIBC -typedef int8_t rt_int8_t; /**< 8bit integer type */ -typedef int16_t rt_int16_t; /**< 16bit integer type */ -typedef int32_t rt_int32_t; /**< 32bit integer type */ -typedef uint8_t rt_uint8_t; /**< 8bit unsigned integer type */ -typedef uint16_t rt_uint16_t; /**< 16bit unsigned integer type */ -typedef uint32_t rt_uint32_t; /**< 32bit unsigned integer type */ -typedef int64_t rt_int64_t; /**< 64bit integer type */ -typedef uint64_t rt_uint64_t; /**< 64bit unsigned integer type */ -#else -typedef signed char rt_int8_t; /**< 8bit integer type */ -typedef signed short rt_int16_t; /**< 16bit integer type */ -typedef signed int rt_int32_t; /**< 32bit integer type */ -typedef unsigned char rt_uint8_t; /**< 8bit unsigned integer type */ -typedef unsigned short rt_uint16_t; /**< 16bit unsigned integer type */ -typedef unsigned int rt_uint32_t; /**< 32bit unsigned integer type */ -#ifdef ARCH_CPU_64BIT -typedef signed long rt_int64_t; /**< 64bit integer type */ -typedef unsigned long rt_uint64_t; /**< 64bit unsigned integer type */ -#else -typedef signed long long rt_int64_t; /**< 64bit integer type */ -typedef unsigned long long rt_uint64_t; /**< 64bit unsigned integer type */ -#endif /* ARCH_CPU_64BIT */ -#endif /* RT_USING_LIBC */ -#endif /* RT_USING_ARCH_DATA_TYPE */ - -#if defined(RT_USING_LIBC) && !defined(RT_USING_NANO) -typedef size_t rt_size_t; /**< Type for size number */ -typedef ssize_t rt_ssize_t; /**< Used for a count of bytes or an error indication */ -#else -typedef rt_ubase_t rt_size_t; /**< Type for size number */ -typedef rt_base_t rt_ssize_t; /**< Used for a count of bytes or an error indication */ -#endif /* defined(RT_USING_LIBC) && !defined(RT_USING_NANO) */ - -typedef rt_base_t rt_err_t; /**< Type for error number */ -typedef rt_uint32_t rt_time_t; /**< Type for time stamp */ -typedef rt_uint32_t rt_tick_t; /**< Type for tick count */ -typedef rt_base_t rt_flag_t; /**< Type for flags */ -typedef rt_ubase_t rt_dev_t; /**< Type for device */ -typedef rt_base_t rt_off_t; /**< Type for offset */ - -#ifdef __cplusplus - typedef rt_base_t rt_atomic_t; -#else -#if defined(RT_USING_HW_ATOMIC) - typedef rt_base_t rt_atomic_t; -#elif defined(RT_USING_STDC_ATOMIC) - #include <stdatomic.h> - typedef atomic_size_t rt_atomic_t; -#else - typedef rt_base_t rt_atomic_t; -#endif /* RT_USING_STDC_ATOMIC */ -#endif /* __cplusplus */ - -/* boolean type definitions */ -#define RT_TRUE 1 /**< boolean true */ -#define RT_FALSE 0 /**< boolean fails */ - -/* null pointer definition */ -#define RT_NULL 0 +#include "rttypes.h" /**@}*/ @@ -194,90 +132,7 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ #define RT_STATIC_ASSERT(name, expn) typedef char _static_assert_##name[(expn)?1:-1] /* Compiler Related Definitions */ -#if defined(__ARMCC_VERSION) /* ARM Compiler */ -#define rt_section(x) __attribute__((section(x))) -#define rt_used __attribute__((used)) -#define rt_align(n) __attribute__((aligned(n))) -#define rt_weak __attribute__((weak)) -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static __inline -#define rt_always_inline rt_inline -#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ -#define rt_section(x) @ x -#define rt_used __root -#define PRAGMA(x) _Pragma(#x) -#define rt_align(n) PRAGMA(data_alignment=n) -#define rt_weak __weak -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static inline -#define rt_always_inline rt_inline -#elif defined (__GNUC__) /* GNU GCC Compiler */ -#define __RT_STRINGIFY(x...) #x -#define RT_STRINGIFY(x...) __RT_STRINGIFY(x) -#define rt_section(x) __attribute__((section(x))) -#define rt_used __attribute__((used)) -#define rt_align(n) __attribute__((aligned(n))) -#define rt_weak __attribute__((weak)) -#define rt_typeof __typeof__ -#define rt_noreturn __attribute__ ((noreturn)) -#define rt_inline static __inline -#define rt_always_inline static inline __attribute__((always_inline)) -#elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */ -#define rt_section(x) __attribute__((section(x))) -#define rt_used __attribute__((used)) -#define rt_align(n) __attribute__((aligned(n))) -#define rt_weak __attribute__((weak)) -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static inline -#define rt_always_inline rt_inline -#elif defined (_MSC_VER) /* for Visual Studio Compiler */ -#define rt_section(x) -#define rt_used -#define rt_align(n) __declspec(align(n)) -#define rt_weak -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static __inline -#define rt_always_inline rt_inline -#elif defined (__TI_COMPILER_VERSION__) /* for TI CCS Compiler */ -/** - * The way that TI compiler set section is different from other(at least - * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more - * details. - */ -#define rt_section(x) __attribute__((section(x))) -#ifdef __TI_EABI__ -#define rt_used __attribute__((retain)) __attribute__((used)) -#else -#define rt_used __attribute__((used)) -#endif -#define PRAGMA(x) _Pragma(#x) -#define rt_align(n) __attribute__((aligned(n))) -#ifdef __TI_EABI__ -#define rt_weak __attribute__((weak)) -#else -#define rt_weak -#endif -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static inline -#define rt_always_inline rt_inline -#elif defined (__TASKING__) /* for TASKING Compiler */ -#define rt_section(x) __attribute__((section(x))) -#define rt_used __attribute__((used, protect)) -#define PRAGMA(x) _Pragma(#x) -#define rt_align(n) __attribute__((__align(n))) -#define rt_weak __attribute__((weak)) -#define rt_typeof typeof -#define rt_noreturn -#define rt_inline static inline -#define rt_always_inline rt_inline -#else /* Unkown Compiler */ - #error not supported tool chain -#endif /* __ARMCC_VERSION */ +#include "rtcompiler.h" /* initialization export */ #ifdef RT_USING_COMPONENTS_INIT @@ -417,6 +272,8 @@ typedef int (*init_fn_t)(void); #define RT_EPERM EPERM /**< Operation not permitted */ #define RT_EFAULT EFAULT /**< Bad address */ #define RT_ENOBUFS ENOBUFS /**< No buffer space is available */ +#define RT_ESCHEDISR 253 /**< scheduler failure in isr context */ +#define RT_ESCHEDLOCKED 252 /**< scheduler failure in critical region */ #define RT_ETRAP 254 /**< Trap event */ #else #define RT_EOK 0 /**< There is no error */ @@ -436,6 +293,8 @@ typedef int (*init_fn_t)(void); #define RT_ETRAP 14 /**< Trap event */ #define RT_EFAULT 15 /**< Bad address */ #define RT_ENOBUFS 16 /**< No buffer space is available */ +#define RT_ESCHEDISR 17 /**< scheduler failure in isr context */ +#define RT_ESCHEDLOCKED 18 /**< scheduler failure in critical region */ #endif /* defined(RT_USING_LIBC) && !defined(RT_USING_NANO) */ /**@}*/ @@ -470,53 +329,6 @@ typedef int (*init_fn_t)(void); #define RT_ALIGN_DOWN(size, align) ((size) & ~((align) - 1)) /** - * Double List structure - */ -struct rt_list_node -{ - struct rt_list_node *next; /**< point to next node. */ - struct rt_list_node *prev; /**< point to prev node. */ -}; -typedef struct rt_list_node rt_list_t; /**< Type for lists. */ - -/** - * Single List structure - */ -struct rt_slist_node -{ - struct rt_slist_node *next; /**< point to next node. */ -}; -typedef struct rt_slist_node rt_slist_t; /**< Type for single list. */ - -#ifdef RT_USING_SMP -#include <cpuport.h> /* for spinlock from arch */ - -struct rt_spinlock -{ - rt_hw_spinlock_t lock; -#if defined(RT_DEBUGING_SPINLOCK) - void *owner; - void *pc; -#endif /* RT_DEBUGING_SPINLOCK */ -}; -typedef struct rt_spinlock rt_spinlock_t; - -#ifndef RT_SPINLOCK_INIT -#define RT_SPINLOCK_INIT {{0}} // default -#endif /* RT_SPINLOCK_INIT */ - -#else -typedef rt_ubase_t rt_spinlock_t; -struct rt_spinlock -{ - rt_spinlock_t lock; -}; -#define RT_SPINLOCK_INIT {0} -#endif /* RT_USING_SMP */ - -#define RT_DEFINE_SPINLOCK(x) struct rt_spinlock x = RT_SPINLOCK_INIT - -/** * @addtogroup KernelObject */ @@ -770,6 +582,8 @@ struct rt_object_information #define RT_TIMER_FLAG_HARD_TIMER 0x0 /**< hard timer,the timer's callback function will be called in tick isr. */ #define RT_TIMER_FLAG_SOFT_TIMER 0x4 /**< soft timer,the timer's callback function will be called in timer thread. */ +#define RT_TIMER_FLAG_THREAD_TIMER \ + (0x8 | RT_TIMER_FLAG_HARD_TIMER) /**< thread timer that cooperates with scheduler directly */ #define RT_TIMER_CTRL_SET_TIME 0x0 /**< set timer control command */ #define RT_TIMER_CTRL_GET_TIME 0x1 /**< get timer control command */ @@ -792,6 +606,11 @@ struct rt_object_information #endif /** + * timeout handler of rt_timer + */ +typedef void (*rt_timer_func_t)(void *parameter); + +/** * timer structure */ struct rt_timer @@ -800,8 +619,8 @@ struct rt_timer rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; - void (*timeout_func)(void *parameter); /**< timeout function */ - void *parameter; /**< timeout function's parameter */ + rt_timer_func_t timeout_func; /**< timeout function */ + void *parameter; /**< timeout function's parameter */ rt_tick_t init_tick; /**< timer timeout tick */ rt_tick_t timeout_tick; /**< timeout tick */ @@ -901,30 +720,43 @@ struct rt_cpu_usage_stats }; typedef struct rt_cpu_usage_stats *rt_cpu_usage_stats_t; +#define _SCHEDULER_CONTEXT(fileds) fileds + /** * CPUs definitions * */ struct rt_cpu { - struct rt_thread *current_thread; - struct rt_thread *idle_thread; - rt_atomic_t irq_nest; - rt_uint8_t irq_switch_flag; + /** + * protected by: + * - other cores: accessing from other coress is undefined behaviour + * - local core: rt_enter_critical()/rt_exit_critical() + */ + _SCHEDULER_CONTEXT( + struct rt_thread *current_thread; - rt_uint8_t current_priority; - rt_list_t priority_table[RT_THREAD_PRIORITY_MAX]; -#if RT_THREAD_PRIORITY_MAX > 32 - rt_uint32_t priority_group; - rt_uint8_t ready_table[32]; -#else - rt_uint32_t priority_group; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + rt_uint8_t irq_switch_flag:1; + rt_uint8_t critical_switch_flag:1; + rt_uint8_t sched_lock_flag:1; + + rt_uint8_t current_priority; + rt_list_t priority_table[RT_THREAD_PRIORITY_MAX]; + #if RT_THREAD_PRIORITY_MAX > 32 + rt_uint32_t priority_group; + rt_uint8_t ready_table[32]; + #else + rt_uint32_t priority_group; + #endif /* RT_THREAD_PRIORITY_MAX > 32 */ - rt_atomic_t tick; + rt_atomic_t tick; /**< Passing tickes on this core */ + ); + + struct rt_thread *idle_thread; + rt_atomic_t irq_nest; - struct rt_spinlock spinlock; #ifdef RT_USING_SMART + struct rt_spinlock spinlock; struct rt_cpu_usage_stats cpu_stat; #endif }; @@ -1013,11 +845,12 @@ typedef void (*rt_thread_cleanup_t)(struct rt_thread *tid); /** * Thread structure */ + +#include "rtsched.h" /* for struct rt_sched_thread_ctx */ + struct rt_thread { struct rt_object parent; - rt_list_t tlist; /**< the thread list */ - rt_list_t tlist_schedule; /**< the thread list */ /* stack point and entry */ void *sp; /**< stack point */ @@ -1029,24 +862,13 @@ struct rt_thread /* error code */ rt_err_t error; /**< error code */ - rt_uint8_t stat; /**< thread status */ - #ifdef RT_USING_SMP - rt_uint8_t bind_cpu; /**< thread is bind to cpu */ - rt_uint8_t oncpu; /**< process on cpu */ - rt_atomic_t cpus_lock_nest; /**< cpus lock count */ - rt_atomic_t critical_lock_nest; /**< critical lock count */ -#endif /*RT_USING_SMP*/ +#endif - /* priority */ - rt_uint8_t current_priority; /**< current priority */ - rt_uint8_t init_priority; /**< initialized priority */ -#if RT_THREAD_PRIORITY_MAX > 32 - rt_uint8_t number; - rt_uint8_t high_mask; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ - rt_uint32_t number_mask; /**< priority number mask */ + RT_SCHED_THREAD_CTX; + struct rt_timer thread_timer; /**< built-in thread timer */ + rt_thread_cleanup_t cleanup; /**< cleanup function when thread exit */ #ifdef RT_USING_MUTEX /* object for IPC */ @@ -1071,9 +893,6 @@ struct rt_thread void *si_list; /**< the signal infor list */ #endif /* RT_USING_SIGNALS */ - rt_atomic_t init_tick; /**< thread's initialized tick */ - rt_atomic_t remaining_tick; /**< remaining tick */ - #ifdef RT_USING_CPU_USAGE rt_uint64_t duration_tick; /**< cpu usage tick */ #endif /* RT_USING_CPU_USAGE */ @@ -1082,10 +901,6 @@ struct rt_thread void *pthread_data; /**< the handle of pthread data, adapt 32/64bit */ #endif /* RT_USING_PTHREADS */ - struct rt_timer thread_timer; /**< built-in thread timer */ - - rt_thread_cleanup_t cleanup; /**< cleanup function when thread exit */ - /* light weight process if present */ #ifdef RT_USING_SMART void *msg_ret; /**< the return msg */ @@ -1100,11 +915,12 @@ struct rt_thread struct lwp_thread_signal signal; /**< lwp signal for user-space thread */ struct rt_user_context user_ctx; /**< user space context */ - struct rt_wakeup wakeup; /**< wakeup data */ - int exit_request; /**< pending exit request of thread */ + struct rt_wakeup wakeup_handle; /**< wakeup handle for IPC */ + rt_atomic_t exit_request; /**< pending exit request of thread */ int tid; /**< thread ID used by process */ int tid_ref_count; /**< reference of tid */ void *susp_recycler; /**< suspended recycler on this thread */ + void *robust_list; /**< pi lock, very carefully, it's a userspace list!*/ rt_uint64_t user_time; rt_uint64_t system_time; @@ -1167,7 +983,7 @@ struct rt_ipc_object { struct rt_object parent; /**< inherit from rt_object */ - rt_list_t suspend_thread; /**< threads pended on this resource */ + rt_list_t suspend_thread; /**< threads pended on this resource */ }; #ifdef RT_USING_SEMAPHORE diff --git a/include/rtsched.h b/include/rtsched.h new file mode 100644 index 0000000000..cb312e320f --- /dev/null +++ b/include/rtsched.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-19 Shell Seperate schduling statements from rt_thread_t + * to rt_sched_thread_ctx. Add definitions of scheduler. + */ +#ifndef __RT_SCHED_H__ +#define __RT_SCHED_H__ + +#include "rttypes.h" +#include "rtcompiler.h" + +struct rt_thread; + +typedef rt_uint8_t rt_sched_thread_status_t; + +#ifdef RT_USING_SCHED_THREAD_CTX + +/** + * Scheduler private status binding on thread. Caller should never accessing + * these members. + */ +struct rt_sched_thread_priv +{ + rt_tick_t init_tick; /**< thread's initialized tick */ + rt_tick_t remaining_tick; /**< remaining tick */ + + /* priority */ + rt_uint8_t current_priority; /**< current priority */ + rt_uint8_t init_priority; /**< initialized priority */ +#if RT_THREAD_PRIORITY_MAX > 32 + rt_uint8_t number; /**< priority low number */ + rt_uint8_t high_mask; /**< priority high mask */ +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + rt_uint32_t number_mask; /**< priority number mask */ + +}; + +/** + * Scheduler public status binding on thread. Caller must hold the scheduler + * lock before access any one of its member. + */ +struct rt_sched_thread_ctx +{ + rt_list_t thread_list_node; /**< node in thread list */ + + rt_uint8_t stat; /**< thread status */ + rt_uint8_t sched_flag_locked:1; /**< calling thread have the scheduler locked */ + rt_uint8_t sched_flag_ttmr_set:1; /**< thread timer is start */ + +#ifdef RT_USING_SMP + rt_uint8_t bind_cpu; /**< thread is bind to cpu */ + rt_uint8_t oncpu; /**< process on cpu */ + + rt_base_t critical_lock_nest; /**< critical lock count */ +#endif + + struct rt_sched_thread_priv sched_thread_priv; /**< private context of scheduler */ +}; + +#define RT_SCHED_THREAD_CTX struct rt_sched_thread_ctx sched_thread_ctx + +#define RT_SCHED_PRIV(thread) ((thread)->sched_thread_ctx.sched_thread_priv) +#define RT_SCHED_CTX(thread) ((thread)->sched_thread_ctx) + +/** + * Convert a list node in container RT_SCHED_CTX(thread)->thread_list_node + * to a thread pointer. + */ +#define RT_THREAD_LIST_NODE_ENTRY(node) \ + rt_container_of( \ + rt_list_entry((node), struct rt_sched_thread_ctx, thread_list_node), \ + struct rt_thread, sched_thread_ctx) +#define RT_THREAD_LIST_NODE(thread) (RT_SCHED_CTX(thread).thread_list_node) + +#else /* !defined(RT_USING_SCHED_THREAD_CTX) */ + +#if RT_THREAD_PRIORITY_MAX > 32 +#define _RT_SCHED_THREAD_CTX_PRIO_EXT \ + rt_uint8_t number; /**< priority low number */ \ + rt_uint8_t high_mask; /**< priority high mask */ + +#else /* ! RT_THREAD_PRIORITY_MAX > 32 */ + +#define _RT_SCHED_THREAD_CTX_PRIO_EXT +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + +#define RT_SCHED_THREAD_CTX \ + rt_list_t tlist; /**< node in thread list */ \ + rt_uint8_t stat; /**< thread status */ \ + rt_uint8_t sched_flag_locked:1; \ + /**< calling thread have the scheduler locked */ \ + rt_uint8_t sched_flag_ttmr_set:1; /**< thread timer is start */ \ + rt_tick_t init_tick; /**< thread's initialized tick */ \ + rt_tick_t remaining_tick; /**< remaining tick */ \ + rt_uint8_t current_priority; /**< current priority */ \ + rt_uint8_t init_priority; /**< initialized priority */ \ + _RT_SCHED_THREAD_CTX_PRIO_EXT; \ + rt_uint32_t number_mask; /**< priority number mask */ + +#define RT_SCHED_PRIV(thread) (*thread) +#define RT_SCHED_CTX(thread) (*thread) + +/** + * Convert a list node in container RT_SCHED_CTX(thread)->thread_list_node + * to a thread pointer. + */ +#define RT_THREAD_LIST_NODE_ENTRY(node) rt_list_entry((node), struct rt_thread, tlist) +#define RT_THREAD_LIST_NODE(thread) (RT_SCHED_CTX(thread).tlist) + +#endif /* RT_USING_SCHED_THREAD_CTX */ + +/** + * System Scheduler Locking + */ + +typedef rt_ubase_t rt_sched_lock_level_t; + +rt_err_t rt_sched_lock(rt_sched_lock_level_t *plvl); +rt_err_t rt_sched_unlock(rt_sched_lock_level_t level); +rt_err_t rt_sched_unlock_n_resched(rt_sched_lock_level_t level); + +rt_bool_t rt_sched_is_locked(void); + +#ifdef RT_USING_SMP +#define RT_SCHED_DEBUG_IS_LOCKED do { RT_ASSERT(rt_sched_is_locked()); } while (0) +#define RT_SCHED_DEBUG_IS_UNLOCKED do { RT_ASSERT(!rt_sched_is_locked()); } while (0) + +#else /* !RT_USING_SMP */ + +#define RT_SCHED_DEBUG_IS_LOCKED +#define RT_SCHED_DEBUG_IS_UNLOCKED +#endif /* RT_USING_SMP */ + +/** + * NOTE: user should NEVER use these APIs directly. See rt_thread_.* or IPC + * methods instead. + */ +#if defined(__RT_KERNEL_SOURCE__) || defined(__RT_IPC_SOURCE__) + +/* thread initialization and startup routine */ +void rt_sched_thread_init_ctx(struct rt_thread *thread, rt_uint32_t tick, rt_uint8_t priority); +void rt_sched_thread_init_priv(struct rt_thread *thread, rt_uint32_t tick, rt_uint8_t priority); +void rt_sched_thread_startup(struct rt_thread *thread); + +/* scheduler related routine */ +void rt_sched_post_ctx_switch(struct rt_thread *thread); +rt_err_t rt_sched_tick_increase(void); + +/* thread status operation */ +rt_uint8_t rt_sched_thread_get_stat(struct rt_thread *thread); +rt_uint8_t rt_sched_thread_get_curr_prio(struct rt_thread *thread); +rt_uint8_t rt_sched_thread_get_init_prio(struct rt_thread *thread); +rt_err_t rt_sched_thread_yield(struct rt_thread *thread); +rt_err_t rt_sched_thread_close(struct rt_thread *thread); +rt_err_t rt_sched_thread_ready(struct rt_thread *thread); +rt_err_t rt_sched_thread_suspend(struct rt_thread *thread, rt_sched_lock_level_t level); +rt_err_t rt_sched_thread_change_priority(struct rt_thread *thread, rt_uint8_t priority); +rt_err_t rt_sched_thread_bind_cpu(struct rt_thread *thread, int cpu); +rt_uint8_t rt_sched_thread_is_suspended(struct rt_thread *thread); +rt_err_t rt_sched_thread_timer_stop(struct rt_thread *thread); +rt_err_t rt_sched_thread_timer_start(struct rt_thread *thread); +void rt_sched_insert_thread(struct rt_thread *thread); +void rt_sched_remove_thread(struct rt_thread *thread); + +#endif /* defined(__RT_KERNEL_SOURCE__) || defined(__RT_IPC_SOURCE__) */ + +#endif /* __RT_SCHED_H__ */ diff --git a/include/rtthread.h b/include/rtthread.h index 07fcb64e08..08ad243960 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -21,6 +21,7 @@ * 2023-06-30 ChuShicheng move debug check from the rtdebug.h * 2023-10-16 Shell Support a new backtrace framework * 2023-12-10 xqyjlj fix spinlock in up + * 2024-01-25 Shell Add rt_susp_list for IPC primitives */ #ifndef __RT_THREAD_H__ @@ -43,7 +44,7 @@ extern "C" { #endif #ifdef __GNUC__ -int entry(void); +int entry(void); #endif /** @@ -173,7 +174,6 @@ rt_err_t rt_thread_resume(rt_thread_t thread); rt_err_t rt_thread_wakeup(rt_thread_t thread); void rt_thread_wakeup_set(struct rt_thread *thread, rt_wakeup_func_t func, void* user_data); #endif /* RT_USING_SMART */ -void rt_thread_timeout(void *parameter); rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size); #ifdef RT_USING_SIGNALS void rt_thread_alloc_sig(rt_thread_t tid); @@ -212,11 +212,10 @@ void rt_system_scheduler_start(void); void rt_schedule(void); void rt_scheduler_do_irq_switch(void *context); -void rt_schedule_insert_thread(struct rt_thread *thread); -void rt_schedule_remove_thread(struct rt_thread *thread); -void rt_enter_critical(void); +rt_base_t rt_enter_critical(void); void rt_exit_critical(void); +void rt_exit_critical_safe(rt_base_t critical_level); rt_uint16_t rt_critical_level(void); #ifdef RT_USING_HOOK @@ -368,6 +367,26 @@ void rt_slab_free(rt_slab_t m, void *ptr); * @{ */ +/** + * Suspend list - A basic building block for IPC primitives which interacts with + * scheduler directly. Its API is similar to a FIFO list. + * + * Note: don't use in application codes directly + */ +void rt_susp_list_print(rt_list_t *list); +/* reserve thread error while resuming it */ +#define RT_THREAD_RESUME_RES_THR_ERR (-1) +struct rt_thread *rt_susp_list_dequeue(rt_list_t *susp_list, rt_err_t thread_error); +rt_err_t rt_susp_list_resume_all(rt_list_t *susp_list, rt_err_t thread_error); +rt_err_t rt_susp_list_resume_all_irq(rt_list_t *susp_list, + rt_err_t thread_error, + struct rt_spinlock *lock); + +/* suspend and enqueue */ +rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int ipc_flags, int suspend_flag); +/* only for a suspended thread, and caller must hold the scheduler lock */ +rt_err_t rt_susp_list_enqueue(rt_list_t *susp_list, rt_thread_t thread, int ipc_flags); + #ifdef RT_USING_SEMAPHORE /* * semaphore interface @@ -725,11 +744,11 @@ int rt_snprintf(char *buf, rt_size_t size, const char *format, ...); #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE) rt_device_t rt_console_set_device(const char *name); rt_device_t rt_console_get_device(void); -#ifdef RT_USING_THREDSAFE_PRINTF +#ifdef RT_USING_THREADSAFE_PRINTF rt_thread_t rt_console_current_user(void); #else rt_inline void *rt_console_current_user(void) { return RT_NULL; } -#endif /* RT_USING_THREDSAFE_PRINTF */ +#endif /* RT_USING_THREADSAFE_PRINTF */ #endif /* defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE) */ rt_err_t rt_get_errno(void); diff --git a/include/rttypes.h b/include/rttypes.h new file mode 100644 index 0000000000..c9b172208d --- /dev/null +++ b/include/rttypes.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-18 Shell Separate the basic types from rtdef.h + */ + +#ifndef __RT_TYPES_H__ +#define __RT_TYPES_H__ + +#include <rtconfig.h> + +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> +#ifndef RT_USING_NANO +#include <sys/types.h> +#include <sys/errno.h> +#if defined(RT_USING_SIGNALS) || defined(RT_USING_SMART) +#include <sys/signal.h> +#endif /* defined(RT_USING_SIGNALS) || defined(RT_USING_SMART) */ +#endif /* RT_USING_NANO */ + +/** + * RT-Thread basic data types definition + */ + +typedef int rt_bool_t; /**< boolean type */ +typedef signed long rt_base_t; /**< Nbit CPU related date type */ +typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */ + +#ifndef RT_USING_ARCH_DATA_TYPE +#ifdef RT_USING_LIBC +typedef int8_t rt_int8_t; /**< 8bit integer type */ +typedef int16_t rt_int16_t; /**< 16bit integer type */ +typedef int32_t rt_int32_t; /**< 32bit integer type */ +typedef uint8_t rt_uint8_t; /**< 8bit unsigned integer type */ +typedef uint16_t rt_uint16_t; /**< 16bit unsigned integer type */ +typedef uint32_t rt_uint32_t; /**< 32bit unsigned integer type */ +typedef int64_t rt_int64_t; /**< 64bit integer type */ +typedef uint64_t rt_uint64_t; /**< 64bit unsigned integer type */ +#else +typedef signed char rt_int8_t; /**< 8bit integer type */ +typedef signed short rt_int16_t; /**< 16bit integer type */ +typedef signed int rt_int32_t; /**< 32bit integer type */ +typedef unsigned char rt_uint8_t; /**< 8bit unsigned integer type */ +typedef unsigned short rt_uint16_t; /**< 16bit unsigned integer type */ +typedef unsigned int rt_uint32_t; /**< 32bit unsigned integer type */ +#ifdef ARCH_CPU_64BIT +typedef signed long rt_int64_t; /**< 64bit integer type */ +typedef unsigned long rt_uint64_t; /**< 64bit unsigned integer type */ +#else +typedef signed long long rt_int64_t; /**< 64bit integer type */ +typedef unsigned long long rt_uint64_t; /**< 64bit unsigned integer type */ +#endif /* ARCH_CPU_64BIT */ +#endif /* RT_USING_LIBC */ +#endif /* RT_USING_ARCH_DATA_TYPE */ + +#if defined(RT_USING_LIBC) && !defined(RT_USING_NANO) +typedef size_t rt_size_t; /**< Type for size number */ +typedef ssize_t rt_ssize_t; /**< Used for a count of bytes or an error indication */ +#else +typedef rt_ubase_t rt_size_t; /**< Type for size number */ +typedef rt_base_t rt_ssize_t; /**< Used for a count of bytes or an error indication */ +#endif /* defined(RT_USING_LIBC) && !defined(RT_USING_NANO) */ + +typedef rt_base_t rt_err_t; /**< Type for error number */ +typedef rt_uint32_t rt_time_t; /**< Type for time stamp */ +typedef rt_uint32_t rt_tick_t; /**< Type for tick count */ +typedef rt_base_t rt_flag_t; /**< Type for flags */ +typedef rt_ubase_t rt_dev_t; /**< Type for device */ +typedef rt_base_t rt_off_t; /**< Type for offset */ + +#ifdef __cplusplus +typedef rt_base_t rt_atomic_t; +#else +#if defined(RT_USING_HW_ATOMIC) +typedef rt_base_t rt_atomic_t; +#elif defined(RT_USING_STDC_ATOMIC) +#include <stdatomic.h> +typedef atomic_size_t rt_atomic_t; +#else +typedef rt_base_t rt_atomic_t; +#endif /* RT_USING_STDC_ATOMIC */ +#endif /* __cplusplus */ + +/* boolean type definitions */ +#define RT_TRUE 1 /**< boolean true */ +#define RT_FALSE 0 /**< boolean fails */ + +/* null pointer definition */ +#define RT_NULL 0 + +/** + * Double List structure + */ +struct rt_list_node +{ + struct rt_list_node *next; /**< point to next node. */ + struct rt_list_node *prev; /**< point to prev node. */ +}; +typedef struct rt_list_node rt_list_t; /**< Type for lists. */ + +/** + * Single List structure + */ +struct rt_slist_node +{ + struct rt_slist_node *next; /**< point to next node. */ +}; +typedef struct rt_slist_node rt_slist_t; /**< Type for single list. */ + +/** + * Spinlock + */ +#ifdef RT_USING_SMP +#include <cpuport.h> /* for spinlock from arch */ + +struct rt_spinlock +{ + rt_hw_spinlock_t lock; +#ifdef RT_USING_DEBUG + rt_uint32_t critical_level; +#endif /* RT_USING_DEBUG */ +#if defined(RT_DEBUGING_SPINLOCK) + void *owner; + void *pc; +#endif /* RT_DEBUGING_SPINLOCK */ +}; + +#ifdef RT_DEBUGING_SPINLOCK + +#define __OWNER_MAGIC ((void *)0xdeadbeaf) + +#if defined(__GNUC__) +#define __GET_RETURN_ADDRESS __builtin_return_address(0) +#else +#define __GET_RETURN_ADDRESS RT_NULL +#endif + +#define _SPIN_LOCK_DEBUG_OWNER(lock) \ + do \ + { \ + struct rt_thread *_curthr = rt_thread_self(); \ + if (_curthr != RT_NULL) \ + { \ + (lock)->owner = _curthr; \ + (lock)->pc = __GET_RETURN_ADDRESS; \ + } \ + } while (0) + +#define _SPIN_UNLOCK_DEBUG_OWNER(lock) \ + do \ + { \ + (lock)->owner = __OWNER_MAGIC; \ + (lock)->pc = RT_NULL; \ + } while (0) + +#else + +#define _SPIN_LOCK_DEBUG_OWNER(lock) +#define _SPIN_UNLOCK_DEBUG_OWNER(lock) +#endif + +#ifdef RT_USING_DEBUG + +#define _SPIN_LOCK_DEBUG_CRITICAL(lock) \ + do \ + { \ + struct rt_thread *_curthr = rt_thread_self(); \ + if (_curthr != RT_NULL) \ + { \ + (lock)->critical_level = rt_critical_level(); \ + } \ + } while (0) + +#define _SPIN_UNLOCK_DEBUG_CRITICAL(lock, critical) \ + do \ + { \ + (critical) = (lock)->critical_level; \ + } while (0) + +#else + +#define _SPIN_LOCK_DEBUG_CRITICAL(lock) +#define _SPIN_UNLOCK_DEBUG_CRITICAL(lock, critical) (critical = 0) +#endif /* RT_USING_DEBUG */ + +#define RT_SPIN_LOCK_DEBUG(lock) \ + do \ + { \ + _SPIN_LOCK_DEBUG_OWNER(lock); \ + _SPIN_LOCK_DEBUG_CRITICAL(lock); \ + } while (0) + +#define RT_SPIN_UNLOCK_DEBUG(lock, critical) \ + do \ + { \ + _SPIN_UNLOCK_DEBUG_OWNER(lock); \ + _SPIN_UNLOCK_DEBUG_CRITICAL(lock, critical); \ + } while (0) + +#ifndef RT_SPINLOCK_INIT +#define RT_SPINLOCK_INIT {{0}} /* can be overridden by cpuport.h */ +#endif /* RT_SPINLOCK_INIT */ + +#else + +struct rt_spinlock +{ + rt_ubase_t lock; +}; +#define RT_SPINLOCK_INIT {0} +#endif /* RT_USING_SMP */ + +typedef struct rt_spinlock rt_spinlock_t; + +#define RT_DEFINE_SPINLOCK(x) struct rt_spinlock x = RT_SPINLOCK_INIT + +#endif /* __RT_TYPES_H__ */ |
