diff options
Diffstat (limited to 'src/cpu.c')
| -rw-r--r-- | src/cpu.c | 121 |
1 files changed, 56 insertions, 65 deletions
@@ -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 */ |
