diff options
-rw-r--r-- | cpukit/posix/src/nanosleep.c | 2 | ||||
-rw-r--r-- | cpukit/posix/src/sched_yield.c | 2 | ||||
-rw-r--r-- | cpukit/rtems/src/taskwakeafter.c | 2 | ||||
-rw-r--r-- | cpukit/sapi/src/interrtext.c | 3 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/interr.h | 3 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threaddispatch.h | 14 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatch.c | 16 | ||||
-rw-r--r-- | cpukit/score/src/threadrestart.c | 8 | ||||
-rw-r--r-- | testsuites/sptests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/sptests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/sptests/spfatal29/Makefile.am | 19 | ||||
-rw-r--r-- | testsuites/sptests/spfatal29/spfatal29.doc | 11 | ||||
-rw-r--r-- | testsuites/sptests/spfatal29/spfatal29.scn | 3 | ||||
-rw-r--r-- | testsuites/sptests/spfatal29/testcase.h | 44 | ||||
-rw-r--r-- | testsuites/sptests/spinternalerror02/init.c | 2 |
15 files changed, 118 insertions, 13 deletions
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c index 38a6b8d6c8..0fec1e48e1 100644 --- a/cpukit/posix/src/nanosleep.c +++ b/cpukit/posix/src/nanosleep.c @@ -96,7 +96,7 @@ static inline int nanosleep_yield( struct timespec *rmtp ) executing = _Thread_Get_executing(); cpu_self = _Thread_Dispatch_disable(); _Thread_Yield( executing ); - _Thread_Dispatch_enable( cpu_self ); + _Thread_Dispatch_direct( cpu_self ); if ( rmtp ) { rmtp->tv_sec = 0; rmtp->tv_nsec = 0; diff --git a/cpukit/posix/src/sched_yield.c b/cpukit/posix/src/sched_yield.c index 7e056cef27..cbbcb34dd6 100644 --- a/cpukit/posix/src/sched_yield.c +++ b/cpukit/posix/src/sched_yield.c @@ -30,6 +30,6 @@ int sched_yield( void ) cpu_self = _Thread_Dispatch_disable(); _Thread_Yield( _Per_CPU_Get_executing( cpu_self ) ); - _Thread_Dispatch_enable( cpu_self ); + _Thread_Dispatch_direct( cpu_self ); return 0; } diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c index fa5f6f4eed..568b937388 100644 --- a/cpukit/rtems/src/taskwakeafter.c +++ b/cpukit/rtems/src/taskwakeafter.c @@ -48,6 +48,6 @@ rtems_status_code rtems_task_wake_after( ticks ); } - _Thread_Dispatch_enable( cpu_self ); + _Thread_Dispatch_direct( cpu_self ); return RTEMS_SUCCESSFUL; } diff --git a/cpukit/sapi/src/interrtext.c b/cpukit/sapi/src/interrtext.c index 665302283b..edf09dbd93 100644 --- a/cpukit/sapi/src/interrtext.c +++ b/cpukit/sapi/src/interrtext.c @@ -56,7 +56,8 @@ static const char *const internal_error_text[] = { "INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL", "INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL", "INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK", - "INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE" + "INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE", + "INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL" }; const char *rtems_internal_error_text( rtems_fatal_code error ) diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index dff61012d7..e23db5c58d 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -165,7 +165,8 @@ typedef enum { INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL, INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL, INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK, - INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE + INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE, + INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL } Internal_errors_Core_list; typedef CPU_Uint32ptr Internal_errors_t; diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h index 801970ab21..f4ca096783 100644 --- a/cpukit/score/include/rtems/score/threaddispatch.h +++ b/cpukit/score/include/rtems/score/threaddispatch.h @@ -95,6 +95,20 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) void _Thread_Dispatch( void ); /** + * @brief Directly do a thread dispatch. + * + * Must be called with a thread dispatch disable level of one, otherwise the + * INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL will occur. This function + * is useful for operations which synchronously block, e.g. self restart, self + * deletion, yield, sleep. + * + * @param[in] cpu_self The current processor. + * + * @see _Thread_Dispatch(). + */ +void _Thread_Dispatch_direct( Per_CPU_Control *cpu_self ); + +/** * @brief Performs a thread dispatch on the current processor. * * On entry the thread dispatch disable level must be equal to one and diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c index 36d2910ef2..c96299cb59 100644 --- a/cpukit/score/src/threaddispatch.c +++ b/cpukit/score/src/threaddispatch.c @@ -233,3 +233,19 @@ void _Thread_Dispatch( void ) _ISR_Local_enable( level ); } } + +void _Thread_Dispatch_direct( Per_CPU_Control *cpu_self ) +{ + ISR_Level level; + + if ( cpu_self->thread_dispatch_disable_level != 1 ) { + _Terminate( + INTERNAL_ERROR_CORE, + 0, + INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL + ); + } + + _ISR_Local_disable( level ); + _Thread_Do_dispatch( cpu_self, level ); +} diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 182cdb6128..a5ed837dfd 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -344,14 +344,8 @@ void _Thread_Life_action_handler( if ( _Thread_Is_life_terminating( previous_life_state ) ) { cpu_self = _Thread_Wait_for_join( executing, cpu_self ); - _Thread_Make_zombie( executing ); - - /* FIXME: Workaround for https://devel.rtems.org/ticket/2751 */ - cpu_self->dispatch_necessary = true; - - _Assert( cpu_self->heir != executing ); - _Thread_Dispatch_enable( cpu_self ); + _Thread_Dispatch_direct( cpu_self ); RTEMS_UNREACHABLE(); } diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 6e01eb2756..54a4de7f44 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -33,6 +33,7 @@ _SUBDIRS = \ spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \ spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \ sptask_err04 spclock_err01 +_SUBDIRS += spfatal29 _SUBDIRS += spmutex01 _SUBDIRS += spextensions01 _SUBDIRS += spsysinit01 diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index 2899b160c7..76d60e3b3c 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -193,6 +193,7 @@ spfatal20/Makefile spfatal24/Makefile spfatal25/Makefile spfatal27/Makefile +spfatal29/Makefile spfifo01/Makefile spfifo02/Makefile spfifo03/Makefile diff --git a/testsuites/sptests/spfatal29/Makefile.am b/testsuites/sptests/spfatal29/Makefile.am new file mode 100644 index 0000000000..23d37a9472 --- /dev/null +++ b/testsuites/sptests/spfatal29/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = spfatal29 +spfatal29_SOURCES = ../spfatal_support/init.c ../spfatal_support/system.h testcase.h + +dist_rtems_tests_DATA = spfatal29.scn spfatal29.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 = $(spfatal29_OBJECTS) +LINK_LIBS = $(spfatal29_LDLIBS) + +spfatal29$(EXEEXT): $(spfatal29_OBJECTS) $(spfatal29_DEPENDENCIES) + @rm -f spfatal29$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spfatal29/spfatal29.doc b/testsuites/sptests/spfatal29/spfatal29.doc new file mode 100644 index 0000000000..194e1f5082 --- /dev/null +++ b/testsuites/sptests/spfatal29/spfatal29.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: spfatal29 + +directives: + + - _Thread_Dispatch_force() + +concepts: + + - Provoke the INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL fatal error. diff --git a/testsuites/sptests/spfatal29/spfatal29.scn b/testsuites/sptests/spfatal29/spfatal29.scn new file mode 100644 index 0000000000..c640980d6e --- /dev/null +++ b/testsuites/sptests/spfatal29/spfatal29.scn @@ -0,0 +1,3 @@ +*** BEGIN OF TEST SPFATAL 29 *** +Fatal error (yield in interrupt context) hit +*** END OF TEST SPFATAL 29 *** diff --git a/testsuites/sptests/spfatal29/testcase.h b/testsuites/sptests/spfatal29/testcase.h new file mode 100644 index 0000000000..096a66ad03 --- /dev/null +++ b/testsuites/sptests/spfatal29/testcase.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@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. + */ + +#define FATAL_ERROR_TEST_NAME "29" +#define FATAL_ERROR_DESCRIPTION "yield in interrupt context" +#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_CORE +#define FATAL_ERROR_EXPECTED_IS_INTERNAL FALSE +#define FATAL_ERROR_EXPECTED_ERROR INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL + +#define CONFIGURE_MAXIMUM_TIMERS 1 + +static void timer(rtems_id id, void *arg) +{ + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); +} + +void force_error() +{ + rtems_status_code sc; + rtems_id id; + + sc = rtems_timer_create( + rtems_build_name('T', 'I', 'M', 'E'), + &id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_timer_fire_after(id, 1, timer, NULL); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_delete(RTEMS_SELF); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} diff --git a/testsuites/sptests/spinternalerror02/init.c b/testsuites/sptests/spinternalerror02/init.c index 3de5ef9483..af9d764271 100644 --- a/testsuites/sptests/spinternalerror02/init.c +++ b/testsuites/sptests/spinternalerror02/init.c @@ -36,7 +36,7 @@ static void test_internal_error_text(void) } while ( text != text_last ); rtems_test_assert( - error - 3 == INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE + error - 3 == INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL ); } |