diff options
author | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-05-20 12:36:01 +0000 |
---|---|---|
committer | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-05-20 12:36:01 +0000 |
commit | a8d7e2ab16f6c4a1a6e4f90010651b016ac6f7c1 (patch) | |
tree | 4123cb2913b2db3224b9c75ab8f9a49c60ea498c /cpukit/score/src | |
parent | 2011-05-20 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-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.c | 12 | ||||
-rw-r--r-- | cpukit/score/src/smplock.c | 86 |
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 ); } |