diff --git a/include/nuttx/spinlock.h b/include/nuttx/spinlock.h index e7041f5df95..640a639a6d6 100644 --- a/include/nuttx/spinlock.h +++ b/include/nuttx/spinlock.h @@ -63,10 +63,14 @@ struct spinlock_s { - spinlock_t sp_lock; /* Indicates if the spinlock is locked or not. See the - * values SP_LOCKED and SP_UNLOCKED. */ - uint8_t sp_cpu; /* CPU holding the lock */ - uint16_t sp_count; /* The count of references by this CPU on the lock */ + volatile spinlock_t sp_lock; /* Indicates if the spinlock is locked or + * not. See the* values SP_LOCKED and + * SP_UNLOCKED. */ +#ifdef CONFIG_SMP + uint8_t sp_cpu; /* CPU holding the lock */ + uint16_t sp_count; /* The count of references by this CPU on + * the lock */ +#endif }; /**************************************************************************** @@ -93,7 +97,7 @@ struct spinlock_s * ****************************************************************************/ -spinlock_t up_testset(FAR spinlock_t *lock); +spinlock_t up_testset(volatile FAR spinlock_t *lock); /**************************************************************************** * Name: spinlock_initialize diff --git a/sched/Kconfig b/sched/Kconfig index 12b1c298a17..45e14fd0950 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -229,6 +229,35 @@ endmenu # Clocks and Timers menu "Tasks and Scheduling" +config SPINLOCK + bool "Support Spinlocks" + default n + depends on EXPERIMENTAL + ---help--- + Enables suppport for spinlocks. Spinlocks are current used only for + SMP suppport. + +config SMP + bool "Symmetric Multi-Processing (SMP)" + default n + depends on EXPERIMENTAL + select SPINLOCK + ---help--- + Enable support for Symmetric Multi-Processing (SMP) on a multi-CPU + platform. + +if SMP + +config SMP_NCPUS + int "Number of CPUs" + default 4 + range 2 32 + ---help--- + This value identifies the number of CPUs support by the processor + that will be used for SMP. + +endif # SMP + choice prompt "Initialization Task" default INIT_ENTRYPOINT if !BUILD_KERNEL @@ -307,11 +336,6 @@ config RR_INTERVAL Round roben scheduling (SCHED_RR) is enabled by setting this interval to a positive, non-zero value. -config SPINLOCK - bool "Support Spinlocks" - default n - depends on EXPERIMENTAL - config SCHED_SPORADIC bool "Support sporadic scheduling" default n diff --git a/sched/semaphore/spinlock.c b/sched/semaphore/spinlock.c index b39cfe4d9a2..20bb3d048a3 100644 --- a/sched/semaphore/spinlock.c +++ b/sched/semaphore/spinlock.c @@ -86,8 +86,10 @@ void spinlock_initialize(FAR struct spinlock_s *lock) DEBUGASSERT(lock != NULL); lock->sp_lock = SP_UNLOCKED; +#ifdef CONFIG_SMP lock->sp_cpu = IMPOSSIBLE_CPU; lock->sp_count = 0; +#endif } /**************************************************************************** @@ -111,6 +113,7 @@ void spinlock_initialize(FAR struct spinlock_s *lock) void spinlock(FAR struct spinlock_s *lock) { +#ifdef CONFIG_SMP irqstate_t flags; uint8_t cpu = this_cpu(); @@ -158,6 +161,20 @@ void spinlock(FAR struct spinlock_s *lock) } irqrestore(flags); + +#else /* CONFIG_SMP */ + + /* Take the lock. REVISIT: We should set an indication in the TCB that + * the thread is spinning. This might be useful in determining some + * scheduling actions? + */ + + while (up_testset(&lock->sp_lock) == SP_LOCKED) + { + sched_yield(); + } + +#endif /* CONFIG_SMP */ } /**************************************************************************** @@ -179,6 +196,7 @@ void spinlock(FAR struct spinlock_s *lock) void spinunlock(FAR struct spinlock_s *lock) { +#ifdef CONFIG_SMP irqstate_t flags; #ifdef CONFIG_SPINLOCK_LOCKDOWN uint8_t cpu = this_cpu(); @@ -225,6 +243,14 @@ void spinunlock(FAR struct spinlock_s *lock) } irqrestore(flags); + +#else /* CONFIG_SMP */ + /* Just mark the spinlock unlocked */ + + DEBUGASSERT(lock != NULL && lock->sp-lock = SP_LOCKED); + lock->sp_lock = SP_UNLOCKED; + +#endif /* CONFIG_SMP */ } #endif /* CONFIG_SPINLOCK */