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:
Sebastian Huber
2013-07-31 12:59:35 +02:00
parent f20275db90
commit 2d915cf389
5 changed files with 195 additions and 48 deletions

View File

@@ -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().
*/

View File

@@ -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

View 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 */

View File

@@ -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

View File

@@ -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 );