From ba25cc208c5c83453a57cc42e402c55ac3ffe019 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 19 Feb 2014 11:21:34 +0100 Subject: score: Add and use _Giant_Drop() New test smptests/smpfatal03. --- cpukit/score/include/rtems/score/threaddispatch.h | 12 ++ cpukit/score/src/smp.c | 8 ++ cpukit/score/src/threaddispatchdisablelevel.c | 13 ++ testsuites/smptests/Makefile.am | 1 + testsuites/smptests/configure.ac | 1 + testsuites/smptests/smpfatal03/Makefile.am | 19 +++ testsuites/smptests/smpfatal03/init.c | 142 ++++++++++++++++++++++ testsuites/smptests/smpfatal03/smpfatal03.doc | 12 ++ testsuites/smptests/smpfatal03/smpfatal03.scn | 2 + 9 files changed, 210 insertions(+) create mode 100644 testsuites/smptests/smpfatal03/Makefile.am create mode 100644 testsuites/smptests/smpfatal03/init.c create mode 100644 testsuites/smptests/smpfatal03/smpfatal03.doc create mode 100644 testsuites/smptests/smpfatal03/smpfatal03.scn diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h index 2211662696..cf9b801af8 100644 --- a/cpukit/score/include/rtems/score/threaddispatch.h +++ b/cpukit/score/include/rtems/score/threaddispatch.h @@ -108,6 +108,18 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) */ void _Giant_Release( void ); + /** + * @brief Releases the giant lock completely if held by the executing processor. + * + * The thread dispatch disable level is not altered by this function. + * + * The only use case for this operation is in + * _SMP_Request_shutdown(). + * + * @param[in] self_cpu The current processor index. + */ + void _Giant_Drop( uint32_t self_cpu ); + /** * @brief Sets thread dispatch level to the value passed in. * diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c index 0f632236b7..e56073d281 100644 --- a/cpukit/score/src/smp.c +++ b/cpukit/score/src/smp.c @@ -73,6 +73,14 @@ void _SMP_Request_shutdown( void ) Per_CPU_Control *self_cpu = _Per_CPU_Get_by_index( self ); _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN ); + + /* + * We have to drop the Giant lock here in order to give other processors the + * opportunity to receive the inter-processor interrupts issued previously. + * In case the executing thread still holds SMP locks, then other processors + * already waiting for this SMP lock will spin forever. + */ + _Giant_Drop( self ); } void _SMP_Send_message( uint32_t cpu, uint32_t message ) diff --git a/cpukit/score/src/threaddispatchdisablelevel.c b/cpukit/score/src/threaddispatchdisablelevel.c index a3dec9998c..ec5ac813d5 100644 --- a/cpukit/score/src/threaddispatchdisablelevel.c +++ b/cpukit/score/src/threaddispatchdisablelevel.c @@ -57,6 +57,19 @@ static void _Giant_Do_release( void ) } } +void _Giant_Drop( uint32_t self_cpu ) +{ + Giant_Control *giant = &_Giant; + + _Assert( _ISR_Get_level() != 0 ); + + if ( giant->owner_cpu == self_cpu ) { + giant->nest_level = 0; + giant->owner_cpu = NO_OWNER_CPU; + _SMP_lock_Release( &giant->lock ); + } +} + uint32_t _Thread_Dispatch_increment_disable_level( void ) { ISR_Level isr_level; diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index 8422f3a7a4..b15bad5c16 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS += smp09 SUBDIRS += smpatomic01 SUBDIRS += smpfatal01 SUBDIRS += smpfatal02 +SUBDIRS += smpfatal03 SUBDIRS += smplock01 SUBDIRS += smpmigration01 SUBDIRS += smpschedule01 diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index 19e32f359f..95d082bc3e 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -67,6 +67,7 @@ smp09/Makefile smpatomic01/Makefile smpfatal01/Makefile smpfatal02/Makefile +smpfatal03/Makefile smplock01/Makefile smpmigration01/Makefile smppsxsignal01/Makefile diff --git a/testsuites/smptests/smpfatal03/Makefile.am b/testsuites/smptests/smpfatal03/Makefile.am new file mode 100644 index 0000000000..4ec2862357 --- /dev/null +++ b/testsuites/smptests/smpfatal03/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = smpfatal03 +smpfatal03_SOURCES = init.c + +dist_rtems_tests_DATA = smpfatal03.scn smpfatal03.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(smpfatal03_OBJECTS) +LINK_LIBS = $(smpfatal03_LDLIBS) + +smpfatal03$(EXEEXT): $(smpfatal03_OBJECTS) $(smpfatal03_DEPENDENCIES) + @rm -f smpfatal03$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smpfatal03/init.c b/testsuites/smptests/smpfatal03/init.c new file mode 100644 index 0000000000..3e5ebe2e8f --- /dev/null +++ b/testsuites/smptests/smpfatal03/init.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#define CPU_COUNT 2 + +static uint32_t main_cpu; + +static SMP_barrier_Control barrier = SMP_BARRIER_CONTROL_INITIALIZER; + +static void end_of_test(void) +{ + printk( "*** END OF TEST SMPFATAL 3 ***\n" ); +} + +static void acquire_giant_and_fatal_task(rtems_task_argument arg) +{ + SMP_barrier_State state = SMP_BARRIER_STATE_INITIALIZER; + int i; + + for (i = 0; i < 13; ++i) { + _Giant_Acquire(); + } + + _SMP_barrier_Wait(&barrier, &state, CPU_COUNT); + + /* + * Now we have to wait some time so that the other thread can actually start + * with the _Giant_Acquire() procedure. + */ + rtems_counter_delay_nanoseconds(1000000); + + rtems_fatal(RTEMS_FATAL_SOURCE_APPLICATION, 0xdeadbeef); +} + +static void wait_for_giant(void) +{ + SMP_barrier_State state = SMP_BARRIER_STATE_INITIALIZER; + + _SMP_barrier_Wait(&barrier, &state, CPU_COUNT); + + _Giant_Acquire(); +} + +static void Init(rtems_task_argument arg) +{ + uint32_t self = rtems_smp_get_current_processor(); + uint32_t cpu_count = rtems_smp_get_processor_count(); + + printk("\n\n*** TEST SMPFATAL 3 ***\n"); + + main_cpu = self; + + if (cpu_count >= CPU_COUNT) { + rtems_status_code sc; + rtems_id id; + + sc = rtems_task_create( + rtems_build_name( 'W', 'A', 'I', 'T' ), + 1, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, acquire_giant_and_fatal_task, 0); + assert(sc == RTEMS_SUCCESSFUL); + + wait_for_giant(); + } else { + end_of_test(); + exit(0); + } +} + +static void fatal_extension( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if ( + source == RTEMS_FATAL_SOURCE_APPLICATION + || source == RTEMS_FATAL_SOURCE_SMP + ) { + uint32_t self = rtems_smp_get_current_processor(); + + assert(!is_internal); + + if (self == main_cpu) { + assert(source == RTEMS_FATAL_SOURCE_SMP); + assert(code == SMP_FATAL_SHUTDOWN); + + end_of_test(); + } else { + assert(source == RTEMS_FATAL_SOURCE_APPLICATION); + assert(code == 0xdeadbeef); + } + } +} + +#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_INITIAL_EXTENSIONS { .fatal = fatal_extension } + +#define CONFIGURE_SMP_APPLICATION + +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT + +#define CONFIGURE_MAXIMUM_TASKS 2 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/smptests/smpfatal03/smpfatal03.doc b/testsuites/smptests/smpfatal03/smpfatal03.doc new file mode 100644 index 0000000000..5c5a8bae77 --- /dev/null +++ b/testsuites/smptests/smpfatal03/smpfatal03.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smpfatal03 + +directives: + + - _Terminate() + +concepts: + + - Ensure that _Terminate() drops the Giant lock so that other processors + waiting on the Giant lock can receive shutdown requests. diff --git a/testsuites/smptests/smpfatal03/smpfatal03.scn b/testsuites/smptests/smpfatal03/smpfatal03.scn new file mode 100644 index 0000000000..f502b4e816 --- /dev/null +++ b/testsuites/smptests/smpfatal03/smpfatal03.scn @@ -0,0 +1,2 @@ +*** TEST SMPFATAL 3 *** +*** END OF TEST SMPFATAL 3 *** -- cgit v1.2.3