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
|
||||
|
||||
#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().
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user