[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