forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -26,7 +26,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <rtems/score/isr.h>
|
#include <rtems/score/isr.h>
|
||||||
#include <rtems/score/smplock.h>
|
#include <rtems/score/isrlock.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup ClassicINTR Interrupts
|
* @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
|
* @brief Low-level lock to protect critical sections accessed by threads and
|
||||||
* interrupt service routines.
|
* 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.
|
* @brief Interrupt lock control.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef ISR_lock_Control rtems_interrupt_lock;
|
||||||
#if defined( RTEMS_SMP )
|
|
||||||
SMP_lock_Control lock;
|
|
||||||
#endif
|
|
||||||
} rtems_interrupt_lock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializer for static initialization of interrupt locks.
|
* @brief Initializer for static initialization of interrupt locks.
|
||||||
*/
|
*/
|
||||||
#if defined( RTEMS_SMP )
|
#define RTEMS_INTERRUPT_LOCK_INITIALIZER ISR_LOCK_INITIALIZER
|
||||||
#define RTEMS_INTERRUPT_LOCK_INITIALIZER \
|
|
||||||
{ SMP_LOCK_INITIALIZER }
|
|
||||||
#else
|
|
||||||
#define RTEMS_INTERRUPT_LOCK_INITIALIZER \
|
|
||||||
{ }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes an interrupt lock.
|
* @brief Initializes an interrupt lock.
|
||||||
*
|
*
|
||||||
* Concurrent initialization leads to unpredictable results.
|
* Concurrent initialization leads to unpredictable results.
|
||||||
|
*
|
||||||
|
* @param[in,out] _lock The interrupt lock.
|
||||||
*/
|
*/
|
||||||
#if defined( RTEMS_SMP )
|
#define rtems_interrupt_lock_initialize( _lock ) \
|
||||||
#define rtems_interrupt_lock_initialize( _lock ) \
|
_ISR_lock_Initialize( _lock )
|
||||||
_SMP_lock_Initialize( &( _lock )->lock )
|
|
||||||
#else
|
|
||||||
#define rtems_interrupt_lock_initialize( _lock ) \
|
|
||||||
do { \
|
|
||||||
(void) _lock; \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Acquires an interrupt lock.
|
* @brief Acquires an interrupt lock.
|
||||||
*
|
*
|
||||||
* Interrupts will be disabled. On SMP configurations this function acquires a
|
* Interrupts will be disabled. On SMP configurations this function acquires
|
||||||
* SMP lock.
|
* an SMP lock.
|
||||||
*
|
*
|
||||||
* This function can be used in thread and interrupt context.
|
* 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().
|
* @see rtems_interrupt_lock_release().
|
||||||
*/
|
*/
|
||||||
#if defined( RTEMS_SMP )
|
#define rtems_interrupt_lock_acquire( _lock, _isr_cookie ) \
|
||||||
#define rtems_interrupt_lock_acquire( _lock, _isr_cookie ) \
|
_ISR_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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Releases an interrupt lock.
|
* @brief Releases an interrupt lock.
|
||||||
*
|
*
|
||||||
* The interrupt status will be restored. On SMP configurations this function
|
* 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.
|
* 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().
|
* @see rtems_interrupt_lock_acquire().
|
||||||
*/
|
*/
|
||||||
#if defined( RTEMS_SMP )
|
#define rtems_interrupt_lock_release( _lock, _isr_cookie ) \
|
||||||
#define rtems_interrupt_lock_release( _lock, _isr_cookie ) \
|
_ISR_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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Acquires an interrupt lock in the corresponding interrupt service
|
* @brief Acquires an interrupt lock in the corresponding interrupt service
|
||||||
* routine.
|
* routine.
|
||||||
*
|
*
|
||||||
* The interrupt status will remain unchanged. On SMP configurations this
|
* 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
|
* In case the corresponding interrupt service routine can be interrupted by
|
||||||
* higher priority interrupts and these interrupts enter the critical section
|
* higher priority interrupts and these interrupts enter the critical section
|
||||||
* protected by this lock, then the result is unpredictable.
|
* protected by this lock, then the result is unpredictable.
|
||||||
*
|
*
|
||||||
|
* @param[in,out] _lock The interrupt lock.
|
||||||
|
*
|
||||||
* @see rtems_interrupt_lock_release_isr().
|
* @see rtems_interrupt_lock_release_isr().
|
||||||
*/
|
*/
|
||||||
#if defined( RTEMS_SMP )
|
#if defined( RTEMS_SMP )
|
||||||
@@ -253,7 +234,9 @@ typedef struct {
|
|||||||
* routine.
|
* routine.
|
||||||
*
|
*
|
||||||
* The interrupt status will remain unchanged. On SMP configurations this
|
* 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().
|
* @see rtems_interrupt_lock_acquire_isr().
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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/interr.h
|
||||||
include_rtems_score_HEADERS += include/rtems/score/isr.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/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/freechain.h
|
||||||
include_rtems_score_HEADERS += include/rtems/score/object.h
|
include_rtems_score_HEADERS += include/rtems/score/object.h
|
||||||
include_rtems_score_HEADERS += include/rtems/score/objectimpl.h
|
include_rtems_score_HEADERS += include/rtems/score/objectimpl.h
|
||||||
|
|||||||
141
cpukit/score/include/rtems/score/isrlock.h
Normal file
141
cpukit/score/include/rtems/score/isrlock.h
Normal file
@@ -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 */
|
||||||
@@ -127,6 +127,10 @@ $(PROJECT_INCLUDE)/rtems/score/isrlevel.h: include/rtems/score/isrlevel.h $(PROJ
|
|||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isrlevel.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isrlevel.h
|
||||||
PREINSTALL_FILES += $(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)
|
$(PROJECT_INCLUDE)/rtems/score/freechain.h: include/rtems/score/freechain.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
|
||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/freechain.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/freechain.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/freechain.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/freechain.h
|
||||||
|
|||||||
@@ -44,6 +44,23 @@ rtems_timer_service_routine test_isr_in_progress(
|
|||||||
|
|
||||||
/* test bodies */
|
/* 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 )
|
static rtems_mode get_interrupt_level( void )
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -228,6 +245,7 @@ rtems_task Init(
|
|||||||
|
|
||||||
puts( "\n\n*** TEST 37 ***" );
|
puts( "\n\n*** TEST 37 ***" );
|
||||||
|
|
||||||
|
test_isr_locks();
|
||||||
test_interrupt_locks();
|
test_interrupt_locks();
|
||||||
|
|
||||||
build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
|
build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
|
||||||
|
|||||||
Reference in New Issue
Block a user