mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 03:09:16 +08:00
🎯 Sync smart & scheduler codes (#8537)
Signed-off-by: Shell <smokewood@qq.com> Co-authored-by: xqyjlj <xqyjlj@126.com>
This commit is contained in:
+11
-1
@@ -35,6 +35,7 @@ config RT_USING_SMART
|
||||
select RT_USING_POSIX_FS
|
||||
select RT_USING_POSIX_TERMIOS
|
||||
select RT_USING_KTIME
|
||||
select RT_USING_STDC_ATOMIC
|
||||
depends on ARCH_ARM_CORTEX_M || ARCH_ARM_ARM9 || ARCH_ARM_CORTEX_A || ARCH_ARMV8 || ARCH_RISCV64
|
||||
depends on !RT_USING_NANO
|
||||
help
|
||||
@@ -66,6 +67,7 @@ config RT_USING_AMP
|
||||
config RT_USING_SMP
|
||||
bool "Enable SMP (Symmetric multiprocessing)"
|
||||
default n
|
||||
select RT_USING_SCHED_THREAD_CTX
|
||||
help
|
||||
This option should be selected by machines which have an SMP-
|
||||
capable CPU.
|
||||
@@ -417,10 +419,18 @@ config RT_USING_INTERRUPT_INFO
|
||||
help
|
||||
Add name and counter information for interrupt trace.
|
||||
|
||||
config RT_USING_THREDSAFE_PRINTF
|
||||
config RT_USING_THREADSAFE_PRINTF
|
||||
bool "Enable thread safe kernel print service"
|
||||
default y if RT_USING_SMP && RT_USING_SMART
|
||||
|
||||
config RT_USING_SCHED_THREAD_CTX
|
||||
bool "Using the scheduler thread context"
|
||||
help
|
||||
Using the scheduler thread context embedded in the thread object.
|
||||
This options is only for backward compatible codes. Maybe use as a
|
||||
mandatory option in the future.
|
||||
default y if RT_USING_SMP
|
||||
|
||||
config RT_USING_CONSOLE
|
||||
bool "Using console for rt_kprintf"
|
||||
default y
|
||||
|
||||
+2
-3
@@ -26,8 +26,7 @@ if GetDepend('RT_USING_DEVICE') == False:
|
||||
|
||||
if GetDepend('RT_USING_SMP') == False:
|
||||
SrcRemove(src, ['cpu.c', 'scheduler_mp.c'])
|
||||
|
||||
if GetDepend('RT_USING_SMP') == True:
|
||||
else:
|
||||
SrcRemove(src, ['scheduler_up.c'])
|
||||
|
||||
LOCAL_CFLAGS = ''
|
||||
@@ -43,6 +42,6 @@ if rtconfig.PLATFORM in GetGCCLikePLATFORM():
|
||||
LOCAL_CFLAGS += ' -Wimplicit-fallthrough' # implicit fallthrough warning
|
||||
LOCAL_CFLAGS += ' -Wduplicated-cond -Wduplicated-branches' # duplicated condition warning
|
||||
|
||||
group = DefineGroup('Kernel', src, depend=[''], CPPPATH=inc, CPPDEFINES=['__RTTHREAD__'], LOCAL_CFLAGS=LOCAL_CFLAGS)
|
||||
group = DefineGroup('Kernel', src, depend=[''], CPPPATH=inc, CPPDEFINES=['__RTTHREAD__'], LOCAL_CFLAGS=LOCAL_CFLAGS, LOCAL_CPPDEFINES=['__RT_KERNEL_SOURCE__'])
|
||||
|
||||
Return('group')
|
||||
|
||||
+2
-17
@@ -85,34 +85,19 @@ void rt_tick_set(rt_tick_t tick)
|
||||
*/
|
||||
void rt_tick_increase(void)
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
rt_base_t level;
|
||||
rt_atomic_t oldval = 0;
|
||||
|
||||
RT_ASSERT(rt_interrupt_get_nest() > 0);
|
||||
|
||||
RT_OBJECT_HOOK_CALL(rt_tick_hook, ());
|
||||
/* increase the global tick */
|
||||
#ifdef RT_USING_SMP
|
||||
/* get percpu and increase the tick */
|
||||
rt_atomic_add(&(rt_cpu_self()->tick), 1);
|
||||
#else
|
||||
rt_atomic_add(&(rt_tick), 1);
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
/* check time slice */
|
||||
thread = rt_thread_self();
|
||||
level = rt_spin_lock_irqsave(&(thread->spinlock));
|
||||
rt_atomic_sub(&(thread->remaining_tick), 1);
|
||||
if (rt_atomic_compare_exchange_strong(&(thread->remaining_tick), &oldval, thread->init_tick))
|
||||
{
|
||||
thread->stat |= RT_THREAD_STAT_YIELD;
|
||||
rt_spin_unlock_irqrestore(&(thread->spinlock), level);
|
||||
rt_schedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&(thread->spinlock), level);
|
||||
}
|
||||
rt_sched_tick_increase();
|
||||
|
||||
/* check timer */
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* 2018-10-30 Bernard The first version
|
||||
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
|
||||
* 2023-12-10 xqyjlj spinlock should lock sched
|
||||
* 2024-01-25 Shell Using rt_exit_critical_safe
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
@@ -16,6 +17,10 @@
|
||||
#include <lwp.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_DEBUG
|
||||
rt_base_t _cpus_critical_level;
|
||||
#endif /* RT_USING_DEBUG */
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
static struct rt_cpu _cpus[RT_CPUS_NR];
|
||||
rt_hw_spinlock_t _cpus_lock;
|
||||
@@ -23,14 +28,6 @@ rt_hw_spinlock_t _cpus_lock;
|
||||
void *_cpus_lock_owner = 0;
|
||||
void *_cpus_lock_pc = 0;
|
||||
|
||||
#define __OWNER_MAGIC ((void *)0xdeadbeaf)
|
||||
|
||||
#if defined (__GNUC__)
|
||||
#define __GET_RETURN_ADDRESS __builtin_return_address(0)
|
||||
#else
|
||||
#define __GET_RETURN_ADDRESS RT_NULL
|
||||
#endif
|
||||
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
|
||||
/**
|
||||
@@ -56,13 +53,7 @@ void rt_spin_lock(struct rt_spinlock *lock)
|
||||
{
|
||||
rt_enter_critical();
|
||||
rt_hw_spin_lock(&lock->lock);
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
if (rt_cpu_self() != RT_NULL)
|
||||
{
|
||||
lock->owner = rt_cpu_self()->current_thread;
|
||||
}
|
||||
lock->pc = __GET_RETURN_ADDRESS;
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
RT_SPIN_LOCK_DEBUG(lock);
|
||||
}
|
||||
RTM_EXPORT(rt_spin_lock)
|
||||
|
||||
@@ -73,12 +64,10 @@ RTM_EXPORT(rt_spin_lock)
|
||||
*/
|
||||
void rt_spin_unlock(struct rt_spinlock *lock)
|
||||
{
|
||||
rt_base_t critical_level;
|
||||
RT_SPIN_UNLOCK_DEBUG(lock, critical_level);
|
||||
rt_hw_spin_unlock(&lock->lock);
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
lock->owner = __OWNER_MAGIC;
|
||||
lock->pc = RT_NULL;
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
rt_exit_critical();
|
||||
rt_exit_critical_safe(critical_level);
|
||||
}
|
||||
RTM_EXPORT(rt_spin_unlock)
|
||||
|
||||
@@ -99,13 +88,7 @@ rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
|
||||
level = rt_hw_local_irq_disable();
|
||||
rt_enter_critical();
|
||||
rt_hw_spin_lock(&lock->lock);
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
if (rt_cpu_self() != RT_NULL)
|
||||
{
|
||||
lock->owner = rt_cpu_self()->current_thread;
|
||||
lock->pc = __GET_RETURN_ADDRESS;
|
||||
}
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
RT_SPIN_LOCK_DEBUG(lock);
|
||||
return level;
|
||||
}
|
||||
RTM_EXPORT(rt_spin_lock_irqsave)
|
||||
@@ -119,13 +102,12 @@ RTM_EXPORT(rt_spin_lock_irqsave)
|
||||
*/
|
||||
void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
|
||||
{
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
lock->owner = __OWNER_MAGIC;
|
||||
lock->pc = RT_NULL;
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
rt_base_t critical_level;
|
||||
|
||||
RT_SPIN_UNLOCK_DEBUG(lock, critical_level);
|
||||
rt_hw_spin_unlock(&lock->lock);
|
||||
rt_hw_local_irq_enable(level);
|
||||
rt_exit_critical();
|
||||
rt_exit_critical_safe(critical_level);
|
||||
}
|
||||
RTM_EXPORT(rt_spin_unlock_irqrestore)
|
||||
|
||||
@@ -162,7 +144,6 @@ rt_base_t rt_cpus_lock(void)
|
||||
struct rt_cpu* pcpu;
|
||||
|
||||
level = rt_hw_local_irq_disable();
|
||||
rt_enter_critical();
|
||||
pcpu = rt_cpu_self();
|
||||
if (pcpu->current_thread != RT_NULL)
|
||||
{
|
||||
@@ -171,11 +152,16 @@ rt_base_t rt_cpus_lock(void)
|
||||
rt_atomic_add(&(pcpu->current_thread->cpus_lock_nest), 1);
|
||||
if (lock_nest == 0)
|
||||
{
|
||||
rt_enter_critical();
|
||||
rt_hw_spin_lock(&_cpus_lock);
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
#ifdef RT_USING_DEBUG
|
||||
_cpus_critical_level = rt_critical_level();
|
||||
#endif /* RT_USING_DEBUG */
|
||||
|
||||
#ifdef RT_DEBUGING_SPINLOCK
|
||||
_cpus_lock_owner = pcpu->current_thread;
|
||||
_cpus_lock_pc = __GET_RETURN_ADDRESS;
|
||||
#endif
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +180,7 @@ void rt_cpus_unlock(rt_base_t level)
|
||||
|
||||
if (pcpu->current_thread != RT_NULL)
|
||||
{
|
||||
rt_base_t critical_level = 0;
|
||||
RT_ASSERT(rt_atomic_load(&(pcpu->current_thread->cpus_lock_nest)) > 0);
|
||||
rt_atomic_sub(&(pcpu->current_thread->cpus_lock_nest), 1);
|
||||
|
||||
@@ -202,12 +189,16 @@ void rt_cpus_unlock(rt_base_t level)
|
||||
#if defined(RT_DEBUGING_SPINLOCK)
|
||||
_cpus_lock_owner = __OWNER_MAGIC;
|
||||
_cpus_lock_pc = RT_NULL;
|
||||
#endif
|
||||
#endif /* RT_DEBUGING_SPINLOCK */
|
||||
#ifdef RT_USING_DEBUG
|
||||
critical_level = _cpus_critical_level;
|
||||
_cpus_critical_level = 0;
|
||||
#endif /* RT_USING_DEBUG */
|
||||
rt_hw_spin_unlock(&_cpus_lock);
|
||||
rt_exit_critical_safe(critical_level);
|
||||
}
|
||||
}
|
||||
rt_hw_local_irq_enable(level);
|
||||
rt_exit_critical();
|
||||
}
|
||||
RTM_EXPORT(rt_cpus_unlock);
|
||||
|
||||
@@ -220,20 +211,10 @@ RTM_EXPORT(rt_cpus_unlock);
|
||||
*/
|
||||
void rt_cpus_lock_status_restore(struct rt_thread *thread)
|
||||
{
|
||||
struct rt_cpu* pcpu = rt_cpu_self();
|
||||
|
||||
#if defined(ARCH_MM_MMU) && defined(RT_USING_SMART)
|
||||
lwp_aspace_switch(thread);
|
||||
#endif
|
||||
if (pcpu->current_thread != RT_NULL )
|
||||
{
|
||||
rt_hw_spin_unlock(&(pcpu->current_thread->spinlock.lock));
|
||||
if ((pcpu->current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
{
|
||||
rt_schedule_insert_thread(pcpu->current_thread);
|
||||
}
|
||||
}
|
||||
pcpu->current_thread = thread;
|
||||
rt_sched_post_ctx_switch(thread);
|
||||
}
|
||||
RTM_EXPORT(rt_cpus_lock_status_restore);
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
+7
-10
@@ -146,7 +146,7 @@ void rt_thread_defunct_enqueue(rt_thread_t thread)
|
||||
{
|
||||
rt_base_t level;
|
||||
level = rt_spin_lock_irqsave(&_defunct_spinlock);
|
||||
rt_list_insert_after(&_rt_thread_defunct, &thread->tlist);
|
||||
rt_list_insert_after(&_rt_thread_defunct, &RT_THREAD_LIST_NODE(thread));
|
||||
rt_spin_unlock_irqrestore(&_defunct_spinlock, level);
|
||||
#ifdef RT_USING_SMP
|
||||
rt_sem_release(&system_sem);
|
||||
@@ -166,20 +166,16 @@ rt_thread_t rt_thread_defunct_dequeue(void)
|
||||
level = rt_spin_lock_irqsave(&_defunct_spinlock);
|
||||
if (l->next != l)
|
||||
{
|
||||
thread = rt_list_entry(l->next,
|
||||
struct rt_thread,
|
||||
tlist);
|
||||
rt_list_remove(&(thread->tlist));
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(l->next);
|
||||
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&_defunct_spinlock, level);
|
||||
#else
|
||||
if (l->next != l)
|
||||
{
|
||||
thread = rt_list_entry(l->next,
|
||||
struct rt_thread,
|
||||
tlist);
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(l->next);
|
||||
level = rt_hw_interrupt_disable();
|
||||
rt_list_remove(&(thread->tlist));
|
||||
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
#endif
|
||||
@@ -308,9 +304,10 @@ static void rt_thread_system_entry(void *parameter)
|
||||
|
||||
while (1)
|
||||
{
|
||||
int ret= rt_sem_take(&system_sem, RT_WAITING_FOREVER);
|
||||
int ret = rt_sem_take(&system_sem, RT_WAITING_FOREVER);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
rt_kprintf("failed to sem_take() error %d\n", ret);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
rt_defunct_execute();
|
||||
|
||||
+34
-14
@@ -1500,14 +1500,21 @@ rt_weak void rt_hw_console_output(const char *str)
|
||||
}
|
||||
RTM_EXPORT(rt_hw_console_output);
|
||||
|
||||
#ifdef RT_USING_THREDSAFE_PRINTF
|
||||
#ifdef RT_USING_THREADSAFE_PRINTF
|
||||
|
||||
static struct rt_spinlock _pr_lock = RT_SPINLOCK_INIT;
|
||||
static struct rt_spinlock _prf_lock = RT_SPINLOCK_INIT;
|
||||
/* system console lock */
|
||||
static struct rt_spinlock _syscon_lock = RT_SPINLOCK_INIT;
|
||||
/* lock of kprintf buffer */
|
||||
static struct rt_spinlock _prbuf_lock = RT_SPINLOCK_INIT;
|
||||
/* current user of system console */
|
||||
static rt_thread_t _pr_curr_user;
|
||||
|
||||
#ifdef RT_USING_DEBUG
|
||||
static rt_base_t _pr_critical_level;
|
||||
#endif /* RT_USING_DEBUG */
|
||||
|
||||
/* nested level of current user */
|
||||
static int _pr_curr_user_nested;
|
||||
static volatile int _pr_curr_user_nested;
|
||||
|
||||
rt_thread_t rt_console_current_user(void)
|
||||
{
|
||||
@@ -1516,35 +1523,42 @@ rt_thread_t rt_console_current_user(void)
|
||||
|
||||
static void _console_take(void)
|
||||
{
|
||||
rt_ubase_t level = rt_spin_lock_irqsave(&_pr_lock);
|
||||
rt_ubase_t level = rt_spin_lock_irqsave(&_syscon_lock);
|
||||
rt_thread_t self_thread = rt_thread_self();
|
||||
rt_base_t critical_level;
|
||||
RT_UNUSED(critical_level);
|
||||
|
||||
while (_pr_curr_user != self_thread)
|
||||
{
|
||||
if (_pr_curr_user == RT_NULL)
|
||||
{
|
||||
/* no preemption is allowed to avoid dead lock */
|
||||
rt_enter_critical();
|
||||
critical_level = rt_enter_critical();
|
||||
#ifdef RT_USING_DEBUG
|
||||
_pr_critical_level = _syscon_lock.critical_level;
|
||||
_syscon_lock.critical_level = critical_level;
|
||||
#endif
|
||||
_pr_curr_user = self_thread;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&_pr_lock, level);
|
||||
rt_spin_unlock_irqrestore(&_syscon_lock, level);
|
||||
rt_thread_yield();
|
||||
level = rt_spin_lock_irqsave(&_pr_lock);
|
||||
level = rt_spin_lock_irqsave(&_syscon_lock);
|
||||
}
|
||||
}
|
||||
|
||||
_pr_curr_user_nested++;
|
||||
|
||||
rt_spin_unlock_irqrestore(&_pr_lock, level);
|
||||
rt_spin_unlock_irqrestore(&_syscon_lock, level);
|
||||
}
|
||||
|
||||
static void _console_release(void)
|
||||
{
|
||||
rt_ubase_t level = rt_spin_lock_irqsave(&_pr_lock);
|
||||
rt_ubase_t level = rt_spin_lock_irqsave(&_syscon_lock);
|
||||
rt_thread_t self_thread = rt_thread_self();
|
||||
RT_UNUSED(self_thread);
|
||||
|
||||
RT_ASSERT(_pr_curr_user == self_thread);
|
||||
|
||||
@@ -1552,22 +1566,28 @@ static void _console_release(void)
|
||||
if (!_pr_curr_user_nested)
|
||||
{
|
||||
_pr_curr_user = RT_NULL;
|
||||
|
||||
#ifdef RT_USING_DEBUG
|
||||
rt_exit_critical_safe(_syscon_lock.critical_level);
|
||||
_syscon_lock.critical_level = _pr_critical_level;
|
||||
#else
|
||||
rt_exit_critical();
|
||||
#endif
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&_pr_lock, level);
|
||||
rt_spin_unlock_irqrestore(&_syscon_lock, level);
|
||||
}
|
||||
|
||||
#define CONSOLE_TAKE _console_take()
|
||||
#define CONSOLE_RELEASE _console_release()
|
||||
#define PRINTF_BUFFER_TAKE rt_ubase_t level = rt_spin_lock_irqsave(&_prf_lock)
|
||||
#define PRINTF_BUFFER_RELEASE rt_spin_unlock_irqrestore(&_prf_lock, level)
|
||||
#define PRINTF_BUFFER_TAKE rt_ubase_t level = rt_spin_lock_irqsave(&_prbuf_lock)
|
||||
#define PRINTF_BUFFER_RELEASE rt_spin_unlock_irqrestore(&_prbuf_lock, level)
|
||||
#else
|
||||
|
||||
#define CONSOLE_TAKE
|
||||
#define CONSOLE_RELEASE
|
||||
#define PRINTF_BUFFER_TAKE
|
||||
#define PRINTF_BUFFER_RELEASE
|
||||
#endif /* RT_USING_THREDSAFE_PRINTF */
|
||||
#endif /* RT_USING_THREADSAFE_PRINTF */
|
||||
|
||||
/**
|
||||
* @brief This function will put string to the console.
|
||||
|
||||
+4
-46
@@ -141,7 +141,6 @@ RTM_EXPORT(rt_mp_init);
|
||||
*/
|
||||
rt_err_t rt_mp_detach(struct rt_mempool *mp)
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
rt_base_t level;
|
||||
|
||||
/* parameter check */
|
||||
@@ -151,21 +150,7 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp)
|
||||
|
||||
level = rt_spin_lock_irqsave(&(mp->spinlock));
|
||||
/* wake up all suspended threads */
|
||||
while (!rt_list_isempty(&(mp->suspend_thread)))
|
||||
{
|
||||
|
||||
/* get next suspend thread */
|
||||
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
|
||||
/* set error code to -RT_ERROR */
|
||||
thread->error = -RT_ERROR;
|
||||
|
||||
/*
|
||||
* resume thread
|
||||
* In rt_thread_resume function, it will remove current thread from
|
||||
* suspend list
|
||||
*/
|
||||
rt_thread_resume(thread);
|
||||
}
|
||||
rt_susp_list_resume_all(&mp->suspend_thread, RT_ERROR);
|
||||
|
||||
/* detach object */
|
||||
rt_object_detach(&(mp->parent));
|
||||
@@ -257,7 +242,6 @@ RTM_EXPORT(rt_mp_create);
|
||||
*/
|
||||
rt_err_t rt_mp_delete(rt_mp_t mp)
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
rt_base_t level;
|
||||
|
||||
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||
@@ -269,20 +253,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
|
||||
|
||||
level = rt_spin_lock_irqsave(&(mp->spinlock));
|
||||
/* wake up all suspended threads */
|
||||
while (!rt_list_isempty(&(mp->suspend_thread)))
|
||||
{
|
||||
/* get next suspend thread */
|
||||
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
|
||||
/* set error code to -RT_ERROR */
|
||||
thread->error = -RT_ERROR;
|
||||
|
||||
/*
|
||||
* resume thread
|
||||
* In rt_thread_resume function, it will remove current thread from
|
||||
* suspend list
|
||||
*/
|
||||
rt_thread_resume(thread);
|
||||
}
|
||||
rt_susp_list_resume_all(&mp->suspend_thread, RT_ERROR);
|
||||
|
||||
rt_spin_unlock_irqrestore(&(mp->spinlock), level);
|
||||
|
||||
@@ -339,8 +310,7 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
|
||||
thread->error = RT_EOK;
|
||||
|
||||
/* need suspend thread */
|
||||
rt_thread_suspend(thread);
|
||||
rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
|
||||
rt_thread_suspend_to_list(thread, &mp->suspend_thread, RT_IPC_FLAG_FIFO, RT_UNINTERRUPTIBLE);
|
||||
|
||||
if (time > 0)
|
||||
{
|
||||
@@ -403,7 +373,6 @@ void rt_mp_free(void *block)
|
||||
{
|
||||
rt_uint8_t **block_ptr;
|
||||
struct rt_mempool *mp;
|
||||
struct rt_thread *thread;
|
||||
rt_base_t level;
|
||||
|
||||
/* parameter check */
|
||||
@@ -424,19 +393,8 @@ void rt_mp_free(void *block)
|
||||
*block_ptr = mp->block_list;
|
||||
mp->block_list = (rt_uint8_t *)block_ptr;
|
||||
|
||||
if (!rt_list_isempty(&(mp->suspend_thread)))
|
||||
if (rt_susp_list_dequeue(&mp->suspend_thread, RT_EOK))
|
||||
{
|
||||
/* get the suspended thread */
|
||||
thread = rt_list_entry(mp->suspend_thread.next,
|
||||
struct rt_thread,
|
||||
tlist);
|
||||
|
||||
/* set error */
|
||||
thread->error = RT_EOK;
|
||||
|
||||
/* resume thread */
|
||||
rt_thread_resume(thread);
|
||||
|
||||
rt_spin_unlock_irqrestore(&(mp->spinlock), level);
|
||||
|
||||
/* do a schedule */
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ enum rt_object_info_type
|
||||
RT_Object_Info_Module, /**< The object is a module. */
|
||||
#endif
|
||||
#ifdef RT_USING_HEAP
|
||||
RT_Object_Info_Memory, /**< The object is a memory. */
|
||||
RT_Object_Info_Memory, /**< The object is a memory. */
|
||||
#endif
|
||||
#ifdef RT_USING_SMART
|
||||
RT_Object_Info_Channel, /**< The object is a IPC channel */
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* (scheduler_comm.c) Common API of scheduling routines.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-01-18 Shell Separate scheduling related codes from thread.c, scheduler_.*
|
||||
*/
|
||||
|
||||
#define DBG_TAG "kernel.sched"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
void rt_sched_thread_init_ctx(struct rt_thread *thread, rt_uint32_t tick, rt_uint8_t priority)
|
||||
{
|
||||
/* setup thread status */
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_INIT;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* not bind on any cpu */
|
||||
RT_SCHED_CTX(thread).bind_cpu = RT_CPUS_NR;
|
||||
RT_SCHED_CTX(thread).oncpu = RT_CPU_DETACHED;
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
rt_sched_thread_init_priv(thread, tick, priority);
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_thread_timer_start(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
RT_SCHED_CTX(thread).sched_flag_ttmr_set = 1;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_thread_timer_stop(struct rt_thread *thread)
|
||||
{
|
||||
rt_err_t error;
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
|
||||
if (RT_SCHED_CTX(thread).sched_flag_ttmr_set)
|
||||
{
|
||||
error = rt_timer_stop(&thread->thread_timer);
|
||||
|
||||
/* mask out timer flag no matter stop success or not */
|
||||
RT_SCHED_CTX(thread).sched_flag_ttmr_set = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = RT_EOK;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
rt_uint8_t rt_sched_thread_get_stat(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
return RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK;
|
||||
}
|
||||
|
||||
rt_uint8_t rt_sched_thread_get_curr_prio(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
return RT_SCHED_PRIV(thread).current_priority;
|
||||
}
|
||||
|
||||
rt_uint8_t rt_sched_thread_get_init_prio(struct rt_thread *thread)
|
||||
{
|
||||
/* read only fields, so lock is unecessary */
|
||||
return RT_SCHED_PRIV(thread).init_priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note Caller must hold the scheduler lock
|
||||
*/
|
||||
rt_uint8_t rt_sched_thread_is_suspended(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
return (RT_SCHED_CTX(thread).stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_thread_close(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_CLOSE;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_thread_yield(struct rt_thread *thread)
|
||||
{
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
|
||||
RT_SCHED_PRIV(thread).remaining_tick = RT_SCHED_PRIV(thread).init_tick;
|
||||
RT_SCHED_CTX(thread).stat |= RT_THREAD_STAT_YIELD;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_thread_ready(struct rt_thread *thread)
|
||||
{
|
||||
rt_err_t error;
|
||||
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
|
||||
if (!rt_sched_thread_is_suspended(thread))
|
||||
{
|
||||
/* failed to proceed, and that's possibly due to a racing condition */
|
||||
error = -RT_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RT_SCHED_CTX(thread).sched_flag_ttmr_set)
|
||||
{
|
||||
/**
|
||||
* Quiet timeout timer first if set. and don't continue if we
|
||||
* failed, because it probably means that a timeout ISR racing to
|
||||
* resume thread before us.
|
||||
*/
|
||||
error = rt_sched_thread_timer_stop(thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = RT_EOK;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
/* remove from suspend list */
|
||||
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
thread->wakeup_handle.func = RT_NULL;
|
||||
#endif
|
||||
|
||||
/* insert to schedule ready list and remove from susp list */
|
||||
rt_sched_insert_thread(thread);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_tick_increase(void)
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
rt_sched_lock_level_t slvl;
|
||||
|
||||
thread = rt_thread_self();
|
||||
|
||||
rt_sched_lock(&slvl);
|
||||
|
||||
RT_SCHED_PRIV(thread).remaining_tick--;
|
||||
if (RT_SCHED_PRIV(thread).remaining_tick)
|
||||
{
|
||||
rt_sched_unlock(slvl);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_sched_thread_yield(thread);
|
||||
|
||||
/* request a rescheduling even though we are probably in an ISR */
|
||||
rt_sched_unlock_n_resched(slvl);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update priority of the target thread
|
||||
*/
|
||||
rt_err_t rt_sched_thread_change_priority(struct rt_thread *thread, rt_uint8_t priority)
|
||||
{
|
||||
RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
|
||||
RT_SCHED_DEBUG_IS_LOCKED;
|
||||
|
||||
/* for ready thread, change queue; otherwise simply update the priority */
|
||||
if ((RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
|
||||
{
|
||||
/* remove thread from schedule queue first */
|
||||
rt_sched_remove_thread(thread);
|
||||
|
||||
/* change thread priority */
|
||||
RT_SCHED_PRIV(thread).current_priority = priority;
|
||||
|
||||
/* recalculate priority attribute */
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
RT_SCHED_PRIV(thread).number = RT_SCHED_PRIV(thread).current_priority >> 3; /* 5bit */
|
||||
RT_SCHED_PRIV(thread).number_mask = 1 << RT_SCHED_PRIV(thread).number;
|
||||
RT_SCHED_PRIV(thread).high_mask = 1 << (RT_SCHED_PRIV(thread).current_priority & 0x07); /* 3bit */
|
||||
#else
|
||||
RT_SCHED_PRIV(thread).number_mask = 1 << RT_SCHED_PRIV(thread).current_priority;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_INIT;
|
||||
|
||||
/* insert thread to schedule queue again */
|
||||
rt_sched_insert_thread(thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
RT_SCHED_PRIV(thread).current_priority = priority;
|
||||
|
||||
/* recalculate priority attribute */
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
RT_SCHED_PRIV(thread).number = RT_SCHED_PRIV(thread).current_priority >> 3; /* 5bit */
|
||||
RT_SCHED_PRIV(thread).number_mask = 1 << RT_SCHED_PRIV(thread).number;
|
||||
RT_SCHED_PRIV(thread).high_mask = 1 << (RT_SCHED_PRIV(thread).current_priority & 0x07); /* 3bit */
|
||||
#else
|
||||
RT_SCHED_PRIV(thread).number_mask = 1 << RT_SCHED_PRIV(thread).current_priority;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
+934
-454
File diff suppressed because it is too large
Load Diff
+152
-37
@@ -161,15 +161,44 @@ static struct rt_thread* _scheduler_get_highest_priority_thread(rt_ubase_t *high
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
|
||||
/* get highest ready priority thread */
|
||||
highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
|
||||
struct rt_thread,
|
||||
tlist);
|
||||
highest_priority_thread = RT_THREAD_LIST_NODE_ENTRY(rt_thread_priority_table[highest_ready_priority].next);
|
||||
|
||||
*highest_prio = highest_ready_priority;
|
||||
|
||||
return highest_priority_thread;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_lock(rt_sched_lock_level_t *plvl)
|
||||
{
|
||||
rt_base_t level;
|
||||
if (!plvl)
|
||||
return -RT_EINVAL;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
*plvl = level;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_unlock(rt_sched_lock_level_t level)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_sched_unlock_n_resched(rt_sched_lock_level_t level)
|
||||
{
|
||||
if (rt_thread_self())
|
||||
{
|
||||
/* if scheduler is available */
|
||||
rt_schedule();
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will initialize the system scheduler.
|
||||
*/
|
||||
@@ -208,8 +237,8 @@ void rt_system_scheduler_start(void)
|
||||
|
||||
rt_current_thread = to_thread;
|
||||
|
||||
rt_schedule_remove_thread(to_thread);
|
||||
to_thread->stat = RT_THREAD_RUNNING;
|
||||
rt_sched_remove_thread(to_thread);
|
||||
RT_SCHED_CTX(to_thread).stat = RT_THREAD_RUNNING;
|
||||
|
||||
/* switch to new thread */
|
||||
|
||||
@@ -250,13 +279,13 @@ void rt_schedule(void)
|
||||
|
||||
to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
|
||||
|
||||
if ((rt_current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
if ((RT_SCHED_CTX(rt_current_thread).stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
{
|
||||
if (rt_current_thread->current_priority < highest_ready_priority)
|
||||
if (RT_SCHED_PRIV(rt_current_thread).current_priority < highest_ready_priority)
|
||||
{
|
||||
to_thread = rt_current_thread;
|
||||
}
|
||||
else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
else if (RT_SCHED_PRIV(rt_current_thread).current_priority == highest_ready_priority && (RT_SCHED_CTX(rt_current_thread).stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
{
|
||||
to_thread = rt_current_thread;
|
||||
}
|
||||
@@ -277,16 +306,16 @@ void rt_schedule(void)
|
||||
|
||||
if (need_insert_from_thread)
|
||||
{
|
||||
rt_schedule_insert_thread(from_thread);
|
||||
rt_sched_insert_thread(from_thread);
|
||||
}
|
||||
|
||||
if ((from_thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
|
||||
if ((RT_SCHED_CTX(from_thread).stat & RT_THREAD_STAT_YIELD_MASK) != 0)
|
||||
{
|
||||
from_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
|
||||
RT_SCHED_CTX(from_thread).stat &= ~RT_THREAD_STAT_YIELD_MASK;
|
||||
}
|
||||
|
||||
rt_schedule_remove_thread(to_thread);
|
||||
to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
rt_sched_remove_thread(to_thread);
|
||||
RT_SCHED_CTX(to_thread).stat = RT_THREAD_RUNNING | (RT_SCHED_CTX(to_thread).stat & ~RT_THREAD_STAT_MASK);
|
||||
|
||||
/* switch to new thread */
|
||||
LOG_D("[%d]switch to priority#%d "
|
||||
@@ -315,11 +344,11 @@ void rt_schedule(void)
|
||||
#ifdef RT_USING_SIGNALS
|
||||
/* check stat of thread for signal */
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
if (RT_SCHED_CTX(rt_current_thread).stat & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
{
|
||||
extern void rt_thread_handle_sig(rt_bool_t clean_state);
|
||||
|
||||
rt_current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
RT_SCHED_CTX(rt_current_thread).stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
@@ -343,8 +372,8 @@ void rt_schedule(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_schedule_remove_thread(rt_current_thread);
|
||||
rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
rt_sched_remove_thread(rt_current_thread);
|
||||
RT_SCHED_CTX(rt_current_thread).stat = RT_THREAD_RUNNING | (RT_SCHED_CTX(rt_current_thread).stat & ~RT_THREAD_STAT_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,6 +385,42 @@ __exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Normally, there isn't anyone racing with us so this operation is lockless */
|
||||
void rt_sched_thread_startup(struct rt_thread *thread)
|
||||
{
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
RT_SCHED_PRIV(thread).number = RT_SCHED_PRIV(thread).current_priority >> 3; /* 5bit */
|
||||
RT_SCHED_PRIV(thread).number_mask = 1L << RT_SCHED_PRIV(thread).number;
|
||||
RT_SCHED_PRIV(thread).high_mask = 1L << (RT_SCHED_PRIV(thread).current_priority & 0x07); /* 3bit */
|
||||
#else
|
||||
RT_SCHED_PRIV(thread).number_mask = 1L << RT_SCHED_PRIV(thread).current_priority;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
|
||||
/* change thread stat, so we can resume it */
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_SUSPEND;
|
||||
}
|
||||
|
||||
void rt_sched_thread_init_priv(struct rt_thread *thread, rt_uint32_t tick, rt_uint8_t priority)
|
||||
{
|
||||
rt_list_init(&RT_THREAD_LIST_NODE(thread));
|
||||
|
||||
/* priority init */
|
||||
RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
|
||||
RT_SCHED_PRIV(thread).init_priority = priority;
|
||||
RT_SCHED_PRIV(thread).current_priority = priority;
|
||||
|
||||
/* don't add to scheduler queue as init thread */
|
||||
RT_SCHED_PRIV(thread).number_mask = 0;
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
RT_SCHED_PRIV(thread).number = 0;
|
||||
RT_SCHED_PRIV(thread).high_mask = 0;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
|
||||
/* tick init */
|
||||
RT_SCHED_PRIV(thread).init_tick = tick;
|
||||
RT_SCHED_PRIV(thread).remaining_tick = tick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will insert a thread to the system ready queue. The state of
|
||||
* thread will be set as READY and the thread will be removed from suspend queue.
|
||||
@@ -364,7 +429,7 @@ __exit:
|
||||
*
|
||||
* @note Please do not invoke this function in user application.
|
||||
*/
|
||||
void rt_schedule_insert_thread(struct rt_thread *thread)
|
||||
void rt_sched_insert_thread(struct rt_thread *thread)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
@@ -376,33 +441,33 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
|
||||
/* it's current thread, it should be RUNNING thread */
|
||||
if (thread == rt_current_thread)
|
||||
{
|
||||
thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_RUNNING | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK);
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* READY thread, insert to ready queue */
|
||||
thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
RT_SCHED_CTX(thread).stat = RT_THREAD_READY | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK);
|
||||
/* there is no time slices left(YIELD), inserting thread before ready list*/
|
||||
if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
|
||||
if((RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_YIELD_MASK) != 0)
|
||||
{
|
||||
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
|
||||
&(thread->tlist));
|
||||
rt_list_insert_before(&(rt_thread_priority_table[RT_SCHED_PRIV(thread).current_priority]),
|
||||
&RT_THREAD_LIST_NODE(thread));
|
||||
}
|
||||
/* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/
|
||||
else
|
||||
{
|
||||
rt_list_insert_after(&(rt_thread_priority_table[thread->current_priority]),
|
||||
&(thread->tlist));
|
||||
rt_list_insert_after(&(rt_thread_priority_table[RT_SCHED_PRIV(thread).current_priority]),
|
||||
&RT_THREAD_LIST_NODE(thread));
|
||||
}
|
||||
|
||||
LOG_D("insert thread[%.*s], the priority: %d",
|
||||
RT_NAME_MAX, thread->parent.name, thread->current_priority);
|
||||
RT_NAME_MAX, thread->parent.name, RT_SCHED_PRIV(rt_current_thread).current_priority);
|
||||
|
||||
/* set priority mask */
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
rt_thread_ready_table[thread->number] |= thread->high_mask;
|
||||
rt_thread_ready_table[RT_SCHED_PRIV(thread).number] |= RT_SCHED_PRIV(thread).high_mask;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
rt_thread_ready_priority_group |= thread->number_mask;
|
||||
rt_thread_ready_priority_group |= RT_SCHED_PRIV(thread).number_mask;
|
||||
|
||||
__exit:
|
||||
/* enable interrupt */
|
||||
@@ -416,7 +481,7 @@ __exit:
|
||||
*
|
||||
* @note Please do not invoke this function in user application.
|
||||
*/
|
||||
void rt_schedule_remove_thread(struct rt_thread *thread)
|
||||
void rt_sched_remove_thread(struct rt_thread *thread)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
@@ -427,20 +492,20 @@ void rt_schedule_remove_thread(struct rt_thread *thread)
|
||||
|
||||
LOG_D("remove thread[%.*s], the priority: %d",
|
||||
RT_NAME_MAX, thread->parent.name,
|
||||
thread->current_priority);
|
||||
RT_SCHED_PRIV(rt_current_thread).current_priority);
|
||||
|
||||
/* remove thread from ready list */
|
||||
rt_list_remove(&(thread->tlist));
|
||||
if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
|
||||
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
|
||||
if (rt_list_isempty(&(rt_thread_priority_table[RT_SCHED_PRIV(thread).current_priority])))
|
||||
{
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
rt_thread_ready_table[thread->number] &= ~thread->high_mask;
|
||||
if (rt_thread_ready_table[thread->number] == 0)
|
||||
rt_thread_ready_table[RT_SCHED_PRIV(thread).number] &= ~RT_SCHED_PRIV(thread).high_mask;
|
||||
if (rt_thread_ready_table[RT_SCHED_PRIV(thread).number] == 0)
|
||||
{
|
||||
rt_thread_ready_priority_group &= ~thread->number_mask;
|
||||
rt_thread_ready_priority_group &= ~RT_SCHED_PRIV(thread).number_mask;
|
||||
}
|
||||
#else
|
||||
rt_thread_ready_priority_group &= ~thread->number_mask;
|
||||
rt_thread_ready_priority_group &= ~RT_SCHED_PRIV(thread).number_mask;
|
||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||
}
|
||||
|
||||
@@ -448,12 +513,54 @@ void rt_schedule_remove_thread(struct rt_thread *thread)
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEBUG
|
||||
|
||||
static volatile int _critical_error_occurred = 0;
|
||||
|
||||
void rt_exit_critical_safe(rt_base_t critical_level)
|
||||
{
|
||||
rt_base_t level;
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
if (!_critical_error_occurred)
|
||||
{
|
||||
if (critical_level != rt_scheduler_lock_nest)
|
||||
{
|
||||
int dummy = 1;
|
||||
_critical_error_occurred = 1;
|
||||
|
||||
rt_kprintf("%s: un-compatible critical level\n" \
|
||||
"\tCurrent %d\n\tCaller %d\n",
|
||||
__func__, rt_scheduler_lock_nest,
|
||||
critical_level);
|
||||
rt_backtrace();
|
||||
|
||||
while (dummy) ;
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
rt_exit_critical();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rt_exit_critical_safe(rt_base_t critical_level)
|
||||
{
|
||||
return rt_exit_critical();
|
||||
}
|
||||
|
||||
#endif
|
||||
RTM_EXPORT(rt_exit_critical_safe);
|
||||
|
||||
/**
|
||||
* @brief This function will lock the thread scheduler.
|
||||
*/
|
||||
void rt_enter_critical(void)
|
||||
rt_base_t rt_enter_critical(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
rt_base_t critical_level;
|
||||
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
@@ -463,9 +570,12 @@ void rt_enter_critical(void)
|
||||
* enough and does not check here
|
||||
*/
|
||||
rt_scheduler_lock_nest ++;
|
||||
critical_level = rt_scheduler_lock_nest;
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return critical_level;
|
||||
}
|
||||
RTM_EXPORT(rt_enter_critical);
|
||||
|
||||
@@ -511,5 +621,10 @@ rt_uint16_t rt_critical_level(void)
|
||||
}
|
||||
RTM_EXPORT(rt_critical_level);
|
||||
|
||||
rt_err_t rt_sched_thread_bind_cpu(struct rt_thread *thread, int cpu)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
/**@endcond*/
|
||||
|
||||
+73
-51
@@ -29,6 +29,8 @@
|
||||
#define sig_mask(sig_no) (1u << sig_no)
|
||||
#define sig_valid(sig_no) (sig_no >= 0 && sig_no < RT_SIG_MAX)
|
||||
|
||||
static struct rt_spinlock _thread_signal_lock = RT_SPINLOCK_INIT;
|
||||
|
||||
struct siginfo_node
|
||||
{
|
||||
siginfo_t si;
|
||||
@@ -63,7 +65,7 @@ static void _signal_entry(void *parameter)
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
LOG_D("switch back to: 0x%08x\n", tid->sp);
|
||||
tid->stat &= ~RT_THREAD_STAT_SIGNAL;
|
||||
RT_SCHED_CTX(tid).stat &= ~RT_THREAD_STAT_SIGNAL;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_hw_context_switch_to((rt_base_t)¶meter, tid);
|
||||
@@ -86,16 +88,16 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
/* thread is not interested in pended signals */
|
||||
if (!(tid->sig_pending & tid->sig_mask))
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tid->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
|
||||
if ((RT_SCHED_CTX(tid).stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
|
||||
{
|
||||
/* resume thread to handle signal */
|
||||
#ifdef RT_USING_SMART
|
||||
@@ -104,9 +106,9 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
rt_thread_resume(tid);
|
||||
#endif
|
||||
/* add signal state */
|
||||
tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
|
||||
RT_SCHED_CTX(tid).stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
/* re-schedule */
|
||||
rt_schedule();
|
||||
@@ -116,9 +118,9 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
if (tid == rt_thread_self())
|
||||
{
|
||||
/* add signal state */
|
||||
tid->stat |= RT_THREAD_STAT_SIGNAL;
|
||||
RT_SCHED_CTX(tid).stat |= RT_THREAD_STAT_SIGNAL;
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
/* do signal action in self thread context */
|
||||
if (rt_interrupt_get_nest() == 0)
|
||||
@@ -126,16 +128,16 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
rt_thread_handle_sig(RT_TRUE);
|
||||
}
|
||||
}
|
||||
else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
|
||||
else if (!((RT_SCHED_CTX(tid).stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
|
||||
{
|
||||
/* add signal state */
|
||||
tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
|
||||
RT_SCHED_CTX(tid).stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
{
|
||||
int cpu_id;
|
||||
|
||||
cpu_id = tid->oncpu;
|
||||
cpu_id = RT_SCHED_CTX(tid).oncpu;
|
||||
if ((cpu_id != RT_CPU_DETACHED) && (cpu_id != rt_hw_cpu_id()))
|
||||
{
|
||||
rt_uint32_t cpu_mask;
|
||||
@@ -146,13 +148,13 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
}
|
||||
#else
|
||||
/* point to the signal handle entry */
|
||||
tid->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
RT_SCHED_CTX(tid).stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
tid->sig_ret = tid->sp;
|
||||
tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
|
||||
(void *)((char *)tid->sig_ret - 32), RT_NULL);
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
LOG_D("signal stack pointer @ 0x%08x", tid->sp);
|
||||
|
||||
/* re-schedule */
|
||||
@@ -160,7 +162,7 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,37 +170,38 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
#ifdef RT_USING_SMP
|
||||
void *rt_signal_check(void* context)
|
||||
{
|
||||
rt_base_t level;
|
||||
rt_sched_lock_level_t level;
|
||||
int cpu_id;
|
||||
struct rt_cpu* pcpu;
|
||||
struct rt_thread *current_thread;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
cpu_id = rt_hw_cpu_id();
|
||||
pcpu = rt_cpu_index(cpu_id);
|
||||
current_thread = pcpu->current_thread;
|
||||
|
||||
if (pcpu->irq_nest)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
return context;
|
||||
}
|
||||
|
||||
if (current_thread->cpus_lock_nest == 1)
|
||||
{
|
||||
if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
if (RT_SCHED_CTX(current_thread).stat & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
{
|
||||
void *sig_context;
|
||||
|
||||
current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
RT_SCHED_CTX(current_thread).stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
sig_context = rt_hw_stack_init((void *)_signal_entry, context,
|
||||
(void*)((char*)context - 32), RT_NULL);
|
||||
return sig_context;
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
return context;
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
@@ -227,10 +230,14 @@ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
|
||||
|
||||
if (!sig_valid(signo)) return SIG_ERR;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
if (tid->sig_vectors == RT_NULL)
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
rt_thread_alloc_sig(tid);
|
||||
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
}
|
||||
|
||||
if (tid->sig_vectors)
|
||||
@@ -241,7 +248,7 @@ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
|
||||
else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
|
||||
else tid->sig_vectors[signo] = handler;
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
return old;
|
||||
}
|
||||
@@ -262,11 +269,11 @@ void rt_signal_mask(int signo)
|
||||
rt_base_t level;
|
||||
rt_thread_t tid = rt_thread_self();
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
tid->sig_mask &= ~sig_mask(signo);
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,19 +292,19 @@ void rt_signal_unmask(int signo)
|
||||
rt_base_t level;
|
||||
rt_thread_t tid = rt_thread_self();
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
tid->sig_mask |= sig_mask(signo);
|
||||
|
||||
/* let thread handle pended signals */
|
||||
if (tid->sig_mask & tid->sig_pending)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
_signal_deliver(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +342,7 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
|
||||
/* clear siginfo to avoid unknown value */
|
||||
memset(si, 0x0, sizeof(rt_siginfo_t));
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
/* already pending */
|
||||
if (tid->sig_pending & *set) goto __done;
|
||||
@@ -349,7 +356,7 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
|
||||
/* suspend self thread */
|
||||
rt_thread_suspend_with_flag(tid, RT_UNINTERRUPTIBLE);
|
||||
/* set thread stat as waiting for signal */
|
||||
tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
|
||||
RT_SCHED_CTX(tid).stat |= RT_THREAD_STAT_SIGNAL_WAIT;
|
||||
|
||||
/* start timeout timer */
|
||||
if (timeout != RT_WAITING_FOREVER)
|
||||
@@ -360,21 +367,21 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
|
||||
&timeout);
|
||||
rt_timer_start(&(tid->thread_timer));
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
/* do thread scheduling */
|
||||
rt_schedule();
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
/* remove signal waiting flag */
|
||||
tid->stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;
|
||||
RT_SCHED_CTX(tid).stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;
|
||||
|
||||
/* check errno of thread */
|
||||
if (tid->error == -RT_ETIMEOUT)
|
||||
{
|
||||
tid->error = RT_EOK;
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
/* timer timeout */
|
||||
ret = -RT_ETIMEOUT;
|
||||
@@ -428,7 +435,7 @@ __done:
|
||||
}
|
||||
|
||||
__done_int:
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
__done_return:
|
||||
return ret;
|
||||
@@ -441,11 +448,11 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||
rt_thread_t tid = rt_thread_self();
|
||||
struct siginfo_node *si_node;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
if (tid->sig_pending & tid->sig_mask)
|
||||
{
|
||||
/* if thread is not waiting for signal */
|
||||
if (!(tid->stat & RT_THREAD_STAT_SIGNAL_WAIT))
|
||||
if (!(RT_SCHED_CTX(tid).stat & RT_THREAD_STAT_SIGNAL_WAIT))
|
||||
{
|
||||
while (tid->sig_pending & tid->sig_mask)
|
||||
{
|
||||
@@ -464,12 +471,12 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||
signo = si_node->si.si_signo;
|
||||
handler = tid->sig_vectors[signo];
|
||||
tid->sig_pending &= ~sig_mask(signo);
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
LOG_D("handle signal: %d, handler 0x%08x", signo, handler);
|
||||
if (handler) handler(signo);
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
error = -RT_EINTR;
|
||||
|
||||
rt_mp_free(si_node); /* release this siginfo node */
|
||||
@@ -480,7 +487,7 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||
/* whether clean signal status */
|
||||
if (clean_state == RT_TRUE)
|
||||
{
|
||||
tid->stat &= ~RT_THREAD_STAT_SIGNAL;
|
||||
RT_SCHED_CTX(tid).stat &= ~RT_THREAD_STAT_SIGNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -488,12 +495,13 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||
}
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
}
|
||||
|
||||
void rt_thread_alloc_sig(rt_thread_t tid)
|
||||
{
|
||||
int index;
|
||||
rt_bool_t need_free = RT_FALSE;
|
||||
rt_base_t level;
|
||||
rt_sighandler_t *vectors;
|
||||
|
||||
@@ -505,9 +513,23 @@ void rt_thread_alloc_sig(rt_thread_t tid)
|
||||
vectors[index] = _signal_default_handler;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
tid->sig_vectors = vectors;
|
||||
rt_hw_interrupt_enable(level);
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
if (tid->sig_vectors == RT_NULL)
|
||||
{
|
||||
tid->sig_vectors = vectors;
|
||||
}
|
||||
else
|
||||
{
|
||||
need_free = RT_TRUE;
|
||||
}
|
||||
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
if (need_free)
|
||||
{
|
||||
rt_free(vectors);
|
||||
}
|
||||
}
|
||||
|
||||
void rt_thread_free_sig(rt_thread_t tid)
|
||||
@@ -516,13 +538,13 @@ void rt_thread_free_sig(rt_thread_t tid)
|
||||
struct siginfo_node *si_node;
|
||||
rt_sighandler_t *sig_vectors;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
si_node = (struct siginfo_node *)tid->si_list;
|
||||
tid->si_list = RT_NULL;
|
||||
|
||||
sig_vectors = tid->sig_vectors;
|
||||
tid->sig_vectors = RT_NULL;
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
if (si_node)
|
||||
{
|
||||
@@ -570,7 +592,7 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||
si.si_code = SI_USER;
|
||||
si.si_value.sival_ptr = RT_NULL;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
if (tid->sig_pending & sig_mask(sig))
|
||||
{
|
||||
/* whether already emits this signal? */
|
||||
@@ -590,12 +612,12 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||
if (entry->si.si_signo == sig)
|
||||
{
|
||||
memcpy(&(entry->si), &si, sizeof(siginfo_t));
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
|
||||
si_node = (struct siginfo_node *) rt_mp_alloc(_siginfo_pool, 0);
|
||||
if (si_node)
|
||||
@@ -603,7 +625,7 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||
rt_slist_init(&(si_node->list));
|
||||
memcpy(&(si_node->si), &si, sizeof(siginfo_t));
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
level = rt_spin_lock_irqsave(&_thread_signal_lock);
|
||||
|
||||
if (tid->si_list)
|
||||
{
|
||||
@@ -620,7 +642,7 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||
/* a new signal */
|
||||
tid->sig_pending |= sig_mask(sig);
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_spin_unlock_irqrestore(&_thread_signal_lock, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+273
-356
File diff suppressed because it is too large
Load Diff
+88
-59
@@ -20,6 +20,7 @@
|
||||
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to timer.c
|
||||
* 2022-04-19 Stanley Correct descriptions
|
||||
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
|
||||
* 2024-01-25 Shell add RT_TIMER_FLAG_THREAD_TIMER for timer to sync with sched
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
@@ -31,7 +32,7 @@
|
||||
|
||||
/* hard timer list */
|
||||
static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||
static struct rt_spinlock _hard_spinlock;
|
||||
static struct rt_spinlock _htimer_lock;
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
|
||||
@@ -50,7 +51,7 @@ static struct rt_spinlock _hard_spinlock;
|
||||
static rt_uint8_t _soft_timer_status = RT_SOFT_TIMER_IDLE;
|
||||
/* soft timer list */
|
||||
static rt_list_t _soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||
static struct rt_spinlock _soft_spinlock;
|
||||
static struct rt_spinlock _stimer_lock;
|
||||
static struct rt_thread _timer_thread;
|
||||
static struct rt_semaphore _soft_timer_sem;
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
@@ -94,6 +95,35 @@ void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer))
|
||||
/**@}*/
|
||||
#endif /* RT_USING_HOOK */
|
||||
|
||||
rt_inline struct rt_spinlock* _timerlock_idx(struct rt_timer *timer)
|
||||
{
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
return &_stimer_lock;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
return &_htimer_lock;
|
||||
}
|
||||
}
|
||||
|
||||
rt_inline rt_list_t* _timerhead_idx(struct rt_timer *timer)
|
||||
{
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
/* insert timer to soft timer list */
|
||||
return _soft_timer_list;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
/* insert timer to system timer list */
|
||||
return _timer_list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief [internal] The init funtion of timer
|
||||
@@ -280,17 +310,7 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
RT_ASSERT(rt_object_is_systemobject(&timer->parent));
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
spinlock = &_soft_spinlock;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
spinlock = &_hard_spinlock;
|
||||
}
|
||||
|
||||
spinlock = _timerlock_idx(timer);
|
||||
level = rt_spin_lock_irqsave(spinlock);
|
||||
|
||||
_timer_remove(timer);
|
||||
@@ -325,6 +345,7 @@ RTM_EXPORT(rt_timer_detach);
|
||||
*
|
||||
* RT_TIMER_FLAG_HARD_TIMER Hardware timer
|
||||
* RT_TIMER_FLAG_SOFT_TIMER Software timer
|
||||
* RT_TIMER_FLAG_THREAD_TIMER Thread timer
|
||||
*
|
||||
* NOTE:
|
||||
* You can use multiple values with "|" logical operator. By default, system will use the RT_TIME_FLAG_HARD_TIMER.
|
||||
@@ -373,16 +394,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE);
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
spinlock = &_soft_spinlock;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
spinlock = &_hard_spinlock;
|
||||
}
|
||||
spinlock = _timerlock_idx(timer);
|
||||
|
||||
level = rt_spin_lock_irqsave(spinlock);
|
||||
|
||||
@@ -485,6 +497,8 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
|
||||
*/
|
||||
rt_err_t rt_timer_start(rt_timer_t timer)
|
||||
{
|
||||
rt_sched_lock_level_t slvl;
|
||||
int is_thread_timer = 0;
|
||||
struct rt_spinlock *spinlock;
|
||||
rt_list_t *timer_list;
|
||||
rt_base_t level;
|
||||
@@ -498,13 +512,24 @@ rt_err_t rt_timer_start(rt_timer_t timer)
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
timer_list = _soft_timer_list;
|
||||
spinlock = &_soft_spinlock;
|
||||
spinlock = &_stimer_lock;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
timer_list = _timer_list;
|
||||
spinlock = &_hard_spinlock;
|
||||
spinlock = &_htimer_lock;
|
||||
}
|
||||
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_THREAD_TIMER)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
is_thread_timer = 1;
|
||||
rt_sched_lock(&slvl);
|
||||
|
||||
thread = rt_container_of(timer, struct rt_thread, thread_timer);
|
||||
RT_ASSERT(rt_object_get_type(&thread->parent) == RT_Object_Class_Thread);
|
||||
rt_sched_thread_timer_start(thread);
|
||||
}
|
||||
|
||||
level = rt_spin_lock_irqsave(spinlock);
|
||||
@@ -512,17 +537,19 @@ rt_err_t rt_timer_start(rt_timer_t timer)
|
||||
err = _timer_start(timer_list, timer);
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (err == RT_EOK)
|
||||
if (err == RT_EOK && (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER))
|
||||
{
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
rt_sem_release(&_soft_timer_sem);
|
||||
}
|
||||
rt_sem_release(&_soft_timer_sem);
|
||||
}
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
|
||||
rt_spin_unlock_irqrestore(spinlock, level);
|
||||
|
||||
if (is_thread_timer)
|
||||
{
|
||||
rt_sched_unlock(slvl);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
RTM_EXPORT(rt_timer_start);
|
||||
@@ -543,16 +570,8 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
|
||||
RT_ASSERT(timer != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
spinlock = &_soft_spinlock;
|
||||
}
|
||||
else
|
||||
#endif /* RT_USING_TIMER_SOFT */
|
||||
{
|
||||
spinlock = &_hard_spinlock;
|
||||
}
|
||||
spinlock = _timerlock_idx(timer);
|
||||
|
||||
level = rt_spin_lock_irqsave(spinlock);
|
||||
|
||||
if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||
@@ -565,6 +584,7 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
|
||||
_timer_remove(timer);
|
||||
/* change status */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
|
||||
rt_spin_unlock_irqrestore(spinlock, level);
|
||||
|
||||
return RT_EOK;
|
||||
@@ -582,10 +602,16 @@ RTM_EXPORT(rt_timer_stop);
|
||||
*/
|
||||
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
||||
{
|
||||
struct rt_spinlock *spinlock;
|
||||
rt_base_t level;
|
||||
|
||||
/* parameter check */
|
||||
RT_ASSERT(timer != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
|
||||
spinlock = _timerlock_idx(timer);
|
||||
|
||||
level = rt_spin_lock_irqsave(spinlock);
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_TIMER_CTRL_GET_TIME:
|
||||
@@ -640,6 +666,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rt_spin_unlock_irqrestore(spinlock, level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
@@ -660,21 +687,23 @@ void rt_timer_check(void)
|
||||
|
||||
RT_ASSERT(rt_interrupt_get_nest() > 0);
|
||||
|
||||
LOG_D("timer check enter");
|
||||
|
||||
level = rt_spin_lock_irqsave(&_htimer_lock);
|
||||
|
||||
current_tick = rt_tick_get();
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* Running on core 0 only */
|
||||
if (rt_hw_cpu_id() != 0)
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
rt_list_init(&list);
|
||||
|
||||
LOG_D("timer check enter");
|
||||
|
||||
current_tick = rt_tick_get();
|
||||
|
||||
level = rt_spin_lock_irqsave(&_hard_spinlock);
|
||||
|
||||
while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
||||
{
|
||||
t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
|
||||
@@ -696,7 +725,7 @@ void rt_timer_check(void)
|
||||
}
|
||||
/* add timer to temporary list */
|
||||
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
||||
rt_spin_unlock_irqrestore(&_hard_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
||||
/* call timeout function */
|
||||
t->timeout_func(t->parameter);
|
||||
|
||||
@@ -705,7 +734,7 @@ void rt_timer_check(void)
|
||||
|
||||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||
LOG_D("current tick: %d", current_tick);
|
||||
level = rt_spin_lock_irqsave(&_hard_spinlock);
|
||||
level = rt_spin_lock_irqsave(&_htimer_lock);
|
||||
/* Check whether the timer object is detached or started again */
|
||||
if (rt_list_isempty(&list))
|
||||
{
|
||||
@@ -722,7 +751,7 @@ void rt_timer_check(void)
|
||||
}
|
||||
else break;
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&_hard_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
||||
LOG_D("timer check leave");
|
||||
}
|
||||
|
||||
@@ -736,9 +765,9 @@ rt_tick_t rt_timer_next_timeout_tick(void)
|
||||
rt_base_t level;
|
||||
rt_tick_t next_timeout = RT_TICK_MAX;
|
||||
|
||||
level = rt_spin_lock_irqsave(&_hard_spinlock);
|
||||
level = rt_spin_lock_irqsave(&_htimer_lock);
|
||||
_timer_list_next_timeout(_timer_list, &next_timeout);
|
||||
rt_spin_unlock_irqrestore(&_hard_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
||||
|
||||
return next_timeout;
|
||||
}
|
||||
@@ -757,7 +786,7 @@ static void _soft_timer_check(void)
|
||||
|
||||
rt_list_init(&list);
|
||||
LOG_D("software timer check enter");
|
||||
level = rt_spin_lock_irqsave(&_soft_spinlock);
|
||||
level = rt_spin_lock_irqsave(&_stimer_lock);
|
||||
|
||||
while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
||||
{
|
||||
@@ -785,7 +814,7 @@ static void _soft_timer_check(void)
|
||||
|
||||
_soft_timer_status = RT_SOFT_TIMER_BUSY;
|
||||
|
||||
rt_spin_unlock_irqrestore(&_soft_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_stimer_lock, level);
|
||||
|
||||
/* call timeout function */
|
||||
t->timeout_func(t->parameter);
|
||||
@@ -793,7 +822,7 @@ static void _soft_timer_check(void)
|
||||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||
LOG_D("current tick: %d", current_tick);
|
||||
|
||||
level = rt_spin_lock_irqsave(&_soft_spinlock);
|
||||
level = rt_spin_lock_irqsave(&_stimer_lock);
|
||||
|
||||
_soft_timer_status = RT_SOFT_TIMER_IDLE;
|
||||
/* Check whether the timer object is detached or started again */
|
||||
@@ -813,7 +842,7 @@ static void _soft_timer_check(void)
|
||||
else break; /* not check anymore */
|
||||
}
|
||||
|
||||
rt_spin_unlock_irqrestore(&_soft_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_stimer_lock, level);
|
||||
|
||||
LOG_D("software timer check leave");
|
||||
}
|
||||
@@ -836,9 +865,9 @@ static void _timer_thread_entry(void *parameter)
|
||||
while (1)
|
||||
{
|
||||
/* get the next timeout tick */
|
||||
level = rt_spin_lock_irqsave(&_soft_spinlock);
|
||||
level = rt_spin_lock_irqsave(&_stimer_lock);
|
||||
ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout);
|
||||
rt_spin_unlock_irqrestore(&_soft_spinlock, level);
|
||||
rt_spin_unlock_irqrestore(&_stimer_lock, level);
|
||||
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
@@ -878,7 +907,7 @@ void rt_system_timer_init(void)
|
||||
{
|
||||
rt_list_init(_timer_list + i);
|
||||
}
|
||||
rt_spin_lock_init(&_hard_spinlock);
|
||||
rt_spin_lock_init(&_htimer_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -897,7 +926,7 @@ void rt_system_timer_thread_init(void)
|
||||
{
|
||||
rt_list_init(_soft_timer_list + i);
|
||||
}
|
||||
rt_spin_lock_init(&_soft_spinlock);
|
||||
rt_spin_lock_init(&_stimer_lock);
|
||||
rt_sem_init(&_soft_timer_sem, "stimer", 0, RT_IPC_FLAG_PRIO);
|
||||
/* start software timer thread */
|
||||
rt_thread_init(&_timer_thread,
|
||||
|
||||
Reference in New Issue
Block a user