diff options
| author | xqyjlj <[email protected]> | 2023-10-25 20:31:25 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-25 20:31:25 +0800 |
| commit | 3283f54c7a0444b2e51ec79a4da57e7871528f05 (patch) | |
| tree | e4bcd748ad2362f16d0dea5c5da62922de466999 /src | |
| parent | 91fc52df3635d5dda8285616420f08efa79cea04 (diff) | |
🎈 perf: perf rt_hw_interrupt_disable/enable (#8042)
Signed-off-by: Shell <[email protected]>
Co-authored-by: Shell <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/Kconfig | 7 | ||||
| -rw-r--r-- | src/clock.c | 36 | ||||
| -rw-r--r-- | src/components.c | 6 | ||||
| -rw-r--r-- | src/cpu.c | 121 | ||||
| -rw-r--r-- | src/idle.c | 39 | ||||
| -rw-r--r-- | src/ipc.c | 319 | ||||
| -rw-r--r-- | src/irq.c | 30 | ||||
| -rw-r--r-- | src/mempool.c | 42 | ||||
| -rw-r--r-- | src/object.c | 96 | ||||
| -rw-r--r-- | src/scheduler_mp.c | 504 | ||||
| -rw-r--r-- | src/signal.c | 11 | ||||
| -rw-r--r-- | src/thread.c | 168 | ||||
| -rw-r--r-- | src/timer.c | 165 |
13 files changed, 767 insertions, 777 deletions
diff --git a/src/Kconfig b/src/Kconfig index e76efca64d..6ff7b75788 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -219,6 +219,13 @@ menuconfig RT_USING_DEBUG bool "Enable page leaking tracer" depends on ARCH_MM_MMU default n + + if RT_USING_SMP + config RT_DEBUGING_SPINLOCK + bool "Enable spinlock debugging" + default n + endif + endif menu "Inter-Thread communication" diff --git a/src/clock.c b/src/clock.c index ac146192b7..7c948f3bc1 100644 --- a/src/clock.c +++ b/src/clock.c @@ -15,16 +15,18 @@ * 2018-11-22 Jesven add per cpu tick * 2020-12-29 Meco Man implement rt_tick_get_millisecond() * 2021-06-01 Meco Man add critical section projection for rt_tick_increase() + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable * 2023-10-16 RiceChen fix: only the main core detection rt_timer_check(), in SMP mode */ #include <rthw.h> #include <rtthread.h> +#include <rtatomic.h> #ifdef RT_USING_SMP #define rt_tick rt_cpu_index(0)->tick #else -static volatile rt_tick_t rt_tick = 0; +static volatile rt_atomic_t rt_tick = 0; #endif /* RT_USING_SMP */ #ifndef __on_rt_tick_hook @@ -67,7 +69,7 @@ void rt_tick_sethook(void (*hook)(void)) rt_tick_t rt_tick_get(void) { /* return the global tick */ - return rt_tick; + return (rt_tick_t)rt_atomic_load(&(rt_tick)); } RTM_EXPORT(rt_tick_get); @@ -78,11 +80,7 @@ RTM_EXPORT(rt_tick_get); */ void rt_tick_set(rt_tick_t tick) { - rt_base_t level; - - level = rt_hw_interrupt_disable(); - rt_tick = tick; - rt_hw_interrupt_enable(level); + rt_atomic_store(&(rt_tick), tick); } /** @@ -93,34 +91,32 @@ void rt_tick_increase(void) { struct rt_thread *thread; rt_base_t level; + rt_atomic_t oldval = 0; RT_OBJECT_HOOK_CALL(rt_tick_hook, ()); - - level = rt_hw_interrupt_disable(); - /* increase the global tick */ #ifdef RT_USING_SMP - rt_cpu_self()->tick ++; + rt_atomic_add(&(rt_cpu_self()->tick), 1); #else - ++ rt_tick; + rt_atomic_add(&(rt_tick), 1); #endif /* RT_USING_SMP */ /* check time slice */ thread = rt_thread_self(); - - -- thread->remaining_tick; - if (thread->remaining_tick == 0) + rt_get_thread_struct(thread); + 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)) { - /* change to initialized tick */ - thread->remaining_tick = thread->init_tick; thread->stat |= RT_THREAD_STAT_YIELD; - - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); + rt_put_thread_struct(thread); rt_schedule(); } else { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); + rt_put_thread_struct(thread); } /* check timer */ diff --git a/src/components.c b/src/components.c index c9a25c76dc..33d7ec38e6 100644 --- a/src/components.c +++ b/src/components.c @@ -15,6 +15,7 @@ * in some IDEs. * 2015-07-29 Arda.Fu Add support to use RT_USING_USER_MAIN with IAR * 2018-11-22 Jesven Add secondary cpu boot up + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> @@ -235,7 +236,10 @@ void rt_application_init(void) */ int rtthread_startup(void) { - rt_hw_interrupt_disable(); +#ifdef RT_USING_SMP + rt_hw_spin_lock_init(&_cpus_lock); +#endif + rt_hw_local_irq_disable(); /* board level initialization * NOTE: please initialize heap inside board initialization. @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-10-30 Bernard The first version + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> #include <rtthread.h> @@ -17,57 +18,19 @@ #ifdef RT_USING_SMP static struct rt_cpu _cpus[RT_CPUS_NR]; rt_hw_spinlock_t _cpus_lock; +#if defined(RT_DEBUGING_SPINLOCK) +void *_cpus_lock_owner = 0; +void *_cpus_lock_pc = 0; -/* - * @brief disable scheduler - */ -static void _cpu_preempt_disable(void) -{ - rt_base_t level; - struct rt_thread *current_thread; - - /* disable interrupt */ - level = rt_hw_local_irq_disable(); +#define __OWNER_MAGIC ((void *)0xdeadbeaf) - current_thread = rt_thread_self(); - if (!current_thread) - { - rt_hw_local_irq_enable(level); - return; - } - - /* lock scheduler for local cpu */ - current_thread->scheduler_lock_nest ++; - - /* enable interrupt */ - rt_hw_local_irq_enable(level); -} - -/* - * @brief enable scheduler - */ -static void _cpu_preempt_enable(void) -{ - rt_base_t level; - struct rt_thread *current_thread; - - /* disable interrupt */ - level = rt_hw_local_irq_disable(); - - current_thread = rt_thread_self(); - if (!current_thread) - { - rt_hw_local_irq_enable(level); - return; - } - - /* unlock scheduler for local cpu */ - current_thread->scheduler_lock_nest --; +#if defined (__GNUC__) +#define __GET_RETURN_ADDRESS __builtin_return_address(0) +#else +#define __GET_RETURN_ADDRESS RT_NULL +#endif - rt_schedule(); - /* enable interrupt */ - rt_hw_local_irq_enable(level); -} +#endif /* RT_DEBUGING_SPINLOCK */ /** * @brief Initialize a static spinlock object. @@ -90,8 +53,14 @@ RTM_EXPORT(rt_spin_lock_init) */ void rt_spin_lock(struct rt_spinlock *lock) { - _cpu_preempt_disable(); 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 */ } RTM_EXPORT(rt_spin_lock) @@ -103,7 +72,10 @@ RTM_EXPORT(rt_spin_lock) void rt_spin_unlock(struct rt_spinlock *lock) { rt_hw_spin_unlock(&lock->lock); - _cpu_preempt_enable(); +#if defined(RT_DEBUGING_SPINLOCK) + lock->owner = __OWNER_MAGIC; + lock->pc = RT_NULL; +#endif /* RT_DEBUGING_SPINLOCK */ } RTM_EXPORT(rt_spin_unlock) @@ -121,11 +93,15 @@ rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock) { unsigned long level; - _cpu_preempt_disable(); - level = rt_hw_local_irq_disable(); 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 */ return level; } RTM_EXPORT(rt_spin_lock_irqsave) @@ -139,10 +115,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_hw_spin_unlock(&lock->lock); rt_hw_local_irq_enable(level); - - _cpu_preempt_enable(); } RTM_EXPORT(rt_spin_unlock_irqrestore) @@ -183,13 +161,16 @@ rt_base_t rt_cpus_lock(void) pcpu = rt_cpu_self(); if (pcpu->current_thread != RT_NULL) { - register rt_ubase_t lock_nest = pcpu->current_thread->cpus_lock_nest; + register rt_ubase_t lock_nest = rt_atomic_load(&(pcpu->current_thread->cpus_lock_nest)); - pcpu->current_thread->cpus_lock_nest++; + rt_atomic_add(&(pcpu->current_thread->cpus_lock_nest), 1); if (lock_nest == 0) { - pcpu->current_thread->scheduler_lock_nest++; rt_hw_spin_lock(&_cpus_lock); +#if defined(RT_DEBUGING_SPINLOCK) + _cpus_lock_owner = pcpu->current_thread; + _cpus_lock_pc = __GET_RETURN_ADDRESS; +#endif } } @@ -208,12 +189,15 @@ void rt_cpus_unlock(rt_base_t level) if (pcpu->current_thread != RT_NULL) { - RT_ASSERT(pcpu->current_thread->cpus_lock_nest > 0); - pcpu->current_thread->cpus_lock_nest--; + RT_ASSERT(rt_atomic_load(&(pcpu->current_thread->cpus_lock_nest)) > 0); + rt_atomic_sub(&(pcpu->current_thread->cpus_lock_nest), 1); if (pcpu->current_thread->cpus_lock_nest == 0) { - pcpu->current_thread->scheduler_lock_nest--; +#if defined(RT_DEBUGING_SPINLOCK) + _cpus_lock_owner = __OWNER_MAGIC; + _cpus_lock_pc = RT_NULL; +#endif rt_hw_spin_unlock(&_cpus_lock); } } @@ -235,11 +219,18 @@ void rt_cpus_lock_status_restore(struct rt_thread *thread) #if defined(ARCH_MM_MMU) && defined(RT_USING_SMART) lwp_aspace_switch(thread); #endif - pcpu->current_thread = thread; - if (!thread->cpus_lock_nest) + if (pcpu->current_thread != RT_NULL ) { - rt_hw_spin_unlock(&_cpus_lock); + rt_spin_unlock(&(pcpu->current_thread->spinlock)); + if ((pcpu->current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING) + { + rt_schedule_insert_thread(pcpu->current_thread); + } + rt_put_thread_struct(pcpu->current_thread); + } + pcpu->current_thread = thread; + rt_get_thread_struct(thread); } RTM_EXPORT(rt_cpus_lock_status_restore); -#endif +#endif /* RT_USING_SMP */ diff --git a/src/idle.c b/src/idle.c index dac65eb744..ca5064e346 100644 --- a/src/idle.c +++ b/src/idle.c @@ -16,6 +16,7 @@ * 2018-11-22 Jesven add per cpu idle task * combine the code of primary and secondary cpu * 2021-11-15 THEWON Remove duplicate work between idle and _thread_exit + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> @@ -42,7 +43,8 @@ #define _CPUS_NR RT_CPUS_NR static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct); - +static struct rt_mutex _defunct_mutex; +static rt_atomic_t _idle_inited = 0; static struct rt_thread idle_thread[_CPUS_NR]; rt_align(RT_ALIGN_SIZE) static rt_uint8_t idle_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE]; @@ -78,12 +80,8 @@ static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void); rt_err_t rt_thread_idle_sethook(void (*hook)(void)) { rt_size_t i; - rt_base_t level; rt_err_t ret = -RT_EFULL; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++) { if (idle_hook_list[i] == RT_NULL) @@ -93,9 +91,6 @@ rt_err_t rt_thread_idle_sethook(void (*hook)(void)) break; } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return ret; } @@ -110,12 +105,8 @@ rt_err_t rt_thread_idle_sethook(void (*hook)(void)) rt_err_t rt_thread_idle_delhook(void (*hook)(void)) { rt_size_t i; - rt_base_t level; rt_err_t ret = -RT_ENOSYS; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++) { if (idle_hook_list[i] == hook) @@ -125,9 +116,6 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) break; } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return ret; } @@ -142,7 +130,13 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void)) */ void rt_thread_defunct_enqueue(rt_thread_t thread) { + if (rt_atomic_load(&_idle_inited) == 0) + { + return; + } + rt_mutex_take(&_defunct_mutex, RT_WAITING_FOREVER); rt_list_insert_after(&_rt_thread_defunct, &thread->tlist); + rt_mutex_release(&_defunct_mutex); #ifdef RT_USING_SMP rt_sem_release(&system_sem); #endif @@ -158,8 +152,7 @@ rt_thread_t rt_thread_defunct_dequeue(void) rt_list_t *l = &_rt_thread_defunct; #ifdef RT_USING_SMP - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + rt_mutex_take(&_defunct_mutex, RT_WAITING_FOREVER); if (l->next != l) { thread = rt_list_entry(l->next, @@ -167,7 +160,8 @@ rt_thread_t rt_thread_defunct_dequeue(void) tlist); rt_list_remove(&(thread->tlist)); } - rt_hw_interrupt_enable(level); + rt_mutex_release(&_defunct_mutex); + RT_UNUSED(level); #else if (l->next != l) { @@ -204,6 +198,11 @@ static void rt_defunct_execute(void) { break; } + + while (rt_atomic_load(&(thread->ref_count))) + { + rt_thread_delay(5); + } #ifdef RT_USING_MODULE module = (struct rt_dlmodule*)thread->parent.module_id; if (module) @@ -341,7 +340,7 @@ void rt_thread_idle_init(void) #ifdef RT_USING_SMP RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2); - rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&system_sem, "defunct", 0, RT_IPC_FLAG_FIFO); /* create defunct thread */ rt_thread_init(&rt_system_thread, @@ -355,6 +354,8 @@ void rt_thread_idle_init(void) /* startup */ rt_thread_startup(&rt_system_thread); #endif + rt_mutex_init(&_defunct_mutex, "defunct_mutex", RT_IPC_FLAG_FIFO); + rt_atomic_store(&(_idle_inited), 1); } /** @@ -45,6 +45,7 @@ * 2022-10-15 Bernard add nested mutex feature * 2022-10-16 Bernard add prioceiling feature in mutex * 2023-04-16 Xin-zheqi redesigen queue recv and send function return real message size + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rtthread.h> @@ -133,6 +134,8 @@ rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list, rt_uint8_t flag, int suspend_flag) { + rt_base_t level_local; + level_local = rt_hw_local_irq_disable(); if ((thread->stat & RT_THREAD_SUSPEND_MASK) != RT_THREAD_SUSPEND_MASK) { rt_err_t ret = rt_thread_suspend_with_flag(thread, suspend_flag); @@ -140,6 +143,7 @@ rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list, /* suspend thread */ if (ret != RT_EOK) { + rt_hw_local_irq_enable(level_local); return ret; } } @@ -182,7 +186,7 @@ rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list, RT_ASSERT(0); break; } - + rt_hw_local_irq_enable(level_local); return RT_EOK; } @@ -240,13 +244,10 @@ rt_inline rt_err_t _ipc_list_resume(rt_list_t *list) rt_inline rt_err_t _ipc_list_resume_all(rt_list_t *list) { struct rt_thread *thread; - rt_base_t level; /* wakeup all suspended threads */ while (!rt_list_isempty(list)) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); /* get next suspended thread */ thread = rt_list_entry(list->next, struct rt_thread, tlist); @@ -259,9 +260,6 @@ rt_inline rt_err_t _ipc_list_resume_all(rt_list_t *list) * suspended list */ rt_thread_resume(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); } return RT_EOK; @@ -331,6 +329,7 @@ rt_err_t rt_sem_init(rt_sem_t sem, /* set parent */ sem->parent.parent.flag = flag; + rt_spin_lock_init(&(sem->spinlock)); return RT_EOK; } @@ -357,16 +356,20 @@ RTM_EXPORT(rt_sem_init); */ rt_err_t rt_sem_detach(rt_sem_t sem) { + rt_base_t level; + /* parameter check */ RT_ASSERT(sem != RT_NULL); RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore); RT_ASSERT(rt_object_is_systemobject(&sem->parent.parent)); + level = rt_spin_lock_irqsave(&(sem->spinlock)); /* wakeup all suspended threads */ _ipc_list_resume_all(&(sem->parent.suspend_thread)); /* detach semaphore object */ rt_object_detach(&(sem->parent.parent)); + rt_spin_unlock_irqrestore(&(sem->spinlock), level); return RT_EOK; } @@ -427,6 +430,7 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) /* set parent */ sem->parent.parent.flag = flag; + rt_spin_lock_init(&(sem->spinlock)); return sem; } @@ -514,8 +518,7 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag) /* current context checking */ RT_DEBUG_SCHEDULER_AVAILABLE(sem->value == 0 && timeout != 0); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(sem->spinlock)); LOG_D("thread %s take sem:%s, which value is: %d", rt_thread_self()->parent.name, @@ -526,17 +529,14 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag) { /* semaphore is available */ sem->value --; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(sem->spinlock), level); } else { /* no waiting, return with timeout */ if (timeout == 0) { - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&(sem->spinlock), level); return -RT_ETIMEOUT; } else @@ -557,7 +557,7 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag) suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(sem->spinlock), level); return ret; } @@ -574,7 +574,7 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag) } /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(sem->spinlock), level); /* do schedule */ rt_schedule(); @@ -655,8 +655,7 @@ rt_err_t rt_sem_release(rt_sem_t sem) need_schedule = RT_FALSE; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(sem->spinlock)); LOG_D("thread %s releases sem:%s, which value is: %d", rt_thread_self()->parent.name, @@ -677,13 +676,12 @@ rt_err_t rt_sem_release(rt_sem_t sem) } else { - rt_hw_interrupt_enable(level); /* enable interrupt */ + rt_spin_unlock_irqrestore(&(sem->spinlock), level); return -RT_EFULL; /* value overflowed */ } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(sem->spinlock), level); /* resume a thread, re-schedule */ if (need_schedule == RT_TRUE) @@ -722,18 +720,14 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) /* get value */ value = (rt_ubase_t)arg; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(sem->spinlock)); /* resume all waiting thread */ _ipc_list_resume_all(&sem->parent.suspend_thread); /* set new value */ sem->value = (rt_uint16_t)value; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&(sem->spinlock), level); rt_schedule(); return RT_EOK; @@ -894,6 +888,7 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; + rt_spin_lock_init(&(mutex->spinlock)); return RT_EOK; } @@ -927,12 +922,12 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex) RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex); RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent)); - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mutex->spinlock)); /* wakeup all suspended threads */ _ipc_list_resume_all(&(mutex->parent.suspend_thread)); /* remove mutex from thread's taken list */ rt_list_remove(&mutex->taken_list); - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); /* detach mutex object */ rt_object_detach(&(mutex->parent.parent)); @@ -953,7 +948,13 @@ void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread) { rt_uint8_t priority; rt_bool_t need_update = RT_FALSE; + rt_ubase_t level; + /* parameter check */ + RT_ASSERT(mutex != RT_NULL); + RT_ASSERT(thread != RT_NULL); + + level = rt_spin_lock_irqsave(&(mutex->spinlock)); rt_list_remove(&(thread->tlist)); /** @@ -994,6 +995,7 @@ void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread) _thread_update_priority(mutex->owner, priority, RT_UNINTERRUPTIBLE); } } + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); } @@ -1012,7 +1014,7 @@ rt_uint8_t rt_mutex_setprioceiling(rt_mutex_t mutex, rt_uint8_t priority) if ((mutex) && (priority < RT_THREAD_PRIORITY_MAX)) { /* critical section here if multiple updates to one mutex happen */ - rt_ubase_t level = rt_hw_interrupt_disable(); + rt_ubase_t level = rt_spin_lock_irqsave(&(mutex->spinlock)); ret_priority = mutex->ceiling_priority; mutex->ceiling_priority = priority; if (mutex->owner) @@ -1021,7 +1023,7 @@ rt_uint8_t rt_mutex_setprioceiling(rt_mutex_t mutex, rt_uint8_t priority) if (priority != mutex->owner->current_priority) _thread_update_priority(mutex->owner, priority, RT_UNINTERRUPTIBLE); } - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); } else { @@ -1043,10 +1045,16 @@ RTM_EXPORT(rt_mutex_setprioceiling); rt_uint8_t rt_mutex_getprioceiling(rt_mutex_t mutex) { rt_uint8_t prio = 0xFF; + rt_ubase_t level; + + /* parameter check */ + RT_ASSERT(mutex != RT_NULL); if (mutex) { + level = rt_spin_lock_irqsave(&(mutex->spinlock)); prio = mutex->ceiling_priority; + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); } return prio; @@ -1098,6 +1106,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; + rt_spin_lock_init(&(mutex->spinlock)); return mutex; } @@ -1133,12 +1142,12 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex) RT_DEBUG_NOT_IN_INTERRUPT; - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mutex->spinlock)); /* wakeup all suspended threads */ _ipc_list_resume_all(&(mutex->parent.suspend_thread)); /* remove mutex from thread's taken list */ rt_list_remove(&mutex->taken_list); - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); /* delete mutex object */ rt_object_delete(&(mutex->parent.parent)); @@ -1189,8 +1198,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend /* get current thread */ thread = rt_thread_self(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mutex->spinlock)); RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mutex->parent.parent))); @@ -1209,7 +1217,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend } else { - rt_hw_interrupt_enable(level); /* enable interrupt */ + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); return -RT_EFULL; /* value overflowed */ } } @@ -1241,8 +1249,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend /* set error as timeout */ thread->error = -RT_ETIMEOUT; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); return -RT_ETIMEOUT; } @@ -1261,7 +1268,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); return ret; } @@ -1291,14 +1298,12 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend rt_timer_start(&(thread->thread_timer)); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); /* do schedule */ rt_schedule(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mutex->spinlock)); if (thread->error == RT_EOK) { @@ -1349,8 +1354,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); /* clear pending object before exit */ thread->pending_object = RT_NULL; @@ -1363,8 +1367,7 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mutex->parent.parent))); @@ -1441,8 +1444,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) /* get current thread */ thread = rt_thread_self(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mutex->spinlock)); LOG_D("mutex_release:current thread %s, hold: %d", thread->parent.name, mutex->hold); @@ -1453,9 +1455,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) if (thread != mutex->owner) { thread->error = -RT_ERROR; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); return -RT_ERROR; } @@ -1494,6 +1494,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) LOG_D("mutex_release: resume thread: %s", next_thread->parent.name); + rt_spin_lock(&(next_thread->spinlock)); /* remove the thread from the suspended list of mutex */ rt_list_remove(&(next_thread->tlist)); @@ -1503,7 +1504,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) rt_list_insert_after(&next_thread->taken_object_list, &mutex->taken_list); /* cleanup pending object */ next_thread->pending_object = RT_NULL; - + rt_spin_unlock(&(next_thread->spinlock)); /* resume thread */ rt_thread_resume(next_thread); @@ -1532,8 +1533,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mutex->spinlock), level); /* perform a schedule */ if (need_schedule == RT_TRUE) @@ -1628,6 +1628,7 @@ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag) /* initialize event */ event->set = 0; + rt_spin_lock_init(&(event->spinlock)); return RT_EOK; } @@ -1654,16 +1655,20 @@ RTM_EXPORT(rt_event_init); */ rt_err_t rt_event_detach(rt_event_t event) { + rt_base_t level; + /* parameter check */ RT_ASSERT(event != RT_NULL); RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event); RT_ASSERT(rt_object_is_systemobject(&event->parent.parent)); + level = rt_spin_lock_irqsave(&(event->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&(event->parent.suspend_thread)); /* detach event object */ rt_object_detach(&(event->parent.parent)); + rt_spin_unlock_irqrestore(&(event->spinlock), level); return RT_EOK; } @@ -1719,6 +1724,7 @@ rt_event_t rt_event_create(const char *name, rt_uint8_t flag) /* initialize event */ event->set = 0; + rt_spin_lock_init(&(event->spinlock)); return event; } @@ -1752,11 +1758,13 @@ rt_err_t rt_event_delete(rt_event_t event) RT_DEBUG_NOT_IN_INTERRUPT; + rt_spin_lock(&(event->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&(event->parent.suspend_thread)); /* delete event object */ rt_object_delete(&(event->parent.parent)); + rt_spin_unlock(&(event->spinlock)); return RT_EOK; } @@ -1799,8 +1807,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) need_schedule = RT_FALSE; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(event->spinlock)); /* set event */ event->set |= set; @@ -1838,8 +1845,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) } else { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); return -RT_EINVAL; } @@ -1868,8 +1874,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); /* do a schedule */ if (need_schedule == RT_TRUE) @@ -1943,8 +1948,7 @@ static rt_err_t _rt_event_recv(rt_event_t event, RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(event->spinlock)); /* check event set */ if (option & RT_EVENT_FLAG_AND) @@ -1984,8 +1988,7 @@ static rt_err_t _rt_event_recv(rt_event_t event, /* no waiting */ thread->error = -RT_ETIMEOUT; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); return -RT_ETIMEOUT; } @@ -2002,7 +2005,7 @@ static rt_err_t _rt_event_recv(rt_event_t event, suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); return ret; } @@ -2016,8 +2019,7 @@ static rt_err_t _rt_event_recv(rt_event_t event, rt_timer_start(&(thread->thread_timer)); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); /* do a schedule */ rt_schedule(); @@ -2029,15 +2031,14 @@ static rt_err_t _rt_event_recv(rt_event_t event, } /* received an event, disable interrupt to protect */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(event->spinlock)); /* set received event */ if (recved) *recved = thread->event_set; } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent))); @@ -2097,8 +2098,7 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) if (cmd == RT_IPC_CMD_RESET) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(event->spinlock)); /* resume all waiting thread */ _ipc_list_resume_all(&event->parent.suspend_thread); @@ -2106,8 +2106,7 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg) /* initialize event set */ event->set = 0; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(event->spinlock), level); rt_schedule(); @@ -2192,6 +2191,7 @@ rt_err_t rt_mb_init(rt_mailbox_t mb, /* initialize an additional list of sender suspend thread */ rt_list_init(&(mb->suspend_sender_thread)); + rt_spin_lock_init(&(mb->spinlock)); return RT_EOK; } @@ -2218,11 +2218,14 @@ RTM_EXPORT(rt_mb_init); */ rt_err_t rt_mb_detach(rt_mailbox_t mb) { + rt_base_t level; + /* parameter check */ RT_ASSERT(mb != RT_NULL); RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox); RT_ASSERT(rt_object_is_systemobject(&mb->parent.parent)); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&(mb->parent.suspend_thread)); /* also resume all mailbox private suspended thread */ @@ -2230,6 +2233,7 @@ rt_err_t rt_mb_detach(rt_mailbox_t mb) /* detach mailbox object */ rt_object_detach(&(mb->parent.parent)); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return RT_EOK; } @@ -2302,6 +2306,7 @@ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) /* initialize an additional list of sender suspend thread */ rt_list_init(&(mb->suspend_sender_thread)); + rt_spin_lock_init(&(mb->spinlock)); return mb; } @@ -2334,6 +2339,7 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) RT_ASSERT(rt_object_is_systemobject(&mb->parent.parent) == RT_FALSE); RT_DEBUG_NOT_IN_INTERRUPT; + rt_spin_lock(&(mb->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&(mb->parent.suspend_thread)); @@ -2341,6 +2347,8 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) /* also resume all mailbox private suspended thread */ _ipc_list_resume_all(&(mb->suspend_sender_thread)); + rt_spin_unlock(&(mb->spinlock)); + /* free mailbox pool */ RT_KERNEL_FREE(mb->msg_pool); @@ -2401,12 +2409,12 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent))); /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* for non-blocking call */ if (mb->entry == mb->size && timeout == 0) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return -RT_EFULL; } @@ -2419,8 +2427,7 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, /* no waiting, return timeout */ if (timeout == 0) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return -RT_EFULL; } @@ -2433,7 +2440,7 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return ret; } @@ -2452,9 +2459,7 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, &timeout); rt_timer_start(&(thread->thread_timer)); } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); /* re-schedule */ rt_schedule(); @@ -2466,8 +2471,7 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, return thread->error; } - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* if it's not waiting forever and then re-calculate timeout tick */ if (timeout > 0) @@ -2493,7 +2497,7 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, } else { - rt_hw_interrupt_enable(level); /* enable interrupt */ + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return -RT_EFULL; /* value overflowed */ } @@ -2502,16 +2506,13 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, { _ipc_list_resume(&(mb->parent.suspend_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); rt_schedule(); return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return RT_EOK; } @@ -2600,12 +2601,11 @@ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); if (mb->entry == mb->size) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return -RT_EFULL; } @@ -2630,16 +2630,13 @@ rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) { _ipc_list_resume(&(mb->parent.suspend_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); rt_schedule(); return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return RT_EOK; } @@ -2692,13 +2689,12 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mb->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* for non-blocking call */ if (mb->entry == 0 && timeout == 0) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return -RT_ETIMEOUT; } @@ -2712,8 +2708,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo /* no waiting, return timeout */ if (timeout == 0) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); thread->error = -RT_ETIMEOUT; @@ -2727,7 +2722,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); return ret; } @@ -2747,8 +2742,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo rt_timer_start(&(thread->thread_timer)); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); /* re-schedule */ rt_schedule(); @@ -2759,9 +2753,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo /* return error */ return thread->error; } - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* if it's not waiting forever and then re-calculate timeout tick */ if (timeout > 0) @@ -2792,8 +2784,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo { _ipc_list_resume(&(mb->suspend_sender_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent))); @@ -2801,9 +2792,7 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent))); @@ -2852,8 +2841,7 @@ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) if (cmd == RT_IPC_CMD_RESET) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mb->spinlock)); /* resume all waiting thread */ _ipc_list_resume_all(&(mb->parent.suspend_thread)); @@ -2865,8 +2853,7 @@ rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg) mb->in_offset = 0; mb->out_offset = 0; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mb->spinlock), level); rt_schedule(); @@ -2984,6 +2971,7 @@ rt_err_t rt_mq_init(rt_mq_t mq, /* initialize an additional list of sender suspend thread */ rt_list_init(&(mq->suspend_sender_thread)); + rt_spin_lock_init(&(mq->spinlock)); return RT_EOK; } @@ -3010,11 +2998,14 @@ RTM_EXPORT(rt_mq_init); */ rt_err_t rt_mq_detach(rt_mq_t mq) { + rt_base_t level; + /* parameter check */ RT_ASSERT(mq != RT_NULL); RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue); RT_ASSERT(rt_object_is_systemobject(&mq->parent.parent)); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&mq->parent.suspend_thread); /* also resume all message queue private suspended thread */ @@ -3022,6 +3013,7 @@ rt_err_t rt_mq_detach(rt_mq_t mq) /* detach message queue object */ rt_object_detach(&(mq->parent.parent)); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return RT_EOK; } @@ -3120,6 +3112,7 @@ rt_mq_t rt_mq_create(const char *name, /* initialize an additional list of sender suspend thread */ rt_list_init(&(mq->suspend_sender_thread)); + rt_spin_lock_init(&(mq->spinlock)); return mq; } @@ -3154,11 +3147,14 @@ rt_err_t rt_mq_delete(rt_mq_t mq) RT_DEBUG_NOT_IN_INTERRUPT; + rt_spin_lock(&(mq->spinlock)); /* resume all suspended thread */ _ipc_list_resume_all(&(mq->parent.suspend_thread)); /* also resume all message queue private suspended thread */ _ipc_list_resume_all(&(mq->suspend_sender_thread)); + rt_spin_unlock(&(mq->spinlock)); + /* free message queue pool */ RT_KERNEL_FREE(mq->msg_pool); @@ -3236,16 +3232,14 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* get a free list, there must be an empty item */ msg = (struct rt_mq_message *)mq->msg_queue_free; /* for non-blocking call */ if (msg == RT_NULL && timeout == 0) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_EFULL; } @@ -3259,8 +3253,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, /* no waiting, return timeout */ if (timeout == 0) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_EFULL; } @@ -3272,7 +3265,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return ret; } @@ -3292,8 +3285,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, rt_timer_start(&(thread->thread_timer)); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); /* re-schedule */ rt_schedule(); @@ -3304,9 +3296,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, /* return error */ return thread->error; } - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* if it's not waiting forever and then re-calculate timeout tick */ if (timeout > 0) @@ -3321,8 +3311,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, /* move free list pointer */ mq->msg_queue_free = msg->next; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); /* the msg is the new tailer of list, the next shall be NULL */ msg->next = RT_NULL; @@ -3333,7 +3322,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, rt_memcpy(GET_MESSAGEBYTE_ADDR(msg), buffer, size); /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); #ifdef RT_USING_MESSAGEQUEUE_PRIORITY msg->prio = prio; if (mq->msg_queue_head == RT_NULL) @@ -3382,7 +3371,7 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, } else { - rt_hw_interrupt_enable(level); /* enable interrupt */ + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_EFULL; /* value overflowed */ } @@ -3391,16 +3380,13 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq, { _ipc_list_resume(&(mq->parent.suspend_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); rt_schedule(); return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return RT_EOK; } @@ -3505,32 +3491,28 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* get a free list, there must be an empty item */ msg = (struct rt_mq_message *)mq->msg_queue_free; /* message queue is full */ if (msg == RT_NULL) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_EFULL; } /* move free list pointer */ mq->msg_queue_free = msg->next; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); /* add the length */ ((struct rt_mq_message *)msg)->length = size; /* copy buffer */ rt_memcpy(GET_MESSAGEBYTE_ADDR(msg), buffer, size); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* link msg to the beginning of message queue */ msg->next = (struct rt_mq_message *)mq->msg_queue_head; @@ -3547,7 +3529,7 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) } else { - rt_hw_interrupt_enable(level); /* enable interrupt */ + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_EFULL; /* value overflowed */ } @@ -3556,16 +3538,14 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size) { _ipc_list_resume(&(mq->parent.suspend_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); rt_schedule(); return RT_EOK; } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return RT_EOK; } @@ -3630,13 +3610,12 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, thread = rt_thread_self(); RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mq->parent.parent))); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* for non-blocking call */ if (mq->entry == 0 && timeout == 0) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return -RT_ETIMEOUT; } @@ -3651,7 +3630,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, if (timeout == 0) { /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); thread->error = -RT_ETIMEOUT; @@ -3665,7 +3644,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); return ret; } @@ -3685,8 +3664,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, rt_timer_start(&(thread->thread_timer)); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); /* re-schedule */ rt_schedule(); @@ -3698,8 +3676,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, return thread->error; } - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* if it's not waiting forever and then re-calculate timeout tick */ if (timeout > 0) @@ -3726,8 +3703,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, mq->entry --; } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); /* get real message length */ len = ((struct rt_mq_message *)msg)->length; @@ -3741,8 +3717,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, if (prio != RT_NULL) *prio = msg->prio; #endif - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* put message to free list */ msg->next = (struct rt_mq_message *)mq->msg_queue_free; mq->msg_queue_free = msg; @@ -3752,8 +3727,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, { _ipc_list_resume(&(mq->suspend_sender_thread)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mq->parent.parent))); @@ -3762,8 +3736,7 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq, return len; } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mq->parent.parent))); @@ -3841,8 +3814,7 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) if (cmd == RT_IPC_CMD_RESET) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mq->spinlock)); /* resume all waiting thread */ _ipc_list_resume_all(&mq->parent.suspend_thread); @@ -3869,8 +3841,7 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg) /* clean entry */ mq->entry = 0; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mq->spinlock), level); rt_schedule(); @@ -12,6 +12,7 @@ * 2021-08-15 Supperthomas fix the comment * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to irq.c * 2022-07-04 Yunjie fix RT_DEBUG_LOG + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> @@ -71,7 +72,7 @@ void rt_interrupt_leave_sethook(void (*hook)(void)) #ifdef RT_USING_SMP #define rt_interrupt_nest rt_cpu_self()->irq_nest #else -volatile rt_uint8_t rt_interrupt_nest = 0; +volatile rt_atomic_t rt_interrupt_nest = 0; #endif /* RT_USING_SMP */ @@ -84,15 +85,10 @@ volatile rt_uint8_t rt_interrupt_nest = 0; */ rt_weak void rt_interrupt_enter(void) { - rt_base_t level; - - level = rt_hw_interrupt_disable(); - rt_interrupt_nest ++; + rt_atomic_add(&(rt_interrupt_nest), 1); RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,()); - rt_hw_interrupt_enable(level); - LOG_D("irq has come..., irq current nest:%d", - (rt_int32_t)rt_interrupt_nest); + (rt_int32_t)rt_atomic_load(&(rt_interrupt_nest))); } RTM_EXPORT(rt_interrupt_enter); @@ -106,15 +102,11 @@ RTM_EXPORT(rt_interrupt_enter); */ rt_weak void rt_interrupt_leave(void) { - rt_base_t level; - LOG_D("irq is going to leave, irq current nest:%d", - (rt_int32_t)rt_interrupt_nest); - - level = rt_hw_interrupt_disable(); + (rt_int32_t)rt_atomic_load(&(rt_interrupt_nest))); RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,()); - rt_interrupt_nest --; - rt_hw_interrupt_enable(level); + rt_atomic_sub(&(rt_interrupt_nest), 1); + } RTM_EXPORT(rt_interrupt_leave); @@ -129,13 +121,7 @@ RTM_EXPORT(rt_interrupt_leave); */ rt_weak rt_uint8_t rt_interrupt_get_nest(void) { - rt_uint8_t ret; - rt_base_t level; - - level = rt_hw_interrupt_disable(); - ret = rt_interrupt_nest; - rt_hw_interrupt_enable(level); - return ret; + return rt_atomic_load(&rt_interrupt_nest); } RTM_EXPORT(rt_interrupt_get_nest); diff --git a/src/mempool.c b/src/mempool.c index 9057288f3e..3992a85219 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -15,6 +15,7 @@ * 2011-01-24 Bernard add object allocation check. * 2012-03-22 Bernard fix align issue in rt_mp_init and rt_mp_create. * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to mempool.c + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> @@ -131,6 +132,7 @@ rt_err_t rt_mp_init(struct rt_mempool *mp, RT_NULL; mp->block_list = block_ptr; + rt_spin_lock_init(&(mp->spinlock)); return RT_EOK; } @@ -153,11 +155,10 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp) RT_ASSERT(rt_object_get_type(&mp->parent) == RT_Object_Class_MemPool); RT_ASSERT(rt_object_is_systemobject(&mp->parent)); + level = rt_spin_lock_irqsave(&(mp->spinlock)); /* wake up all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); @@ -170,13 +171,11 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp) * suspend list */ rt_thread_resume(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); } /* detach object */ rt_object_detach(&(mp->parent)); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); return RT_EOK; } @@ -249,6 +248,7 @@ rt_mp_t rt_mp_create(const char *name, = RT_NULL; mp->block_list = block_ptr; + rt_spin_lock_init(&(mp->spinlock)); return mp; } @@ -273,12 +273,10 @@ rt_err_t rt_mp_delete(rt_mp_t mp) RT_ASSERT(rt_object_get_type(&mp->parent) == RT_Object_Class_MemPool); RT_ASSERT(rt_object_is_systemobject(&mp->parent) == RT_FALSE); + level = rt_spin_lock_irqsave(&(mp->spinlock)); /* wake up all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error code to -RT_ERROR */ @@ -290,9 +288,6 @@ rt_err_t rt_mp_delete(rt_mp_t mp) * suspend list */ rt_thread_resume(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); } /* release allocated room */ @@ -300,6 +295,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp) /* detach object */ rt_object_delete(&(mp->parent)); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); return RT_EOK; } @@ -329,16 +325,14 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) /* get current thread */ thread = rt_thread_self(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mp->spinlock)); while (mp->block_free_count == 0) { /* memory block is unavailable. */ if (time == 0) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); rt_set_errno(-RT_ETIMEOUT); @@ -366,7 +360,7 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) } /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); /* do a schedule */ rt_schedule(); @@ -380,8 +374,7 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) if (time < 0) time = 0; } - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mp->spinlock)); } /* memory block is available. decrease the free block counter */ @@ -397,8 +390,7 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) /* point to memory pool */ *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); RT_OBJECT_HOOK_CALL(rt_mp_alloc_hook, (mp, (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *)))); @@ -428,8 +420,7 @@ void rt_mp_free(void *block) RT_OBJECT_HOOK_CALL(rt_mp_free_hook, (mp, block)); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(mp->spinlock)); /* increase the free block count */ mp->block_free_count ++; @@ -451,17 +442,14 @@ void rt_mp_free(void *block) /* resume thread */ rt_thread_resume(thread); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); /* do a schedule */ rt_schedule(); return; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(mp->spinlock), level); } RTM_EXPORT(rt_mp_free); diff --git a/src/object.c b/src/object.c index afcd4d8509..1a0b87b9cb 100644 --- a/src/object.c +++ b/src/object.c @@ -14,6 +14,7 @@ * 2017-12-10 Bernard Add object_info enum. * 2018-01-25 Bernard Fix the object find issue when enable MODULE. * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to object.c + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rtthread.h> @@ -86,53 +87,53 @@ enum rt_object_info_type static struct rt_object_information _object_container[RT_Object_Info_Unknown] = { /* initialize object container - thread */ - {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)}, + {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread), RT_SPINLOCK_INIT}, #ifdef RT_USING_SEMAPHORE /* initialize object container - semaphore */ - {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)}, + {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_MUTEX /* initialize object container - mutex */ - {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)}, + {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_EVENT /* initialize object container - event */ - {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)}, + {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_MAILBOX /* initialize object container - mailbox */ - {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)}, + {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_MESSAGEQUEUE /* initialize object container - message queue */ - {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)}, + {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_MEMHEAP /* initialize object container - memory heap */ - {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)}, + {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_MEMPOOL /* initialize object container - memory pool */ - {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)}, + {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_DEVICE /* initialize object container - device */ - {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)}, + {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device), RT_SPINLOCK_INIT}, #endif /* initialize object container - timer */ - {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)}, + {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer), RT_SPINLOCK_INIT}, #ifdef RT_USING_MODULE /* initialize object container - module */ - {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)}, + {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_HEAP /* initialize object container - small memory */ - {RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory)}, + {RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory), RT_SPINLOCK_INIT}, #endif #ifdef RT_USING_SMART /* initialize object container - module */ - {RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel)}, - {RT_Object_Class_Custom, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Custom), sizeof(struct rt_custom_object)}, + {RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel), RT_SPINLOCK_INIT}, + {RT_Object_Class_Custom, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Custom), sizeof(struct rt_custom_object), RT_SPINLOCK_INIT}, #endif }; @@ -257,6 +258,8 @@ rt_object_get_information(enum rt_object_class_type type) { int index; + type = type& ~RT_Object_Class_Static; + for (index = 0; index < RT_Object_Info_Unknown; index ++) if (_object_container[index].type == type) return &_object_container[index]; @@ -282,13 +285,12 @@ int rt_object_get_length(enum rt_object_class_type type) information = rt_object_get_information((enum rt_object_class_type)type); if (information == RT_NULL) return 0; - level = rt_hw_interrupt_disable(); - /* get the count of objects */ + level = rt_spin_lock_irqsave(&(information->spinlock)); rt_list_for_each(node, &(information->object_list)) { count ++; } - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(information->spinlock), level); return count; } @@ -321,7 +323,7 @@ int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers information = rt_object_get_information((enum rt_object_class_type)type); if (information == RT_NULL) return 0; - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(information->spinlock)); /* retrieve pointer of object */ rt_list_for_each(node, &(information->object_list)) { @@ -332,7 +334,7 @@ int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers if (index >= maxlen) break; } - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(information->spinlock), level); return index; } @@ -369,7 +371,7 @@ void rt_object_init(struct rt_object *object, /* check object type to avoid re-initialization */ /* enter critical */ - rt_enter_critical(); + level = rt_spin_lock_irqsave(&(information->spinlock)); /* try to find object */ for (node = information->object_list.next; node != &(information->object_list); @@ -381,7 +383,7 @@ void rt_object_init(struct rt_object *object, RT_ASSERT(obj != object); } /* leave critical */ - rt_exit_critical(); + rt_spin_unlock_irqrestore(&(information->spinlock), level); #endif /* initialize object's parameters */ @@ -395,8 +397,7 @@ void rt_object_init(struct rt_object *object, RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); - /* lock interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(information->spinlock)); #ifdef RT_USING_MODULE if (module) @@ -410,9 +411,7 @@ void rt_object_init(struct rt_object *object, /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); } - - /* unlock interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(information->spinlock), level); } /** @@ -424,23 +423,22 @@ void rt_object_init(struct rt_object *object, void rt_object_detach(rt_object_t object) { rt_base_t level; + struct rt_object_information *information; /* object check */ RT_ASSERT(object != RT_NULL); RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object)); - /* reset object type */ - object->type = 0; - - /* lock interrupt */ - level = rt_hw_interrupt_disable(); + information = rt_object_get_information(object->type); + RT_ASSERT(information != RT_NULL); + level = rt_spin_lock_irqsave(&(information->spinlock)); /* remove from old list */ rt_list_remove(&(object->list)); + rt_spin_unlock_irqrestore(&(information->spinlock), level); - /* unlock interrupt */ - rt_hw_interrupt_enable(level); + object->type = 0; } #ifdef RT_USING_HEAP @@ -494,8 +492,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); - /* lock interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(information->spinlock)); #ifdef RT_USING_MODULE if (module) @@ -509,11 +506,8 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); } + rt_spin_unlock_irqrestore(&(information->spinlock), level); - /* unlock interrupt */ - rt_hw_interrupt_enable(level); - - /* return object */ return object; } @@ -525,6 +519,7 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) void rt_object_delete(rt_object_t object) { rt_base_t level; + struct rt_object_information *information; /* object check */ RT_ASSERT(object != RT_NULL); @@ -532,17 +527,19 @@ void rt_object_delete(rt_object_t object) RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object)); - /* reset object type */ - object->type = RT_Object_Class_Null; - /* lock interrupt */ - level = rt_hw_interrupt_disable(); + information = rt_object_get_information(object->type); + RT_ASSERT(information != RT_NULL); + + level = rt_spin_lock_irqsave(&(information->spinlock)); /* remove from old list */ rt_list_remove(&(object->list)); - /* unlock interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(information->spinlock), level); + + /* reset object type */ + object->type = RT_Object_Class_Null; /* free the memory of object */ RT_KERNEL_FREE(object); @@ -604,6 +601,7 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) struct rt_object *object = RT_NULL; struct rt_list_node *node = RT_NULL; struct rt_object_information *information = RT_NULL; + rt_base_t level; information = rt_object_get_information((enum rt_object_class_type)type); @@ -614,7 +612,7 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) RT_DEBUG_NOT_IN_INTERRUPT; /* enter critical */ - rt_enter_critical(); + level = rt_spin_lock_irqsave(&(information->spinlock)); /* try to find object */ rt_list_for_each(node, &(information->object_list)) @@ -622,15 +620,13 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) object = rt_list_entry(node, struct rt_object, list); if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) { - /* leave critical */ - rt_exit_critical(); + rt_spin_unlock_irqrestore(&(information->spinlock), level); return object; } } - /* leave critical */ - rt_exit_critical(); + rt_spin_unlock_irqrestore(&(information->spinlock), level); return RT_NULL; } diff --git a/src/scheduler_mp.c b/src/scheduler_mp.c index bbf5474929..656457aad6 100644 --- a/src/scheduler_mp.c +++ b/src/scheduler_mp.c @@ -29,6 +29,7 @@ * new task directly * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to scheduler.c * 2023-03-27 rose_man Split into scheduler upc and scheduler_mp.c + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rtthread.h> @@ -39,6 +40,7 @@ #include <rtdbg.h> rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX]; +static RT_DEFINE_SPINLOCK(_spinlock); rt_uint32_t rt_thread_ready_priority_group; #if RT_THREAD_PRIORITY_MAX > 32 /* Maximum priority level, 256 */ @@ -118,7 +120,8 @@ static void _scheduler_stack_check(struct rt_thread *thread) rt_kprintf("thread:%s stack overflow\n", thread->parent.name); - level = rt_hw_interrupt_disable(); + level = rt_hw_local_irq_disable(); + rt_spin_lock(&_spinlock); while (level); } #ifdef ARCH_CPU_STACK_GROWS_UPWARD @@ -163,14 +166,14 @@ static struct rt_thread* _scheduler_get_highest_priority_thread(rt_ubase_t *high *highest_prio = highest_ready_priority; highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, struct rt_thread, - tlist); + tlist_schedule); } else { *highest_prio = local_highest_ready_priority; highest_priority_thread = rt_list_entry(pcpu->priority_table[local_highest_ready_priority].next, struct rt_thread, - tlist); + tlist_schedule); } return highest_priority_thread; @@ -208,6 +211,8 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 rt_memset(pcpu->ready_table, 0, sizeof(pcpu->ready_table)); #endif /* RT_THREAD_PRIORITY_MAX > 32 */ + + rt_spin_lock_init(&(pcpu->spinlock)); } /* initialize ready priority group */ @@ -220,28 +225,6 @@ void rt_system_scheduler_init(void) } /** - * @brief This function will startup the scheduler. It will select one thread - * with the highest priority level, then switch to it. - */ -void rt_system_scheduler_start(void) -{ - struct rt_thread *to_thread; - rt_ubase_t highest_ready_priority; - - to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority); - - to_thread->oncpu = rt_hw_cpu_id(); - - rt_schedule_remove_thread(to_thread); - to_thread->stat = RT_THREAD_RUNNING; - - /* switch to new thread */ - rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread); - - /* never come back */ -} - -/** * @addtogroup Thread * @cond */ @@ -262,6 +245,199 @@ void rt_scheduler_ipi_handler(int vector, void *param) rt_schedule(); } +static void _rt_schedule_insert_thread(struct rt_thread *thread, rt_bool_t is_lock) +{ + int cpu_id; + int bind_cpu; + rt_uint32_t cpu_mask; + + RT_ASSERT(thread != RT_NULL); + + /* disable interrupt */ + if(is_lock) + { + rt_spin_lock(&(thread->spinlock)); + } + + if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) + { + if(is_lock) + { + rt_spin_unlock(&(thread->spinlock)); + } + return; + } + + /* it should be RUNNING thread */ + if (thread->oncpu != RT_CPU_DETACHED) + { + thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK); + if(is_lock) + { + rt_spin_unlock(&(thread->spinlock)); + } + return; + } + + /* READY thread, insert to ready queue */ + thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK); + + cpu_id = rt_hw_cpu_id(); + bind_cpu = thread->bind_cpu ; + + /* insert thread to ready list */ + if (bind_cpu == RT_CPUS_NR) + { +#if RT_THREAD_PRIORITY_MAX > 32 + rt_thread_ready_table[thread->number] |= thread->high_mask; +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + rt_thread_ready_priority_group |= thread->number_mask; + + /* there is no time slices left(YIELD), inserting thread before ready list*/ + if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0) + { + rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), + &(thread->tlist_schedule)); + } + /* 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_schedule)); + } + if(is_lock) + { + rt_spin_unlock(&(thread->spinlock)); + } + + cpu_mask = RT_CPU_MASK ^ (1 << cpu_id); + rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask); + } + else + { + struct rt_cpu *pcpu = rt_cpu_index(bind_cpu); + + if(is_lock) + { + rt_spin_lock(&(pcpu->spinlock)); + } +#if RT_THREAD_PRIORITY_MAX > 32 + pcpu->ready_table[thread->number] |= thread->high_mask; +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + pcpu->priority_group |= thread->number_mask; + + /* there is no time slices left(YIELD), inserting thread before ready list*/ + if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0) + { + rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), + &(thread->tlist_schedule)); + } + /* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/ + else + { + rt_list_insert_after(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), + &(thread->tlist_schedule)); + } + + if(is_lock) + { + rt_spin_unlock(&(pcpu->spinlock)); + rt_spin_unlock(&(thread->spinlock)); + } + + if (cpu_id != bind_cpu) + { + cpu_mask = 1 << bind_cpu; + rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask); + } + } + + LOG_D("insert thread[%.*s], the priority: %d", + RT_NAME_MAX, thread->parent.name, thread->current_priority); +} + +static void _rt_schedule_remove_thread(struct rt_thread *thread, rt_bool_t is_lock) +{ + + RT_ASSERT(thread != RT_NULL); + + LOG_D("remove thread[%.*s], the priority: %d", + RT_NAME_MAX, thread->parent.name, + thread->current_priority); + + /* remove thread from ready list */ + rt_list_remove(&(thread->tlist_schedule)); + if (thread->bind_cpu == RT_CPUS_NR) + { + if (rt_list_isempty(&(rt_thread_priority_table[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_priority_group &= ~thread->number_mask; + } +#else + rt_thread_ready_priority_group &= ~thread->number_mask; +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + } + } + else + { + struct rt_cpu *pcpu = rt_cpu_index(thread->bind_cpu); + if(is_lock) + { + rt_spin_lock(&(pcpu->spinlock)); + } + if (rt_list_isempty(&(pcpu->priority_table[thread->current_priority]))) + { +#if RT_THREAD_PRIORITY_MAX > 32 + pcpu->ready_table[thread->number] &= ~thread->high_mask; + if (pcpu->ready_table[thread->number] == 0) + { + pcpu->priority_group &= ~thread->number_mask; + } +#else + pcpu->priority_group &= ~thread->number_mask; +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ + } + if(is_lock) + { + rt_spin_unlock(&(pcpu->spinlock)); + } + } +} + +/** + * @brief This function will startup the scheduler. It will select one thread + * with the highest priority level, then switch to it. + */ +void rt_system_scheduler_start(void) +{ + struct rt_thread *to_thread; + rt_ubase_t highest_ready_priority; + + rt_hw_local_irq_disable(); + rt_spin_lock(&_spinlock); + + to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority); + rt_spin_lock(&to_thread->spinlock); + to_thread->oncpu = rt_hw_cpu_id(); + + _rt_schedule_remove_thread(to_thread, RT_TRUE); + to_thread->stat = RT_THREAD_RUNNING; + + rt_spin_unlock(&to_thread->spinlock); + rt_spin_unlock(&_spinlock); + + rt_hw_spin_unlock(&_cpus_lock); + + /* switch to new thread */ + rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread); + + /* never come back */ +} + /** * @brief This function will perform one scheduling. It will select one thread * with the highest priority level in global ready queue or local ready queue, @@ -269,24 +445,30 @@ void rt_scheduler_ipi_handler(int vector, void *param) */ void rt_schedule(void) { - rt_base_t level; + rt_base_t level; struct rt_thread *to_thread; struct rt_thread *current_thread; struct rt_cpu *pcpu; - int cpu_id; + int cpu_id; + rt_bool_t need_unlock = RT_TRUE; /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_hw_local_irq_disable(); + + rt_spin_lock(&_spinlock); cpu_id = rt_hw_cpu_id(); pcpu = rt_cpu_index(cpu_id); + rt_spin_lock(&pcpu->spinlock); current_thread = pcpu->current_thread; /* whether do switch in interrupt */ - if (pcpu->irq_nest) + if (rt_atomic_load(&(pcpu->irq_nest))) { pcpu->irq_switch_flag = 1; - rt_hw_interrupt_enable(level); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + rt_hw_local_irq_enable(level); goto __exit; } @@ -306,7 +488,8 @@ void rt_schedule(void) } #endif /* RT_USING_SIGNALS */ - if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ + rt_spin_lock(&(current_thread->spinlock)); + if (rt_atomic_load(&(current_thread->critical_lock_nest)) == 0) /* whether lock scheduler */ { rt_ubase_t highest_ready_priority; @@ -328,15 +511,20 @@ void rt_schedule(void) } else { - rt_schedule_insert_thread(current_thread); + _rt_schedule_insert_thread(current_thread, RT_FALSE); } } else { - rt_schedule_insert_thread(current_thread); + _rt_schedule_insert_thread(current_thread, RT_FALSE); } current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK; } + + if (to_thread != current_thread) + { + rt_spin_lock(&(to_thread->spinlock)); + } to_thread->oncpu = cpu_id; if (to_thread != current_thread) { @@ -345,14 +533,14 @@ void rt_schedule(void) RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread)); - rt_schedule_remove_thread(to_thread); + _rt_schedule_remove_thread(to_thread, RT_FALSE); to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK); /* switch to new thread */ LOG_D("[%d]switch to priority#%d " "thread:%.*s(sp:0x%08x), " "from thread:%.*s(sp: 0x%08x)", - pcpu->irq_nest, highest_ready_priority, + rt_atomic_load(&(pcpu->irq_nest)), highest_ready_priority, RT_NAME_MAX, to_thread->parent.name, to_thread->sp, RT_NAME_MAX, current_thread->parent.name, current_thread->sp); @@ -362,32 +550,42 @@ void rt_schedule(void) RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_spin_unlock(&(to_thread->spinlock)); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + + need_unlock = RT_FALSE; rt_hw_context_switch((rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } } } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + if(need_unlock) + { + rt_spin_unlock(&(current_thread->spinlock)); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + } + rt_hw_local_irq_enable(level); #ifdef RT_USING_SIGNALS /* check stat of thread for signal */ - level = rt_hw_interrupt_disable(); + rt_spin_lock(&(current_thread->spinlock)); if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING) { extern void rt_thread_handle_sig(rt_bool_t clean_state); current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING; - rt_hw_interrupt_enable(level); + rt_spin_unlock(&(current_thread->spinlock)); /* check signal status */ rt_thread_handle_sig(RT_TRUE); } else { - rt_hw_interrupt_enable(level); + rt_spin_unlock(&(current_thread->spinlock)); } #endif /* RT_USING_SIGNALS */ @@ -402,16 +600,18 @@ __exit: */ void rt_scheduler_do_irq_switch(void *context) { - int cpu_id; - rt_base_t level; - struct rt_cpu* pcpu; + int cpu_id; + rt_base_t level; + struct rt_cpu *pcpu; struct rt_thread *to_thread; struct rt_thread *current_thread; + rt_bool_t need_unlock = RT_TRUE; - level = rt_hw_interrupt_disable(); - + level = rt_hw_local_irq_disable(); + rt_spin_lock(&_spinlock); cpu_id = rt_hw_cpu_id(); pcpu = rt_cpu_index(cpu_id); + rt_spin_lock(&pcpu->spinlock); current_thread = pcpu->current_thread; #ifdef RT_USING_SIGNALS @@ -432,11 +632,14 @@ void rt_scheduler_do_irq_switch(void *context) if (pcpu->irq_switch_flag == 0) { - rt_hw_interrupt_enable(level); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + rt_hw_local_irq_enable(level); return; } - - if (current_thread->scheduler_lock_nest == 1 && pcpu->irq_nest == 0) + rt_spin_lock(&(current_thread->spinlock)); + if (rt_atomic_load(&(current_thread->critical_lock_nest)) == 0 && + rt_atomic_load(&(pcpu->irq_nest)) == 0) { rt_ubase_t highest_ready_priority; @@ -461,15 +664,20 @@ void rt_scheduler_do_irq_switch(void *context) } else { - rt_schedule_insert_thread(current_thread); + _rt_schedule_insert_thread(current_thread, RT_FALSE); } } else { - rt_schedule_insert_thread(current_thread); + _rt_schedule_insert_thread(current_thread, RT_FALSE); } current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK; } + + if (to_thread != current_thread) + { + rt_spin_lock(&(to_thread->spinlock)); + } to_thread->oncpu = cpu_id; if (to_thread != current_thread) { @@ -479,7 +687,7 @@ void rt_scheduler_do_irq_switch(void *context) RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread)); - rt_schedule_remove_thread(to_thread); + _rt_schedule_remove_thread(to_thread, RT_FALSE); to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK); #ifdef RT_USING_OVERFLOW_CHECK @@ -487,18 +695,27 @@ void rt_scheduler_do_irq_switch(void *context) #endif /* RT_USING_OVERFLOW_CHECK */ LOG_D("switch in interrupt"); - RT_ASSERT(current_thread->cpus_lock_nest > 0); - current_thread->cpus_lock_nest--; - current_thread->scheduler_lock_nest--; - RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_spin_unlock(&(to_thread->spinlock)); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + + need_unlock = RT_FALSE; rt_hw_context_switch_interrupt(context, (rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } } } - rt_hw_interrupt_enable(level); + + if(need_unlock) + { + rt_spin_unlock(&(current_thread->spinlock)); + rt_spin_unlock(&pcpu->spinlock); + rt_spin_unlock(&_spinlock); + } + + rt_hw_local_irq_enable(level); } /** @@ -511,88 +728,10 @@ void rt_scheduler_do_irq_switch(void *context) */ void rt_schedule_insert_thread(struct rt_thread *thread) { - int cpu_id; - int bind_cpu; - rt_uint32_t cpu_mask; rt_base_t level; - - RT_ASSERT(thread != RT_NULL); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - /* it should be RUNNING thread */ - if (thread->oncpu != RT_CPU_DETACHED) - { - thread->stat = RT_THREAD_RUNNING | (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); - - cpu_id = rt_hw_cpu_id(); - bind_cpu = thread->bind_cpu ; - - /* insert thread to ready list */ - if (bind_cpu == RT_CPUS_NR) - { -#if RT_THREAD_PRIORITY_MAX > 32 - rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ - rt_thread_ready_priority_group |= thread->number_mask; - - /* there is no time slices left(YIELD), inserting thread before ready list*/ - if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0) - { - rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), - &(thread->tlist)); - } - /* 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)); - } - - cpu_mask = RT_CPU_MASK ^ (1 << cpu_id); - rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask); - } - else - { - struct rt_cpu *pcpu = rt_cpu_index(bind_cpu); - -#if RT_THREAD_PRIORITY_MAX > 32 - pcpu->ready_table[thread->number] |= thread->high_mask; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ - pcpu->priority_group |= thread->number_mask; - - /* there is no time slices left(YIELD), inserting thread before ready list*/ - if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0) - { - rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), - &(thread->tlist)); - } - /* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/ - else - { - rt_list_insert_after(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), - &(thread->tlist)); - } - - if (cpu_id != bind_cpu) - { - cpu_mask = 1 << bind_cpu; - rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask); - } - } - - LOG_D("insert thread[%.*s], the priority: %d", - RT_NAME_MAX, thread->parent.name, thread->current_priority); - -__exit: - /* enable interrupt */ - rt_hw_interrupt_enable(level); + level = rt_spin_lock_irqsave(&_spinlock); + _rt_schedule_insert_thread(thread, RT_TRUE); + rt_spin_unlock_irqrestore(&_spinlock, level); } /** @@ -605,53 +744,11 @@ __exit: void rt_schedule_remove_thread(struct rt_thread *thread) { rt_base_t level; - - RT_ASSERT(thread != RT_NULL); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - LOG_D("remove thread[%.*s], the priority: %d", - RT_NAME_MAX, thread->parent.name, - thread->current_priority); - - /* remove thread from ready list */ - rt_list_remove(&(thread->tlist)); - if (thread->bind_cpu == RT_CPUS_NR) - { - if (rt_list_isempty(&(rt_thread_priority_table[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_priority_group &= ~thread->number_mask; - } -#else - rt_thread_ready_priority_group &= ~thread->number_mask; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ - } - } - else - { - struct rt_cpu *pcpu = rt_cpu_index(thread->bind_cpu); - - if (rt_list_isempty(&(pcpu->priority_table[thread->current_priority]))) - { -#if RT_THREAD_PRIORITY_MAX > 32 - pcpu->ready_table[thread->number] &= ~thread->high_mask; - if (pcpu->ready_table[thread->number] == 0) - { - pcpu->priority_group &= ~thread->number_mask; - } -#else - pcpu->priority_group &= ~thread->number_mask; -#endif /* RT_THREAD_PRIORITY_MAX > 32 */ - } - } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + level = rt_spin_lock_irqsave(&_spinlock); + rt_spin_lock(&thread->spinlock); + _rt_schedule_remove_thread(thread, RT_TRUE); + rt_spin_unlock(&thread->spinlock); + rt_spin_unlock_irqrestore(&_spinlock, level); } /** @@ -672,26 +769,8 @@ void rt_enter_critical(void) return; } - /* - * the maximal number of nest is RT_UINT16_MAX, which is big - * enough and does not check here - */ - - { - rt_uint16_t lock_nest = current_thread->cpus_lock_nest; - current_thread->cpus_lock_nest++; - RT_ASSERT(current_thread->cpus_lock_nest != 0); - if (lock_nest == 0) - { - current_thread->scheduler_lock_nest ++; - rt_hw_spin_lock(&_cpus_lock); - } - } /* critical for local cpu */ - current_thread->critical_lock_nest ++; - - /* lock scheduler for local cpu */ - current_thread->scheduler_lock_nest ++; + rt_atomic_add(&(current_thread->critical_lock_nest), 1); /* enable interrupt */ rt_hw_local_irq_enable(level); @@ -716,21 +795,11 @@ void rt_exit_critical(void) return; } - current_thread->scheduler_lock_nest --; + rt_atomic_sub(&(current_thread->critical_lock_nest), 1); - current_thread->critical_lock_nest --; - - RT_ASSERT(current_thread->cpus_lock_nest > 0); - current_thread->cpus_lock_nest--; - if (current_thread->cpus_lock_nest == 0) + if (rt_atomic_load(&(current_thread->critical_lock_nest)) <= 0) { - current_thread->scheduler_lock_nest --; - rt_hw_spin_unlock(&_cpus_lock); - } - - if (current_thread->scheduler_lock_nest <= 0) - { - current_thread->scheduler_lock_nest = 0; + rt_atomic_store(&(current_thread->critical_lock_nest), 0); /* enable interrupt */ rt_hw_local_irq_enable(level); @@ -752,8 +821,7 @@ RTM_EXPORT(rt_exit_critical); rt_uint16_t rt_critical_level(void) { struct rt_thread *current_thread = rt_cpu_self()->current_thread; - - return current_thread->critical_lock_nest; + return rt_atomic_load(&(current_thread->critical_lock_nest)); } RTM_EXPORT(rt_critical_level); diff --git a/src/signal.c b/src/signal.c index 51f92fbde4..9d4b4c4148 100644 --- a/src/signal.c +++ b/src/signal.c @@ -53,17 +53,6 @@ static void _signal_entry(void *parameter) rt_thread_handle_sig(RT_FALSE); #ifdef RT_USING_SMP - { - struct rt_cpu* pcpu = rt_cpu_self(); - - RT_ASSERT(pcpu->current_thread->cpus_lock_nest > 0); - pcpu->current_thread->cpus_lock_nest--; - if (pcpu->current_thread->cpus_lock_nest == 0) - { - pcpu->current_thread->scheduler_lock_nest--; - } - - } #else /* return to thread */ tid->sp = tid->sig_ret; diff --git a/src/thread.c b/src/thread.c index 334c8803ed..21c6230192 100644 --- a/src/thread.c +++ b/src/thread.c @@ -32,6 +32,7 @@ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to thread.c * 2022-01-24 THEWON let rt_thread_sleep return thread->error when using signal * 2022-10-15 Bernard add nested mutex feature + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include <rthw.h> @@ -98,26 +99,17 @@ static void _thread_exit(void) rt_base_t level; /* get current thread */ + LOG_D("line:%d thread:%s exit\n",__LINE__,rt_thread_self()->parent.name); thread = rt_thread_self(); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - /* remove from schedule */ - rt_schedule_remove_thread(thread); - - /* remove it from timer list */ + rt_get_thread_struct(thread); + rt_thread_defunct_enqueue(thread); + level = rt_spin_lock_irqsave(&(thread->spinlock)); rt_timer_detach(&thread->thread_timer); - - /* change stat */ - thread->stat = RT_THREAD_CLOSE; - /* insert to defunct thread list */ - rt_thread_defunct_enqueue(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); + LOG_D("line:%d thread:%s exit\n",__LINE__,rt_thread_self()->parent.name); + rt_put_thread_struct(thread); + thread->stat = RT_THREAD_CLOSE; /* switch to next task */ rt_schedule(); } @@ -139,22 +131,15 @@ static void _thread_timeout(void *parameter) RT_ASSERT(thread != RT_NULL); RT_ASSERT((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* set error number */ thread->error = -RT_ETIMEOUT; /* remove from suspend list */ rt_list_remove(&(thread->tlist)); - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* insert to schedule ready list */ rt_schedule_insert_thread(thread); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - /* do schedule */ rt_schedule(); } @@ -170,6 +155,7 @@ static rt_err_t _thread_init(struct rt_thread *thread, { /* init thread list */ rt_list_init(&(thread->tlist)); + rt_list_init(&(thread->tlist_schedule)); #ifdef RT_USING_SMART thread->wakeup.func = RT_NULL; @@ -217,8 +203,8 @@ static rt_err_t _thread_init(struct rt_thread *thread, #endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* tick init */ - thread->init_tick = tick; - thread->remaining_tick = tick; + rt_atomic_store(&thread->init_tick, tick); + rt_atomic_store(&thread->remaining_tick, tick); /* error and flags */ thread->error = RT_EOK; @@ -230,9 +216,8 @@ static rt_err_t _thread_init(struct rt_thread *thread, thread->oncpu = RT_CPU_DETACHED; /* lock init */ - thread->scheduler_lock_nest = 0; - thread->cpus_lock_nest = 0; - thread->critical_lock_nest = 0; + rt_atomic_store(&thread->cpus_lock_nest, 0); + rt_atomic_store(&thread->critical_lock_nest, 0); #endif /* RT_USING_SMP */ /* initialize cleanup function and user data */ @@ -260,7 +245,9 @@ static rt_err_t _thread_init(struct rt_thread *thread, #endif /* RT_USING_SIGNALS */ #ifdef RT_USING_SMART + thread->tid_ref_count = 0; thread->lwp = RT_NULL; + thread->susp_recycler = RT_NULL; rt_list_init(&(thread->sibling)); /* lwp thread-signal init */ @@ -286,6 +273,8 @@ static rt_err_t _thread_init(struct rt_thread *thread, #ifdef RT_USING_MODULE thread->parent.module_id = 0; #endif /* RT_USING_MODULE */ + rt_atomic_store(&thread->ref_count, 0); + rt_spin_lock_init(&thread->spinlock); RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); @@ -439,7 +428,7 @@ rt_err_t rt_thread_detach(rt_thread_t thread) } /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); @@ -456,13 +445,11 @@ rt_err_t rt_thread_detach(rt_thread_t thread) thread->pending_object = RT_NULL; } #endif + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* insert to defunct thread list */ rt_thread_defunct_enqueue(thread); - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return RT_EOK; } RTM_EXPORT(rt_thread_detach); @@ -550,9 +537,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) /* remove from schedule */ rt_schedule_remove_thread(thread); } - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); @@ -569,13 +554,10 @@ rt_err_t rt_thread_delete(rt_thread_t thread) thread->pending_object = RT_NULL; } #endif - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* insert to defunct thread list */ rt_thread_defunct_enqueue(thread); - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return RT_EOK; } RTM_EXPORT(rt_thread_delete); @@ -595,10 +577,10 @@ rt_err_t rt_thread_yield(void) rt_base_t level; thread = rt_thread_self(); - level = rt_hw_interrupt_disable(); - thread->remaining_tick = thread->init_tick; + level = rt_spin_lock_irqsave(&(thread->spinlock)); + rt_atomic_store(&thread->remaining_tick, thread->init_tick); thread->stat |= RT_THREAD_STAT_YIELD; - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); rt_schedule(); return RT_EOK; @@ -616,7 +598,7 @@ RTM_EXPORT(rt_thread_yield); */ rt_err_t rt_thread_sleep(rt_tick_t tick) { - rt_base_t level; + rt_base_t level, level_local; struct rt_thread *thread; int err; @@ -632,16 +614,12 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) /* current context checking */ RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - /* reset thread error */ thread->error = RT_EOK; - + level_local = rt_hw_local_irq_disable(); /* suspend thread */ err = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE); - + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* reset the timeout of thread timer and start it */ if (err == RT_EOK) { @@ -649,8 +627,8 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) rt_timer_start(&(thread->thread_timer)); /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); + rt_hw_local_irq_enable(level_local); thread->error = -RT_EINTR; rt_schedule(); @@ -661,7 +639,8 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) } else { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); + rt_hw_local_irq_enable(level_local); } return err; @@ -705,7 +684,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* reset thread error */ thread->error = RT_EOK; @@ -717,16 +696,14 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) *tick += inc_tick; left_tick = *tick - cur_tick; - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* suspend thread */ rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE); - + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &left_tick); rt_timer_start(&(thread->thread_timer)); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); rt_schedule(); @@ -739,7 +716,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) else { *tick = cur_tick; - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); } return thread->error; @@ -774,7 +751,6 @@ static void rt_thread_cpu_bind(rt_thread_t thread, int cpu) cpu = RT_CPUS_NR; } - level = rt_hw_interrupt_disable(); if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) { /* unbind */ @@ -791,6 +767,7 @@ static void rt_thread_cpu_bind(rt_thread_t thread, int cpu) } else { + level = rt_spin_lock_irqsave(&(thread->spinlock)); thread->bind_cpu = cpu; if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING) { @@ -807,7 +784,9 @@ static void rt_thread_cpu_bind(rt_thread_t thread, int cpu) /* bind to other cpu */ rt_hw_ipi_send(RT_SCHEDULE_IPI, 1U << cpu); /* self cpu need reschedule */ + rt_spin_unlock_irqrestore(&(thread->spinlock), level); rt_schedule(); + level = rt_spin_lock_irqsave(&(thread->spinlock)); } /* else do nothing */ } @@ -819,8 +798,8 @@ static void rt_thread_cpu_bind(rt_thread_t thread, int cpu) } /* else do nothing */ } + rt_spin_unlock_irqrestore(&(thread->spinlock), level); } - rt_hw_interrupt_enable(level); } #endif @@ -856,15 +835,12 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { case RT_THREAD_CTRL_CHANGE_PRIORITY: { - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - /* for ready thread, change queue */ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) { /* remove thread from schedule queue first */ rt_schedule_remove_thread(thread); - + level = rt_spin_lock_irqsave(&(thread->spinlock)); /* change thread priority */ thread->current_priority = *(rt_uint8_t *)arg; @@ -876,12 +852,14 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) #else thread->number_mask = 1 << thread->current_priority; #endif /* RT_THREAD_PRIORITY_MAX > 32 */ - + thread->stat = RT_THREAD_INIT; + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* insert thread to schedule queue again */ rt_schedule_insert_thread(thread); } else { + level = rt_spin_lock_irqsave(&(thread->spinlock)); thread->current_priority = *(rt_uint8_t *)arg; /* recalculate priority attribute */ @@ -892,10 +870,8 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) #else thread->number_mask = 1 << thread->current_priority; #endif /* RT_THREAD_PRIORITY_MAX > 32 */ + rt_spin_unlock_irqrestore(&(thread->spinlock), level); } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); break; } @@ -927,10 +903,10 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { rt_uint8_t cpu; - cpu = (rt_uint8_t)(size_t)arg; - rt_thread_cpu_bind(thread, cpu); - break; - } + cpu = (rt_uint8_t)(size_t)arg; + rt_thread_cpu_bind(thread, cpu); + break; + } #endif /*RT_USING_SMP*/ default: break; @@ -995,15 +971,16 @@ rt_err_t rt_thread_suspend_with_flag(rt_thread_t thread, int suspend_flag) LOG_D("thread suspend: %s", thread->parent.name); + level = rt_spin_lock_irqsave(&(thread->spinlock)); + stat = thread->stat & RT_THREAD_STAT_MASK; if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING)) { LOG_D("thread suspend: thread disorder, 0x%2x", thread->stat); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); return -RT_ERROR; } - /* disable interrupt */ - level = rt_hw_interrupt_disable(); if (stat == RT_THREAD_RUNNING) { /* not suspend running status thread on other core */ @@ -1013,20 +990,20 @@ rt_err_t rt_thread_suspend_with_flag(rt_thread_t thread, int suspend_flag) if (lwp_thread_signal_suspend_check(thread, suspend_flag) == 0) { /* not to suspend */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); return -RT_EINTR; } #endif - /* change thread stat */ + rt_spin_unlock_irqrestore(&(thread->spinlock), level); rt_schedule_remove_thread(thread); + level = rt_spin_lock_irqsave(&(thread->spinlock)); + rt_thread_set_suspend_state(thread, suspend_flag); /* stop thread timer anyway */ rt_timer_stop(&(thread->thread_timer)); - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(&(thread->spinlock), level); RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread)); return RT_EOK; @@ -1065,8 +1042,7 @@ rt_err_t rt_thread_resume(rt_thread_t thread) return -RT_ERROR; } - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&(thread->spinlock)); //TODO need lock for cpu /* remove from suspend list */ rt_list_remove(&(thread->tlist)); @@ -1077,9 +1053,7 @@ rt_err_t rt_thread_resume(rt_thread_t thread) thread->wakeup.func = RT_NULL; #endif - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&(thread->spinlock), level); /* insert to schedule ready list */ rt_schedule_insert_thread(thread); @@ -1100,22 +1074,22 @@ rt_err_t rt_thread_wakeup(rt_thread_t thread) { register rt_base_t temp; rt_err_t ret; + rt_wakeup_func_t func = RT_NULL; RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - /* disable interrupt */ - temp = rt_hw_interrupt_disable(); - if (thread->wakeup.func) + temp = rt_spin_lock_irqsave(&(thread->spinlock)); + func = thread->wakeup.func; + thread->wakeup.func = RT_NULL; + rt_spin_unlock_irqrestore(&(thread->spinlock), temp); + if (func) { - ret = thread->wakeup.func(thread->wakeup.user_data, thread); - thread->wakeup.func = RT_NULL; + ret = func(thread->wakeup.user_data, thread); } else { ret = rt_thread_resume(thread); } - - rt_hw_interrupt_enable(temp); return ret; } RTM_EXPORT(rt_thread_wakeup); @@ -1127,10 +1101,10 @@ void rt_thread_wakeup_set(struct rt_thread *thread, rt_wakeup_func_t func, void* RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - temp = rt_hw_interrupt_disable(); + temp = rt_spin_lock_irqsave(&(thread->spinlock)); thread->wakeup.func = func; thread->wakeup.user_data = user_data; - rt_hw_interrupt_enable(temp); + rt_spin_unlock_irqrestore(&(thread->spinlock), temp); } RTM_EXPORT(rt_thread_wakeup_set); #endif diff --git a/src/timer.c b/src/timer.c index 6a077f7575..98e8f6defb 100644 --- a/src/timer.c +++ b/src/timer.c @@ -19,6 +19,7 @@ * 2021-08-15 supperthomas add the comment * 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 */ #include <rtthread.h> @@ -30,6 +31,7 @@ /* hard timer list */ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; +static struct rt_spinlock _hard_spinlock; #ifdef RT_USING_TIMER_SOFT @@ -48,6 +50,7 @@ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; 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_thread _timer_thread; rt_align(RT_ALIGN_SIZE) static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE]; @@ -161,26 +164,14 @@ static void _timer_init(rt_timer_t timer, static rt_err_t _timer_list_next_timeout(rt_list_t timer_list[], rt_tick_t *timeout_tick) { struct rt_timer *timer; - rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); if (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); *timeout_tick = timer->timeout_tick; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return -RT_ERROR; } @@ -294,22 +285,31 @@ RTM_EXPORT(rt_timer_init); rt_err_t rt_timer_detach(rt_timer_t timer) { rt_base_t level; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent)); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); +#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; + } + + level = rt_spin_lock_irqsave(spinlock); _timer_remove(timer); /* stop timer */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(spinlock, level); rt_object_detach(&(timer->parent)); return RT_EOK; @@ -378,22 +378,30 @@ RTM_EXPORT(rt_timer_create); rt_err_t rt_timer_delete(rt_timer_t timer) { rt_base_t level; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); +#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; + } + + level = rt_spin_lock_irqsave(spinlock); _timer_remove(timer); /* stop timer */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(spinlock, level); rt_object_delete(&(timer->parent)); return RT_EOK; @@ -413,41 +421,42 @@ rt_err_t rt_timer_start(rt_timer_t timer) unsigned int row_lvl; rt_list_t *timer_list; rt_base_t level; - rt_bool_t need_schedule; rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]; unsigned int tst_nr; static unsigned int random_nr; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); - need_schedule = RT_FALSE; - - /* stop timer firstly */ - level = rt_hw_interrupt_disable(); - /* remove timer from list */ - _timer_remove(timer); - /* change status of timer */ - timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); - - timer->timeout_tick = rt_tick_get() + timer->init_tick; #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* insert timer to soft timer list */ timer_list = _soft_timer_list; + spinlock = &_soft_spinlock; } else #endif /* RT_USING_TIMER_SOFT */ { /* insert timer to system timer list */ timer_list = _timer_list; + spinlock = &_hard_spinlock; } + /* stop timer firstly */ + level = rt_spin_lock_irqsave(spinlock); + /* remove timer from list */ + _timer_remove(timer); + /* change status of timer */ + timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; + + RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); + + timer->timeout_tick = rt_tick_get() + timer->init_tick; + row_head[0] = &timer_list[0]; for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { @@ -510,18 +519,12 @@ rt_err_t rt_timer_start(rt_timer_t timer) { /* resume timer thread to check soft timer */ rt_thread_resume(&_timer_thread); - need_schedule = RT_TRUE; } } #endif /* RT_USING_TIMER_SOFT */ - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); - if (need_schedule) - { - rt_schedule(); - } return RT_EOK; } @@ -537,28 +540,35 @@ RTM_EXPORT(rt_timer_start); rt_err_t rt_timer_stop(rt_timer_t timer) { rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + struct rt_spinlock *spinlock; /* timer check */ 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; + } + level = rt_spin_lock_irqsave(spinlock); + if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); return -RT_ERROR; } - RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent))); _timer_remove(timer); /* change status */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); return RT_EOK; } @@ -575,13 +585,10 @@ RTM_EXPORT(rt_timer_stop); */ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) { - rt_base_t level; - /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); - level = rt_hw_interrupt_disable(); switch (cmd) { case RT_TIMER_CTRL_GET_TIME: @@ -636,7 +643,6 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) default: break; } - rt_hw_interrupt_enable(level); return RT_EOK; } @@ -655,14 +661,20 @@ void rt_timer_check(void) rt_base_t level; rt_list_t list; +#ifdef RT_USING_SMP + if (rt_hw_cpu_id() != 0) + { + return; + } +#endif + rt_list_init(&list); LOG_D("timer check enter"); current_tick = rt_tick_get(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_hard_spinlock); while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { @@ -685,6 +697,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); /* call timeout function */ t->timeout_func(t->parameter); @@ -693,7 +706,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); /* Check whether the timer object is detached or started again */ if (rt_list_isempty(&list)) { @@ -710,10 +723,7 @@ void rt_timer_check(void) } else break; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&_hard_spinlock, level); LOG_D("timer check leave"); } @@ -724,8 +734,13 @@ void rt_timer_check(void) */ 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); _timer_list_next_timeout(_timer_list, &next_timeout); + rt_spin_unlock_irqrestore(&_hard_spinlock, level); + return next_timeout; } @@ -742,11 +757,8 @@ void rt_soft_timer_check(void) rt_list_t list; rt_list_init(&list); - LOG_D("software timer check enter"); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_soft_spinlock); while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { @@ -773,8 +785,8 @@ void rt_soft_timer_check(void) rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1])); _soft_timer_status = RT_SOFT_TIMER_BUSY; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + + rt_spin_unlock_irqrestore(&_soft_spinlock, level); /* call timeout function */ t->timeout_func(t->parameter); @@ -782,8 +794,7 @@ void rt_soft_timer_check(void) RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t)); LOG_D("current tick: %d", current_tick); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_soft_spinlock); _soft_timer_status = RT_SOFT_TIMER_IDLE; /* Check whether the timer object is detached or started again */ @@ -802,8 +813,8 @@ void rt_soft_timer_check(void) } else break; /* not check anymore */ } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + + rt_spin_unlock_irqrestore(&_soft_spinlock, level); LOG_D("software timer check leave"); } @@ -815,12 +826,18 @@ void rt_soft_timer_check(void) */ static void _timer_thread_entry(void *parameter) { + rt_err_t ret = RT_ERROR; rt_tick_t next_timeout; + rt_base_t level; while (1) { /* get the next timeout tick */ - if (_timer_list_next_timeout(_soft_timer_list, &next_timeout) != RT_EOK) + level = rt_spin_lock_irqsave(&_soft_spinlock); + ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout); + rt_spin_unlock_irqrestore(&_soft_spinlock, level); + + if (ret != RT_EOK) { /* no software timer exist, suspend self. */ rt_thread_suspend_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE); @@ -860,6 +877,7 @@ void rt_system_timer_init(void) { rt_list_init(_timer_list + i); } + rt_spin_lock_init(&_hard_spinlock); } /** @@ -878,6 +896,7 @@ void rt_system_timer_thread_init(void) { rt_list_init(_soft_timer_list + i); } + rt_spin_lock_init(&_soft_spinlock); /* start software timer thread */ rt_thread_init(&_timer_thread, |
