[rtems commit] score: Add and use ISR locks

Sebastian Huber sebh at rtems.org
Wed Jul 31 13:03:53 UTC 2013


Module:    rtems
Branch:    master
Commit:    2d915cf3895fb84a2bc2ab33adbcf8cdad6b62c6
Changeset: http://git.rtems.org/rtems/commit/?id=2d915cf3895fb84a2bc2ab33adbcf8cdad6b62c6

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Jul 31 12:59:35 2013 +0200

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.

---

 cpukit/rtems/include/rtems/rtems/intr.h    |   79 ++++++----------
 cpukit/score/Makefile.am                   |    1 +
 cpukit/score/include/rtems/score/isrlock.h |  141 ++++++++++++++++++++++++++++
 cpukit/score/preinstall.am                 |    4 +
 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 d687e46..ae6dfcc 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 67d4b5e..eb7376d 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 0000000..fb20a8e
--- /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 at 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 5d9cbed..aff76c9 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 0ae0b21..6f85c76 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 );




More information about the vc mailing list