summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src
diff options
context:
space:
mode:
authorJennifer Averett <Jennifer.Averett@OARcorp.com>2011-05-20 12:36:01 +0000
committerJennifer Averett <Jennifer.Averett@OARcorp.com>2011-05-20 12:36:01 +0000
commita8d7e2ab16f6c4a1a6e4f90010651b016ac6f7c1 (patch)
tree4123cb2913b2db3224b9c75ab8f9a49c60ea498c /cpukit/score/src
parent2011-05-20 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff)
downloadrtems-a8d7e2ab16f6c4a1a6e4f90010651b016ac6f7c1.tar.bz2
2011-05-20 Jennifer Averett <Jennifer.Averett@OARcorp.com>
PR 1787/cpukit * score/include/rtems/score/percpu.h, score/include/rtems/score/smplock.h, score/src/smp.c, score/src/smplock.c: Add nesting support to smp spinlock.
Diffstat (limited to 'cpukit/score/src')
-rw-r--r--cpukit/score/src/smp.c12
-rw-r--r--cpukit/score/src/smplock.c86
2 files changed, 78 insertions, 20 deletions
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 068285c114..9714add5ea 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -80,10 +80,10 @@ void rtems_smp_process_interrupt(void)
cpu = bsp_smp_processor_id();
- level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
message = _Per_CPU_Information[cpu].message;
_Per_CPU_Information[cpu].message &= ~message;
- _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+ _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
#if defined(SMP_DEBUG)
{
@@ -126,9 +126,9 @@ void rtems_smp_send_message(
{
ISR_Level level;
- level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
_Per_CPU_Information[cpu].message |= message;
- _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+ _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
bsp_smp_interrupt_cpu( cpu );
}
@@ -145,9 +145,9 @@ void rtems_smp_broadcast_message(
for ( dest_cpu=0 ; dest_cpu < _SMP_Processor_count; dest_cpu++ ) {
if ( cpu == dest_cpu )
continue;
- level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
_Per_CPU_Information[dest_cpu].message |= message;
- _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+ _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
}
bsp_smp_broadcast_interrupt();
}
diff --git a/cpukit/score/src/smplock.c b/cpukit/score/src/smplock.c
index 1dd691835b..91589b5c54 100644
--- a/cpukit/score/src/smplock.c
+++ b/cpukit/score/src/smplock.c
@@ -15,35 +15,93 @@
#include <rtems/system.h>
#include <rtems/score/smplock.h>
+#include <rtems/score/smp.h>
-void _SMP_lock_Spinlock_Initialize(
- SMP_lock_Control *lock
+#if defined (RTEMS_DEBUG)
+ #include <rtems/bspIo.h>
+#endif
+
+void _SMP_lock_spinlock_simple_Initialize(
+ SMP_lock_spinlock_simple_Control *lock
)
{
*lock = 0;
}
-ISR_Level _SMP_lock_Spinlock_Obtain(
- SMP_lock_Control *lock
+ISR_Level _SMP_lock_spinlock_simple_Obtain(
+ SMP_lock_spinlock_simple_Control *lock
+)
+{
+ ISR_Level level;
+ uint32_t value = 1;
+ uint32_t previous;
+
+ /* Note: Disable provides an implicit memory barrier. */
+ _ISR_Disable( level );
+ do {
+ SMP_CPU_SWAP( lock, value, previous );
+ } while (previous == 1);
+
+ return level;
+}
+
+void _SMP_lock_spinlock_simple_Release(
+ SMP_lock_spinlock_simple_Control *lock,
+ ISR_Level level
+)
+{
+ *lock = 0;
+ _ISR_Enable( level );
+}
+
+void _SMP_lock_spinlock_nested_Initialize(
+ SMP_lock_spinlock_nested_Control *lock
+)
+{
+ lock->count = 0;
+ lock->cpu_id = 0;
+}
+
+ISR_Level _SMP_lock_spinlock_nested_Obtain(
+ SMP_lock_spinlock_nested_Control *lock
)
{
- ISR_Level level;
+ ISR_Level level = 0;
uint32_t value = 1;
uint32_t previous;
+ int cpu_id;
/* Note: Disable provides an implicit memory barrier. */
- _ISR_Disable( level );
- do {
- SMP_CPU_SWAP( lock, value, previous );
- } while (previous == 1);
+ _ISR_Disable( level );
+
+ cpu_id = bsp_smp_processor_id();
+
+ /* Deal with nested calls from one cpu */
+ if ( (lock->count > 0) && (cpu_id == lock->cpu_id) ) {
+ lock->count++;
+ return level;
+ }
+
+ do {
+ SMP_CPU_SWAP( lock, value, previous );
+ } while (previous == 1);
+
+ lock->count++;
+ lock->cpu_id = cpu_id;
+
return level;
}
-void _SMP_lock_Spinlock_Release(
- SMP_lock_Control *lock,
- ISR_Level level
+void _SMP_lock_spinlock_nested_Release(
+ SMP_lock_spinlock_nested_Control *lock,
+ ISR_Level level
)
{
- *lock = 0;
- _ISR_Enable( level );
+#if defined(RTEMS_DEBUG)
+ if ( lock->count == 0 )
+ printk ("Releasing spinlock when count is already zero?!?!\n");
+#endif
+ lock->count--;
+
+ _ISR_Enable( level );
}