summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorShell <[email protected]>2024-02-23 17:49:15 +0800
committerGitHub <[email protected]>2024-02-23 17:49:15 +0800
commit71560bafb5735220696ca24a42ba4a668b55949b (patch)
tree236df5973a1fd5b6f0cc9f6c6b6a2d71fd069203 /include
parent6fe69d7431ed54fcea863ed68d7c4f9746e771b0 (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.h100
-rw-r--r--include/rtdef.h296
-rw-r--r--include/rtsched.h172
-rw-r--r--include/rtthread.h33
-rw-r--r--include/rttypes.h223
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__ */