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.hu...@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 > + * <rt...@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 > +@code{@value{DIRPREFIX}interrupt_enable} or > +@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@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel