[PATCH 13/13] config: Add CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Sep 30 09:21:36 UTC 2022


By default, the IDLE task storage areas are statically allocated.  The size of
the task storage area is defined by the CONFIGURE_IDLE_TASK_STACK_SIZE
configuration option.  The task storage area contains the task stack, the
thread-local storage, and the floating-point context on architectures with a
separate floating-point context.  The size of the thread-local storage area is
defined at link time or by the CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE
configuration option.  The new CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
configuration option is used to ensure that the IDLE task stack size has at
least the configured minimum size.  If the IDLE task stack size is too small,
for example because the thread-local storage size is too large, then the system
terminates with the INTERNAL_ERROR_CORE fatal source and the
INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL fatal code during system
initialization.

Update #3835.
---
 cpukit/doxygen/appl-config.h                  | 120 +++++++++++--
 cpukit/include/rtems/confdefs/percpu.h        |  10 ++
 cpukit/include/rtems/score/interr.h           |   3 +-
 cpukit/include/rtems/score/threadidledata.h   |   8 +
 cpukit/sapi/src/interrtext.c                  |   3 +-
 cpukit/score/src/threadcreateidle.c           |  24 ++-
 .../fatal-idle-thread-stack-too-small.yml     |  20 +++
 spec/build/testsuites/validation/grp.yml      |   2 +
 testsuites/libtests/stackchk01/init.c         |  30 +++-
 testsuites/libtests/stackchk01/stackchk01.doc |  12 +-
 testsuites/samples/minimum/init.c             |   3 +
 testsuites/sptests/spinternalerror02/init.c   |   2 +-
 testsuites/validation/tc-acfg-default.c       |  51 +++---
 .../tr-fatal-idle-thread-stack-too-small.c    | 169 ++++++++++++++++++
 .../tr-fatal-idle-thread-stack-too-small.h    |  84 +++++++++
 .../ts-fatal-idle-thread-stack-too-small.c    |  99 ++++++++++
 16 files changed, 589 insertions(+), 51 deletions(-)
 create mode 100644 spec/build/testsuites/validation/fatal-idle-thread-stack-too-small.yml
 create mode 100644 testsuites/validation/tr-fatal-idle-thread-stack-too-small.c
 create mode 100644 testsuites/validation/tr-fatal-idle-thread-stack-too-small.h
 create mode 100644 testsuites/validation/ts-fatal-idle-thread-stack-too-small.c

diff --git a/cpukit/doxygen/appl-config.h b/cpukit/doxygen/appl-config.h
index ee647dc961..7564bc4462 100644
--- a/cpukit/doxygen/appl-config.h
+++ b/cpukit/doxygen/appl-config.h
@@ -3400,13 +3400,66 @@
  */
 #define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
 
+/* Generated from spec:/acfg/if/idle-task-min-stack-size */
+
+/**
+ * @brief This configuration option is an integer define.
+ *
+ * The value of this configuration option defines the minimum stack size in
+ * bytes for every IDLE task in the system.
+ *
+ * @par Default Value
+ * #CPU_STACK_MINIMUM_SIZE / 4
+ *
+ * @par Value Constraints
+ * @parblock
+ * The value of the configuration option shall be large enough so that
+ *
+ * * the thread handler can call the thread switch extensions for the IDLE
+ *   task,
+ *
+ * * the thread handler can call the thread begin extensions for the IDLE task,
+ *
+ * * the thread handler can call the IDLE task body (see
+ *   #CONFIGURE_IDLE_TASK_BODY), and
+ *
+ * * the IDLE task can be interrupted by interrupt services.
+ * @endparblock
+ *
+ * @par Notes
+ * @parblock
+ * Adjusting this parameter should be done with caution.  Examining the actual
+ * stack usage using the stack checker usage reporting facility is recommended
+ * (see also #CONFIGURE_STACK_CHECKER_ENABLED).
+ *
+ * This parameter can be used to increase the minimum from that recommended.
+ * This can be used in higher memory systems to reduce the risk of stack
+ * overflow without performing analysis on actual consumption.
+ *
+ * By default, the IDLE task storage areas are statically allocated.  The size
+ * of the task storage area is defined by the #CONFIGURE_IDLE_TASK_STACK_SIZE
+ * configuration option.  The task storage area contains the task stack, the
+ * thread-local storage, and the floating-point context on architectures with a
+ * separate floating-point context.  The size of the thread-local storage area
+ * is defined at link time or by the
+ * #CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE configuration option.  This
+ * configuration option is used to ensure that the IDLE task stack size has at
+ * least the configured minimum size.  If the IDLE task stack size is too
+ * small, for example because the thread-local storage size is too large, then
+ * the system terminates with the INTERNAL_ERROR_CORE fatal source and the
+ * INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL fatal code during system
+ * initialization.
+ * @endparblock
+ */
+#define CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
+
 /* Generated from spec:/acfg/if/idle-task-stack-size */
 
 /**
  * @brief This configuration option is an integer define.
  *
- * The value of this configuration option defines the task stack size for an
- * IDLE task.
+ * The value of this configuration option defines the task storage area size
+ * for an IDLE task.
  *
  * @par Default Value
  * The default value is #CONFIGURE_MINIMUM_TASK_STACK_SIZE.
@@ -3425,8 +3478,27 @@
  * @endparblock
  *
  * @par Notes
- * In SMP configurations, there is one IDLE task per configured processor, see
- * #CONFIGURE_MAXIMUM_PROCESSORS.
+ * @parblock
+ * Where the system was built with SMP support enabled, there is one IDLE task
+ * for each configured processor, see #CONFIGURE_MAXIMUM_PROCESSORS.
+ *
+ * By default, the IDLE task storage areas are statically allocated.  The size
+ * of the task storage area for each IDLE task is defined by this configuration
+ * option.  The task storage area contains the task stack, the thread-local
+ * storage, and the floating-point context on architectures with a separate
+ * floating-point context.  The size of the thread-local storage area is
+ * defined at link time or by the #CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE
+ * configuration option.  The #CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
+ * configuration option is used to ensure that the IDLE task stack size has at
+ * least the configured minimum size.  If the IDLE task stack size is too
+ * small, for example because the thread-local storage size is too large, then
+ * the system terminates with the INTERNAL_ERROR_CORE fatal source and the
+ * INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL fatal code during system
+ * initialization.
+ *
+ * You can use the #CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE configuration
+ * option to change the task stack allocator for IDLE tasks.
+ * @endparblock
  */
 #define CONFIGURE_IDLE_TASK_STACK_SIZE
 
@@ -4829,31 +4901,51 @@
  * task.
  *
  * @par Default Value
- * The default value is ``_Stack_Allocator_allocate_for_idle_default``, which
- * indicates that IDLE task stacks will be allocated from an area statically
+ * By default, the IDLE task stacks will be allocated from an area statically
  * allocated by ``<rtems/confdefs.h>``.
  *
  * @par Value Constraints
- * The value of this configuration option shall be defined to a valid function
- * pointer of the type ``void *( *allocate )( uint32_t, size_t * )``.
+ * @parblock
+ * The following constraints apply to this configuration option:
+ *
+ * * The value of the configuration option shall be defined to a valid function
+ *   pointer of the type ``void *( *allocate )( uint32_t, size_t * )``.
+ *
+ * * The IDLE task stack allocator shall return a pointer to the allocated
+ *   memory area or terminate the system with a fatal error if the allocation
+ *   request cannot be satisfied.
+ *
+ * * The IDLE task stack allocator may increase the size of the allocated
+ *   memory area.
+ * @endparblock
  *
  * @par Notes
+ * @parblock
  * This configuration option is independent of the other thread stack allocator
  * configuration options.  It is assumed that any memory allocated for the
  * stack of an IDLE task will not be from the RTEMS Workspace or the memory
  * statically allocated by default.
  *
+ * The IDLE task stack allocator may increase the size of the allocated memory
+ * area to account for the actual thread-local storage size which is defined at
+ * link time.
+ *
+ * The size of the statically allocated memory area used by the default
+ * allocator is defined by the #CONFIGURE_IDLE_TASK_STACK_SIZE configuration
+ * option.  The #CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE configuration option
+ * ensures that the IDLE task stack size has at least the configured minimum
+ * size.
+ *
  * For applications with a thread-local storage size which is completely
  * unknown at the time the application configuration is defined, RTEMS provides
  * an IDLE task stack allocator which uses rtems_malloc().  The size of the
  * allocated thread storage area is the sum of stack size defined by the
  * #CONFIGURE_IDLE_TASK_STACK_SIZE configuration option and the actual
- * thread-local storage size of the application.  Define this configuration
- * option to ``rtems_malloc_task_stack_for_idle`` to use this allocator.  If
- * the memory allocation fails, then the system terminates with the
- * INTERNAL_ERROR_CORE fatal source and the
- * INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STACK fatal code during system
- * initialization.
+ * thread-local storage size of the application.  If the memory allocation
+ * fails, then the system terminates with the INTERNAL_ERROR_CORE fatal source
+ * and the INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STACK fatal code during
+ * system initialization.  Define this configuration option to
+ * ``rtems_malloc_task_stack_for_idle`` to use this allocator.
  * @endparblock
  */
 #define CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
diff --git a/cpukit/include/rtems/confdefs/percpu.h b/cpukit/include/rtems/confdefs/percpu.h
index b91590bfd9..c08e388cfa 100644
--- a/cpukit/include/rtems/confdefs/percpu.h
+++ b/cpukit/include/rtems/confdefs/percpu.h
@@ -130,12 +130,22 @@ RTEMS_DEFINE_GLOBAL_SYMBOL(
   #endif
 #endif
 
+#ifndef CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
+  #define CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE ( CPU_STACK_MINIMUM_SIZE / 4 )
+#endif
+
 #if CONFIGURE_IDLE_TASK_STACK_SIZE < CONFIGURE_MINIMUM_TASK_STACK_SIZE
   #error "CONFIGURE_IDLE_TASK_STACK_SIZE less than CONFIGURE_MINIMUM_TASK_STACK_SIZE"
 #endif
 
+#if CONFIGURE_IDLE_TASK_STACK_SIZE < CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
+  #error "CONFIGURE_IDLE_TASK_STACK_SIZE less than CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE"
+#endif
+
 const size_t _Thread_Idle_stack_size = CONFIGURE_IDLE_TASK_STACK_SIZE;
 
+const size_t _Thread_Idle_minimum_stack_size = CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE;
+
 /*
  * If the user provides a custom idle stack allocator, then we do not need
  * memory reserved for the stacks but the symbol is still referenced in
diff --git a/cpukit/include/rtems/score/interr.h b/cpukit/include/rtems/score/interr.h
index 1eeb93cc6e..0c789c3bd7 100644
--- a/cpukit/include/rtems/score/interr.h
+++ b/cpukit/include/rtems/score/interr.h
@@ -230,7 +230,8 @@ typedef enum {
   INTERNAL_ERROR_TOO_LARGE_TLS_SIZE = 41,
   INTERNAL_ERROR_RTEMS_INIT_TASK_CONSTRUCT_FAILED = 42,
   INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STACK = 43,
-  INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED = 44
+  INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED = 44,
+  INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL = 45
 } Internal_errors_Core_list;
 
 typedef CPU_Uint32ptr Internal_errors_t;
diff --git a/cpukit/include/rtems/score/threadidledata.h b/cpukit/include/rtems/score/threadidledata.h
index 4f2a785ccd..1ee420b197 100644
--- a/cpukit/include/rtems/score/threadidledata.h
+++ b/cpukit/include/rtems/score/threadidledata.h
@@ -58,6 +58,14 @@ extern "C" {
  */
 extern const size_t _Thread_Idle_stack_size;
 
+/**
+ * @brief The idle thread minimum stack size in bytes.
+ *
+ * This constant is defined by the application configuration via
+ * <rtems/confdefs.h>.
+ */
+extern const size_t _Thread_Idle_minimum_stack_size;
+
 /**
  * @brief The idle thread body type.
  */
diff --git a/cpukit/sapi/src/interrtext.c b/cpukit/sapi/src/interrtext.c
index 85ccf13201..e229995fc6 100644
--- a/cpukit/sapi/src/interrtext.c
+++ b/cpukit/sapi/src/interrtext.c
@@ -85,7 +85,8 @@ static const char *const internal_error_text[] = {
   "INTERNAL_ERROR_TOO_LARGE_TLS_SIZE",
   "INTERNAL_ERROR_RTEMS_INIT_TASK_CONSTRUCT_FAILED",
   "INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STACK",
-  "INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED"
+  "INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED",
+  "INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL"
 };
 
 const char *rtems_internal_error_text( rtems_fatal_code error )
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index d2037b36f0..dcc8f5cc6c 100644
--- a/cpukit/score/src/threadcreateidle.c
+++ b/cpukit/score/src/threadcreateidle.c
@@ -53,7 +53,10 @@
 
 #include <string.h>
 
-static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
+static void _Thread_Create_idle_for_CPU(
+  Per_CPU_Control *cpu,
+  uintptr_t        minimum_stack_size
+)
 {
   Thread_Configuration  config;
   Thread_Control       *idle;
@@ -82,6 +85,10 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
     &config.stack_size
   );
 
+  if ( config.stack_size < minimum_stack_size ) {
+    _Internal_error( INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL );
+  }
+
   /*
    *  The entire workspace is zeroed during its initialization.  Thus, all
    *  fields not explicitly assigned were explicitly zeroed by
@@ -118,21 +125,28 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
 
 void _Thread_Create_idle( void )
 {
+  uintptr_t minimum_stack_size;
 #if defined(RTEMS_SMP)
-  uint32_t cpu_max;
-  uint32_t cpu_index;
+  uint32_t  cpu_max;
+  uint32_t  cpu_index;
+#endif
 
+  minimum_stack_size = _TLS_Get_allocation_size() +
+    CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE +
+    _Thread_Idle_minimum_stack_size;
+
+#if defined(RTEMS_SMP)
   cpu_max = _SMP_Get_processor_maximum();
 
   for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
     Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
 
     if ( _Per_CPU_Is_processor_online( cpu ) ) {
-      _Thread_Create_idle_for_CPU( cpu );
+      _Thread_Create_idle_for_CPU( cpu, minimum_stack_size );
     }
   }
 #else
-  _Thread_Create_idle_for_CPU( _Per_CPU_Get() );
+  _Thread_Create_idle_for_CPU( _Per_CPU_Get(), minimum_stack_size );
 #endif
 
   _CPU_Use_thread_local_storage(
diff --git a/spec/build/testsuites/validation/fatal-idle-thread-stack-too-small.yml b/spec/build/testsuites/validation/fatal-idle-thread-stack-too-small.yml
new file mode 100644
index 0000000000..11be4d7a8d
--- /dev/null
+++ b/spec/build/testsuites/validation/fatal-idle-thread-stack-too-small.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/validation/tr-fatal-idle-thread-stack-too-small.c
+- testsuites/validation/ts-fatal-idle-thread-stack-too-small.c
+stlib: []
+target: testsuites/validation/ts-fatal-idle-thread-stack-too-small.exe
+type: build
+use-after: []
+use-before: []
diff --git a/spec/build/testsuites/validation/grp.yml b/spec/build/testsuites/validation/grp.yml
index 7a5fbb1c90..42e546636b 100644
--- a/spec/build/testsuites/validation/grp.yml
+++ b/spec/build/testsuites/validation/grp.yml
@@ -19,6 +19,8 @@ links:
   uid: fatal-boot-processor-not-assigned-to-scheduler
 - role: build-dependency
   uid: fatal-idle-thread-create-failed
+- role: build-dependency
+  uid: fatal-idle-thread-stack-too-small
 - role: build-dependency
   uid: fatal-init-task-construct-failed
 - role: build-dependency
diff --git a/testsuites/libtests/stackchk01/init.c b/testsuites/libtests/stackchk01/init.c
index 9e58409b17..b87b6baa2d 100644
--- a/testsuites/libtests/stackchk01/init.c
+++ b/testsuites/libtests/stackchk01/init.c
@@ -35,14 +35,18 @@
 
 const char rtems_test_name[] = "STACKCHK 1";
 
-/* forward declarations to avoid warnings */
-rtems_task Init(rtems_task_argument argument);
+static void stack_visitor( const rtems_stack_checker_info *info, void *arg )
+{
+  if ( rtems_object_id_get_api( info->id ) == 1 ) {
+    *(uintptr_t *) arg = info->used;
+  }
+}
 
-rtems_task Init(
-  rtems_task_argument argument
-)
+static rtems_task Init( rtems_task_argument argument )
 {
-  bool              blown;
+  bool      blown;
+  uintptr_t used;
+  uintptr_t limit;
 
   TEST_BEGIN();
 
@@ -50,14 +54,26 @@ rtems_task Init(
   blown = rtems_stack_checker_is_blown();
   rtems_test_assert(!blown);
 
+  rtems_task_wake_after( 2 );
+  used = 0;
+  rtems_stack_checker_iterate( stack_visitor, &used );
+  limit = CPU_STACK_MINIMUM_SIZE / 4;
+  printf(
+    "check used IDLE stack size: 0 < %" PRIuPTR " <= %" PRIuPTR "\n",
+    used,
+    limit
+  );
+  rtems_test_assert( used > 0 );
+  rtems_test_assert( used <= limit );
+
   TEST_END();
   rtems_test_exit(0);
 }
 
 /* configuration information */
 
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
-#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
 
 #define CONFIGURE_MAXIMUM_TASKS 1
 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
diff --git a/testsuites/libtests/stackchk01/stackchk01.doc b/testsuites/libtests/stackchk01/stackchk01.doc
index 5b3d9c894b..dffcc487c9 100644
--- a/testsuites/libtests/stackchk01/stackchk01.doc
+++ b/testsuites/libtests/stackchk01/stackchk01.doc
@@ -30,9 +30,17 @@ This file describes the directives and concepts tested by this test set.
 test set name:  stackchk01
 
 directives:
-  rtems_stack_checker_is_blown
+
+* CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE
+
+* rtems_stack_checker_is_blown
+
+* rtems_stack_checker_iterate
 
 concepts:
 
-+ ensure that dynamic checks for a blown stack work both when the stack
+* Ensure that dynamic checks for a blown stack work both when the stack
   is not blown and when it is.
+
+* Ensure that the default value of CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE is
+  sufficient.
diff --git a/testsuites/samples/minimum/init.c b/testsuites/samples/minimum/init.c
index ee14a1aef4..b39bb49a1a 100644
--- a/testsuites/samples/minimum/init.c
+++ b/testsuites/samples/minimum/init.c
@@ -88,6 +88,9 @@ static void *Init( uintptr_t ignored )
 #define CONFIGURE_MINIMUM_TASK_STACK_SIZE 512
 #endif
 
+#define CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE \
+  (CONFIGURE_MINIMUM_TASK_STACK_SIZE - CPU_STACK_ALIGNMENT)
+
 /*
  * Keep the interrupt/initialization stack as is.  Otherwise, the test may fail
  * in the low level system initialization.
diff --git a/testsuites/sptests/spinternalerror02/init.c b/testsuites/sptests/spinternalerror02/init.c
index f94759a99b..2d2f080d25 100644
--- a/testsuites/sptests/spinternalerror02/init.c
+++ b/testsuites/sptests/spinternalerror02/init.c
@@ -49,7 +49,7 @@ static void test_internal_error_text(void)
   } while ( text != text_last );
 
   rtems_test_assert(
-    error - 3 == INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED
+    error - 3 == INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL
   );
 }
 
diff --git a/testsuites/validation/tc-acfg-default.c b/testsuites/validation/tc-acfg-default.c
index 95fa497cf1..0c65995128 100644
--- a/testsuites/validation/tc-acfg-default.c
+++ b/testsuites/validation/tc-acfg-default.c
@@ -74,10 +74,12 @@
  *
  *   - Check the configured CONFIGURE_IDLE_TASK_BODY.
  *
- *   - Check the default value CONFIGURE_IDLE_TASK_STACK_SIZE where the
+ *   - Check the default value of CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE.
+ *
+ *   - Check the default value of CONFIGURE_IDLE_TASK_STACK_SIZE where the
  *     optional BSP-provided default value is enabled.
  *
- *   - Check the default value CONFIGURE_INTERRUPT_STACK_SIZE where the
+ *   - Check the default value of CONFIGURE_INTERRUPT_STACK_SIZE where the
  *     optional BSP-provided default value is enabled.
  *
  *   - Check the BSP-provided initial extension is registered.
@@ -160,11 +162,20 @@ static void AcfgValDefault_Action_0( void )
   T_step_eq_ptr( 0, rtems_configuration_get_idle_task(), IdleBody );
 
   /*
-   * Check the default value CONFIGURE_IDLE_TASK_STACK_SIZE where the optional
-   * BSP-provided default value is enabled.
+   * Check the default value of CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE.
    */
   T_step_eq_sz(
     1,
+    _Thread_Idle_minimum_stack_size,
+    CPU_STACK_MINIMUM_SIZE / 4
+  );
+
+  /*
+   * Check the default value of CONFIGURE_IDLE_TASK_STACK_SIZE where the
+   * optional BSP-provided default value is enabled.
+   */
+  T_step_eq_sz(
+    2,
     rtems_configuration_get_idle_task_stack_size(),
   #if defined(BSP_IDLE_TASK_STACK_SIZE)
     BSP_IDLE_TASK_STACK_SIZE
@@ -174,11 +185,11 @@ static void AcfgValDefault_Action_0( void )
   );
 
   /*
-   * Check the default value CONFIGURE_INTERRUPT_STACK_SIZE where the optional
-   * BSP-provided default value is enabled.
+   * Check the default value of CONFIGURE_INTERRUPT_STACK_SIZE where the
+   * optional BSP-provided default value is enabled.
    */
   T_step_eq_sz(
-    2,
+    3,
     rtems_configuration_get_interrupt_stack_size(),
   #if defined(BSP_INTERRUPT_STACK_SIZE)
     BSP_INTERRUPT_STACK_SIZE
@@ -190,9 +201,9 @@ static void AcfgValDefault_Action_0( void )
   /*
    * Check the BSP-provided initial extension is registered.
    */
-  T_step_eq_sz( 3, _User_extensions_Initial_count, 1 );
+  T_step_eq_sz( 4, _User_extensions_Initial_count, 1 );
   T_step_eq_ptr(
-    4,
+    5,
     _User_extensions_Initial_extensions[ 0 ].fatal,
     bsp.fatal
   );
@@ -216,7 +227,7 @@ static void AcfgValDefault_Action_1( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 5, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 6, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -242,7 +253,7 @@ static void AcfgValDefault_Action_2( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 6, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 7, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -266,7 +277,7 @@ static void AcfgValDefault_Action_3( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 7, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 8, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -282,7 +293,7 @@ static void AcfgValDefault_Action_4( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 8, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 9, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -290,7 +301,7 @@ static void AcfgValDefault_Action_4( void )
  */
 static void AcfgValDefault_Action_5( void )
 {
-  T_step_eq_u32( 9, rtems_scheduler_get_processor_maximum(), 1 );
+  T_step_eq_u32( 10, rtems_scheduler_get_processor_maximum(), 1 );
 }
 
 /**
@@ -312,7 +323,7 @@ static void AcfgValDefault_Action_6( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 10, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 11, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -328,7 +339,7 @@ static void AcfgValDefault_Action_7( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 11, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 12, sc, RTEMS_TOO_MANY );
 
   /*
    * Check the default CONFIGURE_MAXIMUM_TASKS value.  A maximum Classic API
@@ -339,7 +350,7 @@ static void AcfgValDefault_Action_7( void )
    * suite containing the test case.  The test suite defines
    * CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION.
    */
-  T_step_eq_u32( 12, rtems_configuration_get_maximum_tasks(), 0 );
+  T_step_eq_u32( 13, rtems_configuration_get_maximum_tasks(), 0 );
 }
 
 /**
@@ -355,7 +366,7 @@ static void AcfgValDefault_Action_8( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 13, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 14, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -373,7 +384,7 @@ static void AcfgValDefault_Action_9( void )
   /*
    * Check that the returned status code is RTEMS_TOO_MANY.
    */
-  T_step_rsc( 14, sc, RTEMS_TOO_MANY );
+  T_step_rsc( 15, sc, RTEMS_TOO_MANY );
 }
 
 /**
@@ -381,7 +392,7 @@ static void AcfgValDefault_Action_9( void )
  */
 T_TEST_CASE( AcfgValDefault )
 {
-  T_plan( 15 );
+  T_plan( 16 );
 
   AcfgValDefault_Action_0();
   AcfgValDefault_Action_1();
diff --git a/testsuites/validation/tr-fatal-idle-thread-stack-too-small.c b/testsuites/validation/tr-fatal-idle-thread-stack-too-small.c
new file mode 100644
index 0000000000..4d7fbee152
--- /dev/null
+++ b/testsuites/validation/tr-fatal-idle-thread-stack-too-small.c
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseScoreThreadValFatalIdleThreadStackTooSmall
+ */
+
+/*
+ * Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include "tr-fatal-idle-thread-stack-too-small.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseScoreThreadValFatalIdleThreadStackTooSmall \
+ *   spec:/score/thread/val/fatal-idle-thread-stack-too-small
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesFatalIdleThreadStackTooSmall
+ *
+ * @brief Tests a fatal error caused by a too small idle thread stack size.
+ *
+ * This test case performs the following actions:
+ *
+ * - The test action is carried out by configuring a thread-local storage
+ *   demand which leads to a too small idle thread stack size.
+ *
+ *   - Check that the expected fatal source is present.
+ *
+ *   - Check that the expected fatal code is present.
+ *
+ *   - Check the configured value of CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE.
+ *
+ * @{
+ */
+
+/**
+ * @brief Test context for
+ *   spec:/score/thread/val/fatal-idle-thread-stack-too-small test case.
+ */
+typedef struct {
+  /**
+   * @brief This member contains a copy of the corresponding
+   *   ScoreThreadValFatalIdleThreadStackTooSmall_Run() parameter.
+   */
+  rtems_fatal_source source;
+
+  /**
+   * @brief This member contains a copy of the corresponding
+   *   ScoreThreadValFatalIdleThreadStackTooSmall_Run() parameter.
+   */
+  rtems_fatal_code code;
+} ScoreThreadValFatalIdleThreadStackTooSmall_Context;
+
+static ScoreThreadValFatalIdleThreadStackTooSmall_Context
+  ScoreThreadValFatalIdleThreadStackTooSmall_Instance;
+
+static T_fixture ScoreThreadValFatalIdleThreadStackTooSmall_Fixture = {
+  .setup = NULL,
+  .stop = NULL,
+  .teardown = NULL,
+  .scope = NULL,
+  .initial_context = &ScoreThreadValFatalIdleThreadStackTooSmall_Instance
+};
+
+/**
+ * @brief The test action is carried out by configuring a thread-local storage
+ *   demand which leads to a too small idle thread stack size.
+ */
+static void ScoreThreadValFatalIdleThreadStackTooSmall_Action_0(
+  ScoreThreadValFatalIdleThreadStackTooSmall_Context *ctx
+)
+{
+  /* Nothing to do */
+
+  /*
+   * Check that the expected fatal source is present.
+   */
+  T_step_eq_int( 0, ctx->source, INTERNAL_ERROR_CORE );
+
+  /*
+   * Check that the expected fatal code is present.
+   */
+  T_step_eq_ulong(
+    1,
+    ctx->code,
+    INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL
+  );
+
+  /*
+   * Check the configured value of CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE.
+   */
+  T_step_eq_sz(
+    2,
+    _Thread_Idle_minimum_stack_size,
+    RTEMS_MINIMUM_STACK_SIZE
+  );
+}
+
+void ScoreThreadValFatalIdleThreadStackTooSmall_Run(
+  rtems_fatal_source source,
+  rtems_fatal_code   code
+)
+{
+  ScoreThreadValFatalIdleThreadStackTooSmall_Context *ctx;
+
+  ctx = &ScoreThreadValFatalIdleThreadStackTooSmall_Instance;
+  ctx->source = source;
+  ctx->code = code;
+
+  ctx = T_case_begin(
+    "ScoreThreadValFatalIdleThreadStackTooSmall",
+    &ScoreThreadValFatalIdleThreadStackTooSmall_Fixture
+  );
+
+  T_plan( 3 );
+
+  ScoreThreadValFatalIdleThreadStackTooSmall_Action_0( ctx );
+
+  T_case_end();
+}
+
+/** @} */
diff --git a/testsuites/validation/tr-fatal-idle-thread-stack-too-small.h b/testsuites/validation/tr-fatal-idle-thread-stack-too-small.h
new file mode 100644
index 0000000000..4d7aac4598
--- /dev/null
+++ b/testsuites/validation/tr-fatal-idle-thread-stack-too-small.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseScoreThreadValFatalIdleThreadStackTooSmall
+ */
+
+/*
+ * Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifndef _TR_FATAL_IDLE_THREAD_STACK_TOO_SMALL_H
+#define _TR_FATAL_IDLE_THREAD_STACK_TOO_SMALL_H
+
+#include <rtems.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup RTEMSTestCaseScoreThreadValFatalIdleThreadStackTooSmall
+ *
+ * @{
+ */
+
+/**
+ * @brief Runs the parameterized test case.
+ *
+ * @param source is the fatal source.
+ *
+ * @param code is the fatal code.
+ */
+void ScoreThreadValFatalIdleThreadStackTooSmall_Run(
+  rtems_fatal_source source,
+  rtems_fatal_code   code
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TR_FATAL_IDLE_THREAD_STACK_TOO_SMALL_H */
diff --git a/testsuites/validation/ts-fatal-idle-thread-stack-too-small.c b/testsuites/validation/ts-fatal-idle-thread-stack-too-small.c
new file mode 100644
index 0000000000..ff258a1d02
--- /dev/null
+++ b/testsuites/validation/ts-fatal-idle-thread-stack-too-small.c
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesFatalIdleThreadStackTooSmall
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tr-fatal-idle-thread-stack-too-small.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestSuiteTestsuitesFatalIdleThreadStackTooSmall \
+ *   spec:/testsuites/fatal-idle-thread-stack-too-small
+ *
+ * @ingroup RTEMSTestSuites
+ *
+ * @brief This validation test suite contains a test case which triggers a
+ *   fatal error during system initialization.
+ *
+ * @{
+ */
+
+const char rtems_test_name[] = "FatalIdleThreadStackTooSmall";
+
+#define FATAL_SYSINIT_RUN ScoreThreadValFatalIdleThreadStackTooSmall_Run
+
+static _Thread_local volatile uint8_t zero[ RTEMS_MINIMUM_STACK_SIZE ];
+
+static void Init( rtems_task_argument arg )
+{
+  (void) arg;
+  rtems_fatal( RTEMS_FATAL_SOURCE_EXIT, zero[ 0 ] + 1 );
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MINIMUM_TASKS_WITH_USER_PROVIDED_STORAGE 1
+
+#define CONFIGURE_IDLE_TASK_MINIMUM_STACK_SIZE RTEMS_MINIMUM_STACK_SIZE
+
+#define CONFIGURE_INIT_TASK_PRIORITY 0
+
+#define CONFIGURE_INIT_TASK_CONSTRUCT_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#include "ts-fatal-sysinit.h"
+
+/** @} */
-- 
2.35.3



More information about the devel mailing list