diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-07-31 12:59:35 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-07-31 15:09:04 +0200 |
commit | 2d915cf3895fb84a2bc2ab33adbcf8cdad6b62c6 (patch) | |
tree | 3b5807993b4e71b2095624176b02b28d87752668 | |
parent | sptests/sp37: Improved interrupt lock tests (diff) | |
download | rtems-2d915cf3895fb84a2bc2ab33adbcf8cdad6b62c6.tar.bz2 |
score: Add and use ISR locks
ISR locks are low-level locks to protect critical sections accessed by
threads and interrupt service routines.
On single processor configurations the ISR locks degrade to simple ISR
disable/enable sequences. No additional storage or objects are
required.
This synchronization primitive is supported on SMP configurations. Here
SMP locks are used.
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/intr.h | 79 | ||||
-rw-r--r-- | cpukit/score/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/isrlock.h | 141 | ||||
-rw-r--r-- | cpukit/score/preinstall.am | 4 | ||||
-rw-r--r-- | testsuites/sptests/sp37/init.c | 18 |
5 files changed, 195 insertions, 48 deletions
diff --git a/cpukit/rtems/include/rtems/rtems/intr.h b/cpukit/rtems/include/rtems/rtems/intr.h index d687e462e3..ae6dfcc59e 100644 --- a/cpukit/rtems/include/rtems/rtems/intr.h +++ b/cpukit/rtems/include/rtems/rtems/intr.h @@ -26,7 +26,7 @@ extern "C" { #endif #include <rtems/score/isr.h> -#include <rtems/score/smplock.h> +#include <rtems/score/isrlock.h> /** * @defgroup ClassicINTR Interrupts @@ -143,99 +143,80 @@ rtems_status_code rtems_interrupt_catch( * @brief Low-level lock to protect critical sections accessed by threads and * interrupt service routines. * - * This synchronization primitive is supported on SMP configurations. + * On single processor configurations the interrupt locks degrade to simple + * interrupt disable/enable sequences. No additional storage or objects are + * required. * + * This synchronization primitive is supported on SMP configurations. Here SMP + * locks are used. * @{ */ /** * @brief Interrupt lock control. */ -typedef struct { - #if defined( RTEMS_SMP ) - SMP_lock_Control lock; - #endif -} rtems_interrupt_lock; +typedef ISR_lock_Control rtems_interrupt_lock; /** * @brief Initializer for static initialization of interrupt locks. */ -#if defined( RTEMS_SMP ) - #define RTEMS_INTERRUPT_LOCK_INITIALIZER \ - { SMP_LOCK_INITIALIZER } -#else - #define RTEMS_INTERRUPT_LOCK_INITIALIZER \ - { } -#endif +#define RTEMS_INTERRUPT_LOCK_INITIALIZER ISR_LOCK_INITIALIZER /** * @brief Initializes an interrupt lock. * * Concurrent initialization leads to unpredictable results. + * + * @param[in,out] _lock The interrupt lock. */ -#if defined( RTEMS_SMP ) - #define rtems_interrupt_lock_initialize( _lock ) \ - _SMP_lock_Initialize( &( _lock )->lock ) -#else - #define rtems_interrupt_lock_initialize( _lock ) \ - do { \ - (void) _lock; \ - } while (0) -#endif +#define rtems_interrupt_lock_initialize( _lock ) \ + _ISR_lock_Initialize( _lock ) /** * @brief Acquires an interrupt lock. * - * Interrupts will be disabled. On SMP configurations this function acquires a - * SMP lock. + * Interrupts will be disabled. On SMP configurations this function acquires + * an SMP lock. * * This function can be used in thread and interrupt context. * + * @param[in,out] _lock The interrupt lock. + * @param[out] _isr_cookie The interrupt status to restore will be returned. + * * @see rtems_interrupt_lock_release(). */ -#if defined( RTEMS_SMP ) - #define rtems_interrupt_lock_acquire( _lock, _isr_cookie ) \ - _SMP_lock_ISR_disable_and_acquire( &( _lock )->lock, _isr_cookie ) -#else - #define rtems_interrupt_lock_acquire( _lock, _isr_cookie ) \ - do { \ - (void) _lock; \ - rtems_interrupt_disable( _isr_cookie ); \ - } while (0) -#endif +#define rtems_interrupt_lock_acquire( _lock, _isr_cookie ) \ + _ISR_lock_Acquire( _lock, _isr_cookie ) /** * @brief Releases an interrupt lock. * * The interrupt status will be restored. On SMP configurations this function - * releases a SMP lock. + * releases an SMP lock. * * This function can be used in thread and interrupt context. * + * @param[in,out] _lock The interrupt lock. + * @param[in] _isr_cookie The interrupt status to restore. + * * @see rtems_interrupt_lock_acquire(). */ -#if defined( RTEMS_SMP ) - #define rtems_interrupt_lock_release( _lock, _isr_cookie ) \ - _SMP_lock_Release_and_ISR_enable( &( _lock )->lock, _isr_cookie ) -#else - #define rtems_interrupt_lock_release( _lock, _isr_cookie ) \ - do { \ - (void) _lock; \ - rtems_interrupt_enable( _isr_cookie ); \ - } while (0) -#endif +#define rtems_interrupt_lock_release( _lock, _isr_cookie ) \ + _ISR_lock_Release( _lock, _isr_cookie ) /** * @brief Acquires an interrupt lock in the corresponding interrupt service * routine. * * The interrupt status will remain unchanged. On SMP configurations this - * function acquires a SMP lock. + * function acquires an SMP lock. * * In case the corresponding interrupt service routine can be interrupted by * higher priority interrupts and these interrupts enter the critical section * protected by this lock, then the result is unpredictable. * + * @param[in,out] _lock The interrupt lock. + * * @see rtems_interrupt_lock_release_isr(). */ #if defined( RTEMS_SMP ) @@ -253,7 +234,9 @@ typedef struct { * routine. * * The interrupt status will remain unchanged. On SMP configurations this - * function releases a SMP lock. + * function releases an SMP lock. + * + * @param[in,out] _lock The interrupt lock. * * @see rtems_interrupt_lock_acquire_isr(). */ diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 67d4b5e85e..eb7376dd79 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -36,6 +36,7 @@ include_rtems_score_HEADERS += include/rtems/score/protectedheap.h include_rtems_score_HEADERS += include/rtems/score/interr.h include_rtems_score_HEADERS += include/rtems/score/isr.h include_rtems_score_HEADERS += include/rtems/score/isrlevel.h +include_rtems_score_HEADERS += include/rtems/score/isrlock.h include_rtems_score_HEADERS += include/rtems/score/freechain.h include_rtems_score_HEADERS += include/rtems/score/object.h include_rtems_score_HEADERS += include/rtems/score/objectimpl.h diff --git a/cpukit/score/include/rtems/score/isrlock.h b/cpukit/score/include/rtems/score/isrlock.h new file mode 100644 index 0000000000..fb20a8e2d5 --- /dev/null +++ b/cpukit/score/include/rtems/score/isrlock.h @@ -0,0 +1,141 @@ +/** + * @file + * + * @ingroup ScoreISRLocks + * + * @brief ISR Locks + */ + +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#ifndef _RTEMS_SCORE_ISR_LOCK_H +#define _RTEMS_SCORE_ISR_LOCK_H + +#include <rtems/score/isrlevel.h> +#include <rtems/score/smplock.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup ScoreISRLocks ISR Locks + * + * @ingroup ScoreISR + * + * @brief Low-level lock to protect critical sections accessed by threads and + * interrupt service routines. + * + * On single processor configurations the ISR locks degrade to simple ISR + * disable/enable sequences. No additional storage or objects are required. + * + * This synchronization primitive is supported on SMP configurations. Here SMP + * locks are used. + * + * @{ + */ + +/** + * @brief ISR lock control. + */ +typedef struct { + #if defined( RTEMS_SMP ) + SMP_lock_Control lock; + #endif +} ISR_lock_Control; + +/** + * @brief Initializer for static initialization of ISR locks. + */ +#if defined( RTEMS_SMP ) + #define ISR_LOCK_INITIALIZER \ + { SMP_LOCK_INITIALIZER } +#else + #define ISR_LOCK_INITIALIZER \ + { } +#endif + +/** + * @brief Initializes an ISR lock. + * + * Concurrent initialization leads to unpredictable results. + * + * @param[in,out] _lock The ISR lock control. + */ +#if defined( RTEMS_SMP ) + #define _ISR_lock_Initialize( _lock ) \ + _SMP_lock_Initialize( &( _lock )->lock ) +#else + #define _ISR_lock_Initialize( _lock ) \ + do { \ + (void) _lock; \ + } while (0) +#endif + +/** + * @brief Acquires an ISR lock. + * + * Interrupts will be disabled. On SMP configurations this function acquires + * an SMP lock. + * + * This function can be used in thread and interrupt context. + * + * @param[in,out] _lock The ISR lock control. + * @param[out] _isr_cookie The interrupt status to restore will be returned. + * + * @see _ISR_lock_Release(). + */ +#if defined( RTEMS_SMP ) + #define _ISR_lock_Acquire( _lock, _isr_cookie ) \ + _SMP_lock_ISR_disable_and_acquire( &( _lock )->lock, _isr_cookie ) +#else + #define _ISR_lock_Acquire( _lock, _isr_cookie ) \ + do { \ + (void) _lock; \ + _ISR_Disable( _isr_cookie ); \ + } while (0) +#endif + +/** + * @brief Releases an ISR lock. + * + * The interrupt status will be restored. On SMP configurations this function + * releases an SMP lock. + * + * This function can be used in thread and interrupt context. + * + * @param[in,out] _lock The ISR lock control. + * @param[in] _isr_cookie The interrupt status to restore. + * + * @see _ISR_lock_Acquire(). + */ +#if defined( RTEMS_SMP ) + #define _ISR_lock_Release( _lock, _isr_cookie ) \ + _SMP_lock_Release_and_ISR_enable( &( _lock )->lock, _isr_cookie ) +#else + #define _ISR_lock_Release( _lock, _isr_cookie ) \ + do { \ + (void) _lock; \ + _ISR_Enable( _isr_cookie ); \ + } while (0) +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RTEMS_SCORE_ISR_LOCK_H */ diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index 5d9cbed10e..aff76c900b 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -127,6 +127,10 @@ $(PROJECT_INCLUDE)/rtems/score/isrlevel.h: include/rtems/score/isrlevel.h $(PROJ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isrlevel.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isrlevel.h +$(PROJECT_INCLUDE)/rtems/score/isrlock.h: include/rtems/score/isrlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isrlock.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isrlock.h + $(PROJECT_INCLUDE)/rtems/score/freechain.h: include/rtems/score/freechain.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/freechain.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/freechain.h diff --git a/testsuites/sptests/sp37/init.c b/testsuites/sptests/sp37/init.c index 0ae0b2118b..6f85c76232 100644 --- a/testsuites/sptests/sp37/init.c +++ b/testsuites/sptests/sp37/init.c @@ -44,6 +44,23 @@ rtems_timer_service_routine test_isr_in_progress( /* test bodies */ +static void test_isr_locks( void ) +{ + ISR_Level normal_interrupt_level = _ISR_Get_level(); + ISR_lock_Control initialized = ISR_LOCK_INITIALIZER; + ISR_lock_Control lock; + ISR_Level level; + + _ISR_lock_Initialize( &lock ); + rtems_test_assert( memcmp( &lock, &initialized, sizeof( lock ) ) == 0 ); + + _ISR_lock_Acquire( &lock, level ); + rtems_test_assert( normal_interrupt_level != _ISR_Get_level() ); + _ISR_lock_Release( &lock, level ); + + rtems_test_assert( normal_interrupt_level == _ISR_Get_level() ); +} + static rtems_mode get_interrupt_level( void ) { rtems_status_code sc; @@ -228,6 +245,7 @@ rtems_task Init( puts( "\n\n*** TEST 37 ***" ); + test_isr_locks(); test_interrupt_locks(); build_time( &time, 12, 31, 1988, 9, 0, 0, 0 ); |