[rtems commit] rtems: Add interrupt locks

Sebastian Huber sebh at rtems.org
Wed Jun 12 14:08:10 UTC 2013


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Jun 10 11:14:35 2013 +0200

rtems: Add interrupt locks

Interrupt locks are low-level lock to protect critical sections accessed
by threads and interrupt service routines.

---

 cpukit/rtems/include/rtems/rtems/intr.h |  135 ++++++++++++++++++++++++
 doc/user/intr.t                         |  170 +++++++++++++++++++++++++++++++
 testsuites/sptests/sp37/init.c          |   17 +++
 3 files changed, 322 insertions(+), 0 deletions(-)

diff --git a/cpukit/rtems/include/rtems/rtems/intr.h b/cpukit/rtems/include/rtems/rtems/intr.h
index ea6dc6b..d687e46 100644
--- a/cpukit/rtems/include/rtems/rtems/intr.h
+++ b/cpukit/rtems/include/rtems/rtems/intr.h
@@ -26,6 +26,7 @@ extern "C" {
 #endif
 
 #include <rtems/score/isr.h>
+#include <rtems/score/smplock.h>
 
 /**
  *  @defgroup ClassicINTR Interrupts
@@ -134,6 +135,140 @@ rtems_status_code rtems_interrupt_catch(
  */
 #define rtems_interrupt_clear( _interrupt_to_clear )
 
+/**
+ * @defgroup ClassicINTRLocks Interrupt Locks
+ *
+ * @ingroup ClassicINTR
+ *
+ * @brief Low-level lock to protect critical sections accessed by threads and
+ * interrupt service routines.
+ *
+ * This synchronization primitive is supported on SMP configurations.
+ *
+ * @{
+ */
+
+/**
+ * @brief Interrupt lock control.
+ */
+typedef struct {
+  #if defined( RTEMS_SMP )
+    SMP_lock_Control lock;
+  #endif
+} 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
+
+/**
+ * @brief Initializes an interrupt lock.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ */
+#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
+
+/**
+ * @brief Acquires an interrupt lock.
+ *
+ * Interrupts will be disabled.  On SMP configurations this function acquires a
+ * SMP lock.
+ *
+ * This function can be used in thread and interrupt context.
+ *
+ * @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
+
+/**
+ * @brief Releases an interrupt lock.
+ *
+ * The interrupt status will be restored.  On SMP configurations this function
+ * releases a SMP lock.
+ *
+ * This function can be used in thread and interrupt context.
+ *
+ * @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
+
+/**
+ * @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.
+ *
+ * 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.
+ *
+ * @see rtems_interrupt_lock_release_isr().
+ */
+#if defined( RTEMS_SMP )
+  #define rtems_interrupt_lock_acquire_isr( _lock ) \
+    _SMP_lock_Acquire( &( _lock )->lock )
+#else
+  #define rtems_interrupt_lock_acquire_isr( _lock ) \
+    do { \
+      (void) _lock; \
+    } while (0)
+#endif
+
+/**
+ * @brief Releases an interrupt lock in the corresponding interrupt service
+ * routine.
+ *
+ * The interrupt status will remain unchanged.  On SMP configurations this
+ * function releases a SMP lock.
+ *
+ * @see rtems_interrupt_lock_acquire_isr().
+ */
+#if defined( RTEMS_SMP )
+  #define rtems_interrupt_lock_release_isr( _lock ) \
+    _SMP_lock_Release( &( _lock )->lock )
+#else
+  #define rtems_interrupt_lock_release_isr( _lock ) \
+    do { \
+      (void) _lock; \
+    } while (0)
+#endif
+
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/doc/user/intr.t b/doc/user/intr.t
index dd5c9c8..b6a58dc 100644
--- a/doc/user/intr.t
+++ b/doc/user/intr.t
@@ -21,6 +21,11 @@ directive:
 @item @code{@value{DIRPREFIX}interrupt_disable} - Disable Interrupts
 @item @code{@value{DIRPREFIX}interrupt_enable} - Enable Interrupts
 @item @code{@value{DIRPREFIX}interrupt_flash} - Flash Interrupt
+ at item @code{@value{DIRPREFIX}interrupt_lock_initialize} - Initialize an ISR Lock
+ at item @code{@value{DIRPREFIX}interrupt_lock_acquire} - Acquire an ISR Lock
+ at item @code{@value{DIRPREFIX}interrupt_lock_release} - Release an ISR Lock
+ at item @code{@value{DIRPREFIX}interrupt_lock_acquire_isr} - Acquire an ISR Lock from ISR
+ at item @code{@value{DIRPREFIX}interrupt_lock_release_isr} - Release an ISR Lock from ISR
 @item @code{@value{DIRPREFIX}interrupt_is_in_progress} - Is an ISR in Progress
 @end itemize
 
@@ -194,6 +199,10 @@ implementation error to use RTEMS_SELF from an ISR.
 @item rtems_interrupt_enable
 @item rtems_interrupt_disable
 @item rtems_interrupt_flash
+ at item rtems_interrupt_lock_acquire
+ at item rtems_interrupt_lock_release
+ at item rtems_interrupt_lock_acquire_isr
+ at item rtems_interrupt_lock_release_isr
 @item rtems_interrupt_is_in_progress
 @item rtems_interrupt_catch
 @end itemize
@@ -457,6 +466,167 @@ This directive will not cause the calling task to be preempted.
 @c
 @c
 @page
+ at subsection INTERRUPT_LOCK_INITIALIZE - Initialize an ISR Lock
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C 
+ at findex rtems_interrupt_lock_initialize
+ at example
+void rtems_interrupt_lock_initialize(
+  rtems_interrupt_lock *lock
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+NONE
+
+ at subheading DESCRIPTION:
+
+Initializes an interrupt lock.
+
+ at subheading NOTES:
+
+Concurrent initialization leads to unpredictable results.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection INTERRUPT_LOCK_ACQUIRE - Acquire an ISR Lock
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C 
+ at findex rtems_interrupt_lock_acquire
+ at example
+void rtems_interrupt_lock_acquire(
+  rtems_interrupt_lock *lock,
+  rtems_interrupt_level level
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+NONE
+
+ at subheading DESCRIPTION:
+
+Interrupts will be disabled.  On SMP configurations this directive acquires a
+SMP lock.
+
+ at subheading NOTES:
+
+This directive will not cause the calling thread to be preempted.  This
+directive can be used in thread and interrupt context.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection INTERRUPT_LOCK_RELEASE - Release an ISR Lock
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C 
+ at findex rtems_interrupt_lock_release
+ at example
+void rtems_interrupt_lock_release(
+  rtems_interrupt_lock *lock,
+  rtems_interrupt_level level
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+NONE
+
+ at subheading DESCRIPTION:
+
+The interrupt status will be restored.  On SMP configurations this directive
+releases a SMP lock.
+
+ at subheading NOTES:
+
+This directive will not cause the calling thread to be preempted.  This
+directive can be used in thread and interrupt context.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection INTERRUPT_LOCK_ACQUIRE_ISR - Acquire an ISR Lock from ISR
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C 
+ at findex rtems_interrupt_lock_acquire_isr
+ at example
+void rtems_interrupt_lock_acquire_isr(
+  rtems_interrupt_lock *lock,
+  rtems_interrupt_level level
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+NONE
+
+ at subheading DESCRIPTION:
+
+The interrupt status will remain unchanged.  On SMP configurations this
+directive acquires a 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.
+
+ at subheading NOTES:
+
+This directive should be called from the corresponding interrupt service
+routine.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection INTERRUPT_LOCK_RELEASE_ISR - Release an ISR Lock from ISR
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C 
+ at findex rtems_interrupt_lock_release_isr
+ at example
+void rtems_interrupt_lock_release_isr(
+  rtems_interrupt_lock *lock,
+  rtems_interrupt_level level
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+NONE
+
+ at subheading DESCRIPTION:
+
+The interrupt status will remain unchanged.  On SMP configurations this
+directive releases a SMP lock.
+
+ at subheading NOTES:
+
+This directive should be called from the corresponding interrupt service
+routine.
+
+ at c
+ at c
+ at c
+ at page
 @subsection INTERRUPT_IS_IN_PROGRESS - Is an ISR in Progress
 
 @cindex is interrupt in progress
diff --git a/testsuites/sptests/sp37/init.c b/testsuites/sptests/sp37/init.c
index 870316a..956c91d 100644
--- a/testsuites/sptests/sp37/init.c
+++ b/testsuites/sptests/sp37/init.c
@@ -43,6 +43,21 @@ rtems_timer_service_routine test_isr_in_progress(
 );
 
 /* test bodies */
+
+static void test_interrupt_locks( void )
+{
+  rtems_interrupt_lock lock = RTEMS_INTERRUPT_LOCK_INITIALIZER;
+  rtems_interrupt_level level;
+
+  rtems_interrupt_lock_initialize( &lock );
+
+  rtems_interrupt_lock_acquire( &lock, level );
+  rtems_interrupt_lock_release( &lock, level );
+
+  rtems_interrupt_lock_acquire_isr( &lock );
+  rtems_interrupt_lock_release_isr( &lock );
+}
+
 void test_interrupt_inline(void)
 {
   rtems_interrupt_level level;
@@ -318,6 +333,8 @@ rtems_task Init(
 
   check_isr_worked( "body", isr_in_progress_body );
 
+  test_interrupt_locks();
+
   puts( "*** END OF TEST 37 ***" );
   rtems_test_exit( 0 );
 }




More information about the vc mailing list