diff options
author | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-05-23 13:30:15 +0000 |
---|---|---|
committer | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-05-23 13:30:15 +0000 |
commit | 3a8a9997866ded736b038322be6adccee63eb3bd (patch) | |
tree | 64909329b677082e99d3d8bcb71795a43e70192d /cpukit | |
parent | Fix typo. (diff) | |
download | rtems-3a8a9997866ded736b038322be6adccee63eb3bd.tar.bz2 |
2011-05-23 Jennifer Averett <Jennifer.Averett@OARcorp.com>
* score/Makefile.am, score/include/rtems/score/thread.h,
score/inline/rtems/score/thread.inl: Add smp support to dispable
dispatch level accesses.
* score/src/threaddispatchdisablelevel.c: New file.
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/ChangeLog | 7 | ||||
-rw-r--r-- | cpukit/score/Makefile.am | 4 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 55 | ||||
-rw-r--r-- | cpukit/score/inline/rtems/score/thread.inl | 112 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatchdisablelevel.c | 133 |
5 files changed, 262 insertions, 49 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index db98580c86..590165a1f5 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,10 @@ +2011-05-23 Jennifer Averett <Jennifer.Averett@OARcorp.com> + + * score/Makefile.am, score/include/rtems/score/thread.h, + score/inline/rtems/score/thread.inl: Add smp support to dispable + dispatch level accesses. + * score/src/threaddispatchdisablelevel.c: New file. + 2011-05-20 Jennifer Averett <Jennifer.Averett@OARcorp.com> PR 1787/cpukit diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 73d9cee638..9138178e33 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -241,6 +241,10 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \ src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \ src/threadstartmultitasking.c src/threadtickletimeslice.c \ src/iterateoverthreads.c src/threadblockingoperationcancel.c + +if HAS_SMP +libscore_a_SOURCES += src/threaddispatchdisablelevel.c +endif ## THREADQ_C_FILES libscore_a_SOURCES += src/threadq.c src/threadqdequeue.c \ diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 785d8a149e..c3462024d9 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -464,6 +464,14 @@ SCORE_EXTERN Context_Control _Thread_BSP_context; */ SCORE_EXTERN volatile uint32_t _Thread_Dispatch_disable_level; +#if defined(RTEMS_SMP) + /** + * The following declares the smp spinlock to be used to control + * the dispatch critical section accesses across cpus. + */ + SCORE_EXTERN SMP_lock_spinlock_nested_Control _Thread_Dispatch_disable_level_lock; +#endif + /** * The following holds how many user extensions are in the system. This * is used to determine how many user extension data areas to allocate @@ -784,6 +792,53 @@ void _Thread_blocking_operation_Cancel( ISR_Level level ); + +#if defined(RTEMS_SMP) + + /** @brief _Thread_Dispatch_initialization + * + * This routine initializes the thread dispatching subsystem. + */ + void _Thread_Dispatch_initialization(void); + + /** @brief _Thread_Dispatch_in_critical_section + * + * This routine returns true if thread dispatch indicates + * that we are in a critical section. + */ + bool _Thread_Dispatch_in_critical_section(void); + + /** @brief _Thread_Dispatch_get_disable_level + * + * This routine returns value of the the thread dispatch level. + */ + uint32_t _Thread_Dispatch_get_disable_level(void); + + /** @brief _Thread_Dispatch_set_disable_level + * + * This routine sets thread dispatch level to the + * value passed in. + */ + uint32_t _Thread_Dispatch_set_disable_level(uint32_t value); + + /** @brief _Thread_Dispatch_increment_disable_level + * + * This rountine increments the thread dispatch level + */ + uint32_t _Thread_Dispatch_increment_disable_level(void); + + /** @brief _Thread_Dispatch_decrement_disable_level + * + * This routine decrements the thread dispatch level. + */ + uint32_t _Thread_Dispatch_decrement_disable_level(void); + +#else + /* + * The _Thread_Dispatch_... functions are in thread.inl + */ +#endif + #ifndef __RTEMS_APPLICATION__ #include <rtems/score/thread.inl> #endif diff --git a/cpukit/score/inline/rtems/score/thread.inl b/cpukit/score/inline/rtems/score/thread.inl index 7ff1e615fb..ba13bda908 100644 --- a/cpukit/score/inline/rtems/score/thread.inl +++ b/cpukit/score/inline/rtems/score/thread.inl @@ -31,63 +31,77 @@ * @{ */ -/** - * This routine returns true if thread dispatch indicates - * that we are in a critical section. - */ -RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_in_critical_section(void) -{ - if ( _Thread_Dispatch_disable_level == 0 ) - return false; +#if defined(RTEMS_SMP) - return true; -} + /* + * The _Thread_Dispatch_... functions are prototyped in thread.h. + */ -/** - * This routine returns value of the the thread dispatch level. - */ -RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void) -{ - return _Thread_Dispatch_disable_level; -} +#else -/** - * This routine sets thread dispatch level to the - * value passed in. - */ -RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_set_disable_level(uint32_t value) -{ - _Thread_Dispatch_disable_level = value; - return value; -} + /** @brief _Thread_Dispatch_in_critical_section + * + * This routine returns true if thread dispatch indicates + * that we are in a critical section. + */ + RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_in_critical_section(void) + { + if ( _Thread_Dispatch_disable_level == 0 ) + return false; -/** - * This rountine increments the thread dispatch level - */ -RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_increment_disable_level(void) -{ - _Thread_Dispatch_disable_level++; - return _Thread_Dispatch_disable_level; -} + return true; + } -/** - * This routine decrements the thread dispatch level. - */ -RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_decrement_disable_level(void) -{ - _Thread_Dispatch_disable_level--; - return _Thread_Dispatch_disable_level; -} + /** @brief _Thread_Dispatch_get_disable_level + * + * This routine returns value of the the thread dispatch level. + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void) + { + return _Thread_Dispatch_disable_level; + } -/** - * This routine initializes the thread dispatching subsystem. - */ + /** @brief _Thread_Dispatch_set_disable_level + * + * This routine sets thread dispatch level to the + * value passed in. + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_set_disable_level(uint32_t value) + { + _Thread_Dispatch_disable_level = value; + return value; + } -RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) -{ - _Thread_Dispatch_set_disable_level( 1 ); -} + /** @brief _Thread_Dispatch_increment_disable_level + * + * This rountine increments the thread dispatch level + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_increment_disable_level(void) + { + _Thread_Dispatch_disable_level++; + return _Thread_Dispatch_disable_level; + } + + /** @brief _Thread_Dispatch_decrement_disable_level + * + * This routine decrements the thread dispatch level. + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_decrement_disable_level(void) + { + _Thread_Dispatch_disable_level--; + return _Thread_Dispatch_disable_level; + } + + /** @brief _Thread_Dispatch_initialization + * + * This routine initializes the thread dispatching subsystem. + */ + RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) + { + _Thread_Dispatch_set_disable_level( 1 ); + } +#endif /** * This routine halts multitasking and returns control to diff --git a/cpukit/score/src/threaddispatchdisablelevel.c b/cpukit/score/src/threaddispatchdisablelevel.c new file mode 100644 index 0000000000..f0d1cf7a61 --- /dev/null +++ b/cpukit/score/src/threaddispatchdisablelevel.c @@ -0,0 +1,133 @@ +/* + * Thread Dispatch Disable Level Methods + * + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include <rtems/system.h> +#include <rtems/score/apiext.h> +#include <rtems/score/context.h> +#include <rtems/score/interr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/score/priority.h> +#include <rtems/score/states.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/thread.h> + +void _Thread_Dispatch_initialization( void ) +{ + _Thread_Dispatch_disable_level = 0; + _SMP_lock_spinlock_nested_Initialize(&_Thread_Dispatch_disable_level_lock); + _Thread_Dispatch_set_disable_level( 1 ); +} + +bool _Thread_Dispatch_in_critical_section(void) +{ + if ( _Thread_Dispatch_disable_level == 0 ) + return false; + + return true; +} + +uint32_t _Thread_Dispatch_get_disable_level(void) +{ + return _Thread_Dispatch_disable_level; +} + +uint32_t _Thread_Dispatch_increment_disable_level(void) +{ + ISR_Level isr_level; + uint32_t level; + + /* + * Note: _SMP_lock_spinlock_nested_Obtain returns + * with ISR's disabled and the isr_level that + * should be restored after a short period. + * + * Here we obtain the lock and increment the + * Thread dispatch disable level while under the + * protection of the isr being off. After this + * point it is safe to re-enable ISRs and allow + * the dispatch disable lock to provide protection. + */ + + isr_level = _SMP_lock_spinlock_nested_Obtain( + &_Thread_Dispatch_disable_level_lock + ); + + _Thread_Dispatch_disable_level++; + level = _Thread_Dispatch_disable_level; + + _ISR_Enable(isr_level); + + return level; +} + +uint32_t _Thread_Dispatch_decrement_disable_level(void) +{ + ISR_Level isr_level; + uint32_t level; + + /* First we must disable ISRs in order to protect + * accesses to the dispatch disable level. + */ + + _ISR_Disable( isr_level ); + + _Thread_Dispatch_disable_level--; + level = _Thread_Dispatch_disable_level; + + + /* + * Note: _SMP_lock_spinlock_nested_Obtain returns with + * ISR's disabled and _SMP_lock_spinlock_nested_Release + * is responsable for re-enabling interrupts. + */ + _SMP_lock_spinlock_nested_Release( + &_Thread_Dispatch_disable_level_lock, + isr_level + ); + + return level; +} + + +/* + * Note this method is taking a heavy handed approach to + * setting the dispatch level. This may be optimized at a + * later timee, but it must be in such a way that the nesting + * level is decremented by the same number as the dispatch level. + * This approach is safest until we are sure the nested spinlock + * is successfully working with smp isr source code. + */ + +uint32_t _Thread_Dispatch_set_disable_level(uint32_t value) +{ + /* + * If we need the dispatch level to go higher + * call increment method the desired number of times. + */ + + while ( value > _Thread_Dispatch_disable_level ) { + _Thread_Dispatch_increment_disable_level(); + } + + /* + * If we need the dispatch level to go lower + * call increment method the desired number of times. + */ + + while ( value < _Thread_Dispatch_disable_level ) { + _Thread_Dispatch_decrement_disable_level(); + } + + return value; +} |