summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Kconfig7
-rw-r--r--src/clock.c36
-rw-r--r--src/components.c6
-rw-r--r--src/cpu.c121
-rw-r--r--src/idle.c39
-rw-r--r--src/ipc.c319
-rw-r--r--src/irq.c30
-rw-r--r--src/mempool.c42
-rw-r--r--src/object.c96
-rw-r--r--src/scheduler_mp.c504
-rw-r--r--src/signal.c11
-rw-r--r--src/thread.c168
-rw-r--r--src/timer.c165
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.
diff --git a/src/cpu.c b/src/cpu.c
index 0ecf67d1e5..8161b1aeb2 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -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);
}
/**
diff --git a/src/ipc.c b/src/ipc.c
index fe85c9d56c..75bdb2eafc 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -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();
diff --git a/src/irq.c b/src/irq.c
index e38f10e6f4..45a7cf4b66 100644
--- a/src/irq.c
+++ b/src/irq.c
@@ -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)&current_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)&current_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,