summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/posix/src/nanosleep.c2
-rw-r--r--cpukit/posix/src/sched_yield.c2
-rw-r--r--cpukit/rtems/src/taskwakeafter.c2
-rw-r--r--cpukit/sapi/src/interrtext.c3
-rw-r--r--cpukit/score/include/rtems/score/interr.h3
-rw-r--r--cpukit/score/include/rtems/score/threaddispatch.h14
-rw-r--r--cpukit/score/src/threaddispatch.c16
-rw-r--r--cpukit/score/src/threadrestart.c8
-rw-r--r--testsuites/sptests/Makefile.am1
-rw-r--r--testsuites/sptests/configure.ac1
-rw-r--r--testsuites/sptests/spfatal29/Makefile.am19
-rw-r--r--testsuites/sptests/spfatal29/spfatal29.doc11
-rw-r--r--testsuites/sptests/spfatal29/spfatal29.scn3
-rw-r--r--testsuites/sptests/spfatal29/testcase.h44
-rw-r--r--testsuites/sptests/spinternalerror02/init.c2
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
);
}