[PATCH] rtems: rtems_interrupt_enable/flash/disable()

Gedare Bloom gedare at gwu.edu
Fri Jun 12 13:56:24 UTC 2015


I'm not a huge fan of the name, although cute, I want to think some
more on an alternative, maybe Global Lock. What is the relationship of
The Big Hammer to the Giant Lock?

On Fri, Jun 12, 2015 at 4:31 AM, Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
> Use a global ticket lock on SMP configurations to ensure mutual
> exclusion across the system.
> ---
>  c/src/lib/libbsp/shared/bootcard.c      |  7 ++--
>  cpukit/rtems/Makefile.am                |  1 +
>  cpukit/rtems/include/rtems/rtems/intr.h | 48 +++++++++++++++++++++--
>  cpukit/rtems/src/intrbody.c             | 13 +++++++
>  cpukit/rtems/src/intrthebighammer.c     | 67 +++++++++++++++++++++++++++++++++
>  doc/user/intr.t                         |  7 +++-
>  testsuites/sptests/sp37/init.c          |  6 ---
>  7 files changed, 136 insertions(+), 13 deletions(-)
>  create mode 100644 cpukit/rtems/src/intrthebighammer.c
>
> diff --git a/c/src/lib/libbsp/shared/bootcard.c b/c/src/lib/libbsp/shared/bootcard.c
> index 4f91aa9..2a17c94 100644
> --- a/c/src/lib/libbsp/shared/bootcard.c
> +++ b/c/src/lib/libbsp/shared/bootcard.c
> @@ -66,13 +66,14 @@ void boot_card(
>    const char *cmdline
>  )
>  {
> -  rtems_interrupt_level  bsp_isr_level;
> +  ISR_Level bsp_isr_level;
>
>    /*
> -   *  Make sure interrupts are disabled.
> +   * Make sure interrupts are disabled.  Do not use rtems_interrupt_disable()
> +   * here, since on SMP configurations this is not a simple interrupt disable.
>     */
> +  _ISR_Disable_without_giant( bsp_isr_level );
>    (void) bsp_isr_level;
> -  rtems_interrupt_disable( bsp_isr_level );
>
>    bsp_boot_cmdline = cmdline;
>
> diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
> index f38990d..00bf53a 100644
> --- a/cpukit/rtems/Makefile.am
> +++ b/cpukit/rtems/Makefile.am
> @@ -136,6 +136,7 @@ librtems_a_SOURCES += src/ratemondata.c
>  ## INTR_C_FILES
>  librtems_a_SOURCES += src/intrbody.c
>  librtems_a_SOURCES += src/intrcatch.c
> +librtems_a_SOURCES += src/intrthebighammer.c
>
>  ## BARRIER_C_FILES
>  librtems_a_SOURCES += src/barrier.c
> diff --git a/cpukit/rtems/include/rtems/rtems/intr.h b/cpukit/rtems/include/rtems/rtems/intr.h
> index 259120f..0ad002b 100644
> --- a/cpukit/rtems/include/rtems/rtems/intr.h
> +++ b/cpukit/rtems/include/rtems/rtems/intr.h
> @@ -89,29 +89,71 @@ rtems_status_code rtems_interrupt_catch(
>  );
>  #endif
>
> +#if defined(RTEMS_SMP)
> +/*
> + * On SMP configurations replace the simple interrupt disable/enable with
> + * global recursive lock, also known as The Big Hammer.
> + */
> +
> +typedef struct {
> +  SMP_ticket_lock_Control Lock;
> +  SMP_lock_Stats_context Stats;
> +  Thread_Control *owner;
> +  uint32_t nest_level;
> +} The_big_hammer_Control;
> +
> +extern The_big_hammer_Control _The_big_hammer;
> +
> +rtems_interrupt_level _The_big_hammer_Acquire( void );
> +
> +void _The_big_hammer_Release( rtems_interrupt_level level );
> +#endif
> +
>  /**
>   *  @brief Disable RTEMS Interrupt
>   *
>   *  @note The interrupt level shall be of type @ref rtems_interrupt_level.
>   */
> +#if defined(RTEMS_SMP)
> +#define rtems_interrupt_disable( _isr_cookie ) \
> +  do { \
> +    _isr_cookie = _The_big_hammer_Acquire(); \
> +  } while ( 0 )
> +#else
>  #define rtems_interrupt_disable( _isr_cookie ) \
> -    _ISR_Disable(_isr_cookie)
> +  _ISR_Disable( _isr_cookie )
> +#endif
>
>  /**
>   *  @brief Enable RTEMS Interrupt
>   *
>   *  @note The interrupt level shall be of type @ref rtems_interrupt_level.
>   */
> +#if defined(RTEMS_SMP)
> +#define rtems_interrupt_enable( _isr_cookie ) \
> +  do { \
> +    _The_big_hammer_Release( _isr_cookie ); \
> +  } while ( 0 )
> +#else
>  #define rtems_interrupt_enable( _isr_cookie ) \
> -    _ISR_Enable(_isr_cookie)
> +  _ISR_Enable( _isr_cookie )
> +#endif
>
>  /**
>   *  @brief Flash RTEMS Interrupt
>   *
>   *  @note The interrupt level shall be of type @ref rtems_interrupt_level.
>   */
> +#if defined(RTEMS_SMP)
> +#define rtems_interrupt_flash( _isr_cookie ) \
> +  do { \
> +    rtems_interrupt_enable( _isr_cookie ); \
> +    rtems_interrupt_disable( _isr_cookie ); \
> +  } while ( 0 )
> +#else
>  #define rtems_interrupt_flash( _isr_cookie ) \
> -    _ISR_Flash(_isr_cookie)
> +  _ISR_Flash( _isr_cookie )
> +#endif
>
>  /**
>   *  @brief RTEMS Interrupt Is in Progress
> diff --git a/cpukit/rtems/src/intrbody.c b/cpukit/rtems/src/intrbody.c
> index 6b37eb2..9638d6c 100644
> --- a/cpukit/rtems/src/intrbody.c
> +++ b/cpukit/rtems/src/intrbody.c
> @@ -47,7 +47,11 @@ rtems_interrupt_level rtems_interrupt_disable( void )
>  {
>    rtems_interrupt_level previous_level;
>
> +#if defined(RTEMS_SMP)
> +  previous_level = _The_big_hammer_Acquire();
> +#else
>    _ISR_Disable( previous_level );
> +#endif
>
>    return previous_level;
>  }
> @@ -56,14 +60,23 @@ void rtems_interrupt_enable(
>    rtems_interrupt_level previous_level
>  )
>  {
> +#if defined(RTEMS_SMP)
> +  _The_big_hammer_Release( previous_level );
> +#else
>    _ISR_Enable( previous_level );
> +#endif
>  }
>
>  void rtems_interrupt_flash(
>    rtems_interrupt_level previous_level
>  )
>  {
> +#if defined(RTEMS_SMP)
> +  _The_big_hammer_Release( previous_level );
> +  _The_big_hammer_Acquire();
> +#else
>    _ISR_Flash( previous_level );
> +#endif
>  }
>
>  bool rtems_interrupt_is_in_progress( void )
> diff --git a/cpukit/rtems/src/intrthebighammer.c b/cpukit/rtems/src/intrthebighammer.c
> new file mode 100644
> index 0000000..37d8e88
> --- /dev/null
> +++ b/cpukit/rtems/src/intrthebighammer.c
> @@ -0,0 +1,67 @@
> +/**
> + * @file
> + *
> + * @ingroup ClassicINTR
> + *
> + * @brief The Big Hammer
> + */
> +
> +/*
> + * Copyright (c) 2015 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.org/license/LICENSE.
> + */
> +
> +#if HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/rtems/intr.h>
> +
> +#if defined(RTEMS_SMP)
> +The_big_hammer_Control _The_big_hammer = {
> +  .Lock = SMP_TICKET_LOCK_INITIALIZER( "The Big Hammer" )
> +};
> +
> +rtems_interrupt_level _The_big_hammer_Acquire( void )
> +{
> +  The_big_hammer_Control *hammer = &_The_big_hammer;
> +  Thread_Control         *executing;
> +  rtems_interrupt_level   previous_level;
> +
> +  _ISR_Disable_without_giant( previous_level );
> +
> +  executing = _Thread_Executing;
> +
> +  if ( hammer->owner != executing ) {
> +    _SMP_ticket_lock_Acquire( &hammer->Lock, &hammer->Stats );
> +    hammer->owner = executing;
> +    hammer->nest_level = 1;
> +  } else {
> +    ++hammer->nest_level;
> +  }
> +
> +  return previous_level;
> +}
> +
> +void _The_big_hammer_Release( rtems_interrupt_level previous_level )
> +{
> +  The_big_hammer_Control *hammer = &_The_big_hammer;
> +
> +  --hammer->nest_level;
> +  if ( hammer->nest_level == 0 ) {
> +    hammer->owner = NULL;
> +    _SMP_ticket_lock_Release( &hammer->Lock, &hammer->Stats );
> +  }
> +
> +  _ISR_Enable_without_giant( previous_level );
> +}
> +#endif
> diff --git a/doc/user/intr.t b/doc/user/intr.t
> index 6cb6a26..05049a7 100644
> --- a/doc/user/intr.t
> +++ b/doc/user/intr.t
> @@ -386,7 +386,12 @@ NONE
>  This directive disables all maskable interrupts and returns
>  the previous @code{level}.  A later invocation of the
>  @code{@value{DIRPREFIX}interrupt_enable} directive should be used to
> -restore the interrupt level.
> +restore the interrupt level.  On SMP configurations a global recursive lock is
> +acquired after the interrupt disable to ensure mutual exclusion across the
> +system.  This lock is released in the corresponding
> + at code{@value{DIRPREFIX}interrupt_enable} or
> + at code{@value{DIRPREFIX}interrupt_flash}.  The owner of the lock is the
> +executing task.
>
>  @subheading NOTES:
>
> diff --git a/testsuites/sptests/sp37/init.c b/testsuites/sptests/sp37/init.c
> index 647485e..77beb28 100644
> --- a/testsuites/sptests/sp37/init.c
> +++ b/testsuites/sptests/sp37/init.c
> @@ -306,19 +306,13 @@ void test_interrupt_inline(void)
>    }
>
>    puts( "interrupt disable (use inline)" );
> -  _Thread_Disable_dispatch();
>    rtems_interrupt_disable( level );
> -  _Thread_Enable_dispatch();
>
>    puts( "interrupt flash (use inline)" );
> -  _Thread_Disable_dispatch();
>    rtems_interrupt_flash( level );
> -  _Thread_Enable_dispatch();
>
>    puts( "interrupt enable (use inline)" );
> -  _Thread_Disable_dispatch();
>    rtems_interrupt_enable( level );
> -  _Thread_Enable_dispatch();
>
>    puts( "interrupt level mode (use inline)" );
>    level_mode_body = rtems_interrupt_level_body( level );
> --
> 1.8.4.5
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel


More information about the devel mailing list