From cb07e5fb24afebdf233847da551d3ede80727345 Mon Sep 17 00:00:00 2001 From: shaojinchun Date: Thu, 26 Sep 2019 18:13:07 +0800 Subject: 开放spinlock相关函数 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cpu.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/scheduler.c | 11 ++++-- src/thread.c | 1 + 3 files changed, 122 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cpu.c b/src/cpu.c index fe3ba21bb0..a4075108e1 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -11,6 +11,119 @@ #include #include +#ifdef RT_USING_SMP +/*********************************** + * disable scheduler + ***********************************/ +static void rt_preempt_disable(void) +{ + register rt_base_t level; + struct rt_thread *current_thread; + + /* disable interrupt */ + level = rt_hw_local_irq_disable(); + + current_thread = rt_cpu_self()->current_thread; + 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); +} + +/*********************************** + * restore scheduler + ***********************************/ +static void rt_preempt_enable(void) +{ + register rt_base_t level; + struct rt_thread *current_thread; + + /* disable interrupt */ + level = rt_hw_local_irq_disable(); + + current_thread = rt_cpu_self()->current_thread; + if (!current_thread) + { + rt_hw_local_irq_enable(level); + return; + } + + /* unlock scheduler for local cpu */ + current_thread->scheduler_lock_nest --; + + rt_schedule(); + /* enable interrupt */ + rt_hw_local_irq_enable(level); +} +#endif + +void rt_spin_lock_init(rt_spinlock_t *lock) +{ +#ifdef RT_USING_SMP + rt_hw_spin_lock_init(&lock->lock); +#endif +} +RTM_EXPORT(rt_spin_lock_init) + +void rt_spin_lock(rt_spinlock_t *lock) +{ +#ifdef RT_USING_SMP + rt_preempt_disable(); + rt_hw_spin_lock(&lock->lock); +#else + rt_enter_critical(); +#endif +} +RTM_EXPORT(rt_spin_lock) + +void rt_spin_unlock(rt_spinlock_t *lock) +{ +#ifdef RT_USING_SMP + rt_hw_spin_unlock(&lock->lock); + rt_preempt_enable(); +#else + rt_exit_critical(); +#endif +} +RTM_EXPORT(rt_spin_unlock) + +rt_base_t rt_spin_lock_irqsave(rt_spinlock_t *lock) +{ + unsigned long level; + +#ifdef RT_USING_SMP + rt_preempt_disable(); + + level = rt_hw_local_irq_disable(); + rt_hw_spin_lock(&lock->lock); + + return level; +#else + return rt_hw_interrupt_disable(); +#endif +} +RTM_EXPORT(rt_spin_lock_irqsave) + +void rt_spin_unlock_irqrestore(rt_spinlock_t *lock, rt_base_t level) +{ +#ifdef RT_USING_SMP + rt_hw_spin_unlock(&lock->lock); + rt_hw_local_irq_enable(level); + + rt_preempt_enable(); +#else + rt_hw_interrupt_enable(level); +#endif +} +RTM_EXPORT(rt_spin_unlock_irqrestore) + #ifdef RT_USING_SMP static struct rt_cpu rt_cpus[RT_CPUS_NR]; diff --git a/src/scheduler.c b/src/scheduler.c index b487bd4b60..0faafaa2fc 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -840,11 +840,14 @@ void rt_enter_critical(void) */ /* lock scheduler for all cpus */ - if (current_thread->scheduler_lock_nest == !!current_thread->cpus_lock_nest) + if (current_thread->critical_lock_nest == 0) { rt_hw_spin_lock(&_rt_critical_lock); } + /* critical for local cpu */ + current_thread->critical_lock_nest ++; + /* lock scheduler for local cpu */ current_thread->scheduler_lock_nest ++; @@ -892,7 +895,9 @@ void rt_exit_critical(void) current_thread->scheduler_lock_nest --; - if (current_thread->scheduler_lock_nest == !!current_thread->cpus_lock_nest) + current_thread->critical_lock_nest --; + + if (current_thread->critical_lock_nest == 0) { rt_hw_spin_unlock(&_rt_critical_lock); } @@ -951,7 +956,7 @@ rt_uint16_t rt_critical_level(void) #ifdef RT_USING_SMP struct rt_thread *current_thread = rt_cpu_self()->current_thread; - return current_thread->scheduler_lock_nest; + return current_thread->critical_lock_nest; #else return rt_scheduler_lock_nest; #endif /*RT_USING_SMP*/ diff --git a/src/thread.c b/src/thread.c index ab203b1d49..a88729e52c 100644 --- a/src/thread.c +++ b/src/thread.c @@ -172,6 +172,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, /* lock init */ thread->scheduler_lock_nest = 0; thread->cpus_lock_nest = 0; + thread->critical_lock_nest = 0; #endif /*RT_USING_SMP*/ /* initialize cleanup function and user data */ -- cgit v1.3.1