[PATCH v2 12/13] config: Add CONFIGURE_IDLE_TASK_STORAGE_SIZE
Sebastian Huber
sebastian.huber at embedded-brains.de
Thu Oct 6 08:23:31 UTC 2022
By default, allocate the IDLE task storage areas from the RTEMS Workspace.
This avoids having to estimate the thread-local storage size in the default
configuration.
Add the application configuration option CONFIGURE_IDLE_TASK_STORAGE_SIZE to
request a static allocation of the task storage area for IDLE tasks.
Update #3835.
Update #4524.
---
cpukit/doxygen/appl-config.h | 95 +++++++++++++++++--
cpukit/include/rtems/confdefs/percpu.h | 14 ---
cpukit/include/rtems/confdefs/threads.h | 4 +
cpukit/include/rtems/confdefs/wkspace.h | 50 ++++++++--
cpukit/include/rtems/score/interr.h | 3 +-
cpukit/include/rtems/score/stack.h | 58 ++++++++++-
cpukit/include/rtems/score/thread.h | 7 --
cpukit/sapi/src/interrtext.c | 3 +-
cpukit/score/src/stackallocatorforidle.c | 43 ++++-----
.../score/src/stackallocatorforidlewkspace.c | 60 ++++++++++++
cpukit/score/src/threadcreateidle.c | 23 +++--
spec/build/cpukit/librtemscpu.yml | 1 +
spec/build/testsuites/sptests/grp.yml | 2 +
spec/build/testsuites/sptests/spfatal36.yml | 19 ++++
testsuites/sptests/spfatal36/init.c | 62 ++++++++++++
testsuites/sptests/spfatal36/spfatal36.doc | 11 +++
testsuites/sptests/spinternalerror02/init.c | 2 +-
testsuites/sptests/spstkalloc02/init.c | 13 +++
testsuites/sptests/sptls02/init.cc | 8 +-
testsuites/validation/ts-default.h | 5 +-
testsuites/validation/ts-fatal-sysinit.h | 2 +
testsuites/validation/ts-idle.h | 4 +
testsuites/validation/ts-validation-acfg-0.c | 2 +
testsuites/validation/ts-validation-acfg-1.c | 2 +
.../validation/ts-validation-io-kernel.c | 2 +
testsuites/validation/ts-validation-tls-1.c | 3 +
26 files changed, 418 insertions(+), 80 deletions(-)
create mode 100644 cpukit/score/src/stackallocatorforidlewkspace.c
create mode 100644 spec/build/testsuites/sptests/spfatal36.yml
create mode 100644 testsuites/sptests/spfatal36/init.c
create mode 100644 testsuites/sptests/spfatal36/spfatal36.doc
diff --git a/cpukit/doxygen/appl-config.h b/cpukit/doxygen/appl-config.h
index d53947c71a..88cd03d328 100644
--- a/cpukit/doxygen/appl-config.h
+++ b/cpukit/doxygen/appl-config.h
@@ -3431,6 +3431,59 @@
*/
#define CONFIGURE_IDLE_TASK_STACK_SIZE
+/* Generated from spec:/acfg/if/idle-task-storage-size */
+
+/**
+ * @brief This configuration option is an integer define.
+ *
+ * If this configuration option is specified, then the task storage areas for
+ * the IDLE tasks are statically allocated by <rtems/confdefs.h>. The value of
+ * this configuration option defines the size in bytes of the task storage area
+ * of each IDLE task in the system.
+ *
+ * @par Default Value
+ * This configuration option has no default value. If it is not specified,
+ * then the task storage area for each IDLE task will allocated from the RTEMS
+ * Workspace or through a custom IDLE task stack allocator.
+ *
+ * @par Constraints
+ * The value of the configuration option shall be greater than or equal to
+ * #CONFIGURE_IDLE_TASK_STACK_SIZE.
+ *
+ * @par Notes
+ * @parblock
+ * By default, the IDLE task storage areas are allocated from the RTEMS
+ * Workspace. Applications which do not want to use a heap allocator can use
+ * this configuration option to use statically allocated memory for the IDLE
+ * task storage areas. 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. You have
+ * to estimate the actual thread-local storage size if you want to use this
+ * configuration option. If the IDLE task stack size would be less than the
+ * value defined by the #CONFIGURE_IDLE_TASK_STACK_SIZE configuration option,
+ * for example because the thread-local storage size is larger than expected,
+ * 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.
+ *
+ * The value of this configuration option is passed to
+ * RTEMS_TASK_STORAGE_SIZE() by <rtems/confdefs.h> to determine the actual size
+ * of the statically allocated area to take architecture-specific overheads
+ * into account.
+ *
+ * The
+ *
+ * * ``CONFIGURE_IDLE_TASK_STORAGE_SIZE``, and
+ *
+ * * #CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
+ *
+ * configuration options are mutually exclusive.
+ * @endparblock
+ */
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE
+
/** @} */
/* Generated from spec:/acfg/if/group-mpci */
@@ -4826,23 +4879,45 @@
* @brief This configuration option is an initializer define.
*
* The value of this configuration option is the address for the stack
- * allocator allocate handler used to allocate the task stack of each IDLE
- * task.
+ * allocator allocate handler used to allocate the task storage area of each
+ * IDLE 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
- * allocated by ``<rtems/confdefs.h>``.
+ * By default, the IDLE task storage area will be allocated from the RTEMS
+ * Workspace.
*
* @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.
+ * configuration options. It is assumed that any memory allocated for the task
+ * storage area of an IDLE task will not be from the RTEMS Workspace.
+ *
+ * The IDLE task stack allocator may increase the size of the allocated memory
+ * area to account for the actually allocated memory area.
+ *
+ * The
+ *
+ * * #CONFIGURE_IDLE_TASK_STORAGE_SIZE, and
+ *
+ * * ``CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE``
+ *
+ * configuration options are mutually exclusive.
+ * @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..a6b35e0eaf 100644
--- a/cpukit/include/rtems/confdefs/percpu.h
+++ b/cpukit/include/rtems/confdefs/percpu.h
@@ -136,20 +136,6 @@ RTEMS_DEFINE_GLOBAL_SYMBOL(
const size_t _Thread_Idle_stack_size = CONFIGURE_IDLE_TASK_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
- * threadcreateidle.c. The code path just never uses it. Make it minimal
- * size to proceed.
- */
-#ifndef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
- char _Thread_Idle_stacks[
- _CONFIGURE_MAXIMUM_PROCESSORS
- * ( CONFIGURE_IDLE_TASK_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE )
- ] RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
- RTEMS_SECTION( ".rtemsstack.idle" );
-#endif
-
#if defined(CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION) && \
!defined(CONFIGURE_IDLE_TASK_BODY)
#error "If you define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION, then you must define CONFIGURE_IDLE_TASK_BODY as well"
diff --git a/cpukit/include/rtems/confdefs/threads.h b/cpukit/include/rtems/confdefs/threads.h
index 4040bcb50a..5ccfffaf6e 100644
--- a/cpukit/include/rtems/confdefs/threads.h
+++ b/cpukit/include/rtems/confdefs/threads.h
@@ -235,6 +235,10 @@ const size_t _Thread_Control_add_on_count =
#endif
const size_t _Thread_Initial_thread_count =
+#if !defined(CONFIGURE_IDLE_TASK_STORAGE_SIZE) && \
+ !defined(CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE)
+ _CONFIGURE_MAXIMUM_PROCESSORS +
+#endif
rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) +
rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS );
diff --git a/cpukit/include/rtems/confdefs/wkspace.h b/cpukit/include/rtems/confdefs/wkspace.h
index 82de8633bf..5b80872d2b 100644
--- a/cpukit/include/rtems/confdefs/wkspace.h
+++ b/cpukit/include/rtems/confdefs/wkspace.h
@@ -47,6 +47,7 @@
#include <rtems/confdefs/inittask.h>
#include <rtems/confdefs/initthread.h>
#include <rtems/confdefs/objectsposix.h>
+#include <rtems/confdefs/percpu.h>
#include <rtems/confdefs/threads.h>
#include <rtems/confdefs/wkspacesupport.h>
#include <rtems/score/coremsg.h>
@@ -111,8 +112,18 @@
+ 1024 * CONFIGURE_MEMORY_OVERHEAD \
+ _CONFIGURE_HEAP_HANDLER_OVERHEAD )
+#if defined(CONFIGURE_IDLE_TASK_STORAGE_SIZE) || \
+ defined(CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE)
+ #define _CONFIGURE_IDLE_TASK_STACKS 0
+#else
+ #define _CONFIGURE_IDLE_TASK_STACKS \
+ ( _CONFIGURE_MAXIMUM_PROCESSORS * \
+ _Configure_From_stackspace( CONFIGURE_IDLE_TASK_STACK_SIZE ) )
+#endif
+
#define _CONFIGURE_STACK_SPACE_SIZE \
( _CONFIGURE_INIT_TASK_STACK_EXTRA \
+ + _CONFIGURE_IDLE_TASK_STACKS \
+ _CONFIGURE_POSIX_INIT_THREAD_STACK_EXTRA \
+ _CONFIGURE_LIBBLOCK_TASKS_STACK_EXTRA \
+ CONFIGURE_EXTRA_TASK_STACKS \
@@ -212,15 +223,40 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
#error "CONFIGURE_TASK_STACK_ALLOCATOR and CONFIGURE_TASK_STACK_DEALLOCATOR must be both defined or both undefined"
#endif
-/*
- * Custom IDLE thread stacks allocator. If this is provided, it is assumed
- * that the allocator is providing its own memory for these stacks.
- */
-#ifdef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
- const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
- CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE;
+#ifdef CONFIGURE_IDLE_TASK_STORAGE_SIZE
+ #ifdef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
+ #error "CONFIGURE_IDLE_TASK_STORAGE_SIZE and CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE are mutually exclusive"
+ #endif
+
+ #define _CONFIGURE_IDLE_TASK_STORAGE_SIZE \
+ RTEMS_ALIGN_UP( \
+ RTEMS_TASK_STORAGE_SIZE( \
+ CONFIGURE_IDLE_TASK_STORAGE_SIZE, \
+ RTEMS_DEFAULT_ATTRIBUTES \
+ ), \
+ CPU_INTERRUPT_STACK_ALIGNMENT \
+ )
+
+ const size_t _Stack_Allocator_allocate_for_idle_storage_size =
+ _CONFIGURE_IDLE_TASK_STORAGE_SIZE;
+
+ char _Stack_Allocator_allocate_for_idle_storage_areas[
+ _CONFIGURE_MAXIMUM_PROCESSORS * _CONFIGURE_IDLE_TASK_STORAGE_SIZE
+ ] RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
+ RTEMS_SECTION( ".rtemsstack.idle" );
+
+ #define CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE \
+ _Stack_Allocator_allocate_for_idle_static
#endif
+#ifndef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE
+ #define CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE \
+ _Stack_Allocator_allocate_for_idle_workspace;
+#endif
+
+const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
+ CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE;
+
#ifdef CONFIGURE_DIRTY_MEMORY
RTEMS_SYSINIT_ITEM(
_Memory_Dirty_free_areas,
diff --git a/cpukit/include/rtems/score/interr.h b/cpukit/include/rtems/score/interr.h
index d0ecf0f5c8..f21e8d58a1 100644
--- a/cpukit/include/rtems/score/interr.h
+++ b/cpukit/include/rtems/score/interr.h
@@ -229,7 +229,8 @@ typedef enum {
INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA = 40,
INTERNAL_ERROR_TOO_LARGE_TLS_SIZE = 41,
INTERNAL_ERROR_RTEMS_INIT_TASK_CONSTRUCT_FAILED = 42,
- INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED = 43
+ INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED = 43,
+ INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STORAGE = 44
} Internal_errors_Core_list;
typedef CPU_Uint32ptr Internal_errors_t;
diff --git a/cpukit/include/rtems/score/stack.h b/cpukit/include/rtems/score/stack.h
index 7577ca0474..9326480373 100644
--- a/cpukit/include/rtems/score/stack.h
+++ b/cpukit/include/rtems/score/stack.h
@@ -11,8 +11,8 @@
*/
/*
- * COPYRIGHT (c) 1989-2006.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (C) 2022 embedded brains GmbH
+ * Copyright (C) 1989, 2021 On-Line Applications Research Corporation (OAR)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -172,7 +172,57 @@ extern const Stack_Allocator_free _Stack_Allocator_free;
*/
void _Stack_Allocator_do_initialize( void );
-/** @} */
+/**
+ * @brief Allocates the IDLE thread storage area from the workspace.
+ *
+ * If the thread storage area cannot be allocated, then the
+ * ::INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STACK fatal error will occur.
+ *
+ * @param unused is an unused parameter.
+ *
+ * @param stack_size[in] is pointer to a size_t object. On function entry, the
+ * object contains the size of the task storage area to allocate in bytes.
+ *
+ * @return Returns a pointer to the begin of the allocated task storage area.
+ */
+void *_Stack_Allocator_allocate_for_idle_workspace(
+ uint32_t unused,
+ size_t *storage_size
+);
+
+/**
+ * @brief The size in bytes of the idle thread storage area used by
+ * _Stack_Allocator_allocate_for_idle_static().
+ *
+ * Application provided via <rtems/confdefs.h>.
+ */
+extern const size_t _Stack_Allocator_allocate_for_idle_storage_size;
+
+/**
+ * @brief The thread storage areas used by
+ * _Stack_Allocator_allocate_for_idle_static().
+ *
+ * Application provided via <rtems/confdefs.h>.
+ */
+extern char _Stack_Allocator_allocate_for_idle_storage_areas[];
+
+/**
+ * @brief Allocates the IDLE thread storage from the memory statically
+ * allocated by <rtems/confdefs.h>.
+ *
+ * @param cpu_index is the index of the CPU for the IDLE thread using this stack.
+ *
+ * @param stack_size[out] is pointer to a size_t object. On function return, the
+ * object value is set to the value of
+ * ::_Stack_Allocator_allocate_for_idle_storage_size.
+ *
+ * @return Returns a pointer to the begin of the allocated task storage area.
+ */
+void *_Stack_Allocator_allocate_for_idle_static(
+ uint32_t cpu_index,
+ size_t *storage_size
+);
+
/**
* @brief The stack allocator allocate stack for idle thread handler.
*
@@ -181,6 +231,8 @@ void _Stack_Allocator_do_initialize( void );
extern const Stack_Allocator_allocate_for_idle
_Stack_Allocator_allocate_for_idle;
+/** @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/include/rtems/score/thread.h b/cpukit/include/rtems/score/thread.h
index 40fefbc79a..cafa850a94 100644
--- a/cpukit/include/rtems/score/thread.h
+++ b/cpukit/include/rtems/score/thread.h
@@ -1179,13 +1179,6 @@ Thread_Information name##_Information = { \
} \
}
-/**
- * @brief The idle thread stacks.
- *
- * Provided by the application via <rtems/confdefs.h>.
- */
-extern char _Thread_Idle_stacks[];
-
#if defined(RTEMS_MULTIPROCESSING)
/**
* @brief The configured thread control block.
diff --git a/cpukit/sapi/src/interrtext.c b/cpukit/sapi/src/interrtext.c
index 6ed115f430..e828a82051 100644
--- a/cpukit/sapi/src/interrtext.c
+++ b/cpukit/sapi/src/interrtext.c
@@ -84,7 +84,8 @@ static const char *const internal_error_text[] = {
"INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA",
"INTERNAL_ERROR_TOO_LARGE_TLS_SIZE",
"INTERNAL_ERROR_RTEMS_INIT_TASK_CONSTRUCT_FAILED",
- "INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED"
+ "INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED",
+ "INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STORAGE"
};
const char *rtems_internal_error_text( rtems_fatal_code error )
diff --git a/cpukit/score/src/stackallocatorforidle.c b/cpukit/score/src/stackallocatorforidle.c
index c97dde030f..c8c8c0b766 100644
--- a/cpukit/score/src/stackallocatorforidle.c
+++ b/cpukit/score/src/stackallocatorforidle.c
@@ -1,6 +1,15 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreStack
*
+ * @brief This source file contains the implementation of
+ * _Stack_Allocator_allocate_for_idle_static().
+ */
+
+/*
* Copyright (C) 2021 On-Line Applications Research Corporation (OAR)
*
* Redistribution and use in source and binary forms, with or without
@@ -30,35 +39,21 @@
#endif
#include <rtems/score/stack.h>
-#include <rtems/score/thread.h>
#include <rtems/score/assert.h>
-/**
- * @brief Default stack allocator allocate for IDLE threads.
- *
- * The default allocator for IDLE thread stacks gets the memory from a
- * statically allocated area provided via confdefs.h.
- *
- * @param cpu is the index of the CPU for the IDLE thread using this stack.
- *
- * @param stack_size[in] is pointer to a size_t object. On function
- * entry, the object contains the size of the stack area to allocate in
- * bytes.
- *
- * @return Returns the pointer to begin of the allocated stack area.
- */
-static void *_Stack_Allocator_allocate_for_idle_default(
+void *_Stack_Allocator_allocate_for_idle_static(
uint32_t cpu_index,
- size_t *stack_size
+ size_t *storage_size
)
{
+ size_t size;
+
+ size = _Stack_Allocator_allocate_for_idle_storage_size;
+ *storage_size = size;
#if defined(RTEMS_SMP)
- return &_Thread_Idle_stacks[ cpu_index * ( *stack_size ) ];
+ return &_Stack_Allocator_allocate_for_idle_storage_areas[ cpu_index * size ];
#else
_Assert( cpu_index == 0 );
- return &_Thread_Idle_stacks[ 0 ];
+ return &_Stack_Allocator_allocate_for_idle_storage_areas[ 0 ];
#endif
}
-
-const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
- _Stack_Allocator_allocate_for_idle_default;
diff --git a/cpukit/score/src/stackallocatorforidlewkspace.c b/cpukit/score/src/stackallocatorforidlewkspace.c
new file mode 100644
index 0000000000..0864271f07
--- /dev/null
+++ b/cpukit/score/src/stackallocatorforidlewkspace.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreStack
+ *
+ * @brief This source file contains the implementation of
+ * _Stack_Allocator_allocate_for_idle_workspace().
+ */
+
+/*
+ * Copyright (C) 2022 embedded brains GmbH
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/stack.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/wkspace.h>
+
+void *_Stack_Allocator_allocate_for_idle_workspace(
+ uint32_t unused,
+ size_t *storage_size
+)
+{
+ void *area;
+
+ (void) unused;
+ area = _Workspace_Allocate( *storage_size );
+
+ if ( area == NULL ) {
+ _Internal_error( INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STORAGE );
+ }
+
+ return area;
+}
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index d2037b36f0..04565f910b 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 storage_size
+)
{
Thread_Configuration config;
Thread_Control *idle;
@@ -70,8 +73,7 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
config.is_fp = CPU_IDLE_TASK_IS_FP;
config.is_preemptible = true;
config.stack_free = _Objects_Free_nothing;
- config.stack_size = _Thread_Idle_stack_size
- + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE;
+ config.stack_size = storage_size;
/*
* The IDLE thread stacks may be statically allocated or there may be a
@@ -118,21 +120,28 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
void _Thread_Create_idle( void )
{
+ uintptr_t storage_size;
#if defined(RTEMS_SMP)
- uint32_t cpu_max;
- uint32_t cpu_index;
+ uint32_t cpu_max;
+ uint32_t cpu_index;
+#endif
+
+ storage_size = _TLS_Get_allocation_size() +
+ CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE +
+ _Thread_Idle_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, storage_size );
}
}
#else
- _Thread_Create_idle_for_CPU( _Per_CPU_Get() );
+ _Thread_Create_idle_for_CPU( _Per_CPU_Get(), storage_size );
#endif
_CPU_Use_thread_local_storage(
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index f034f3fadf..a1be70c6da 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -1545,6 +1545,7 @@ source:
- cpukit/score/src/smpbarrierwait.c
- cpukit/score/src/stackallocator.c
- cpukit/score/src/stackallocatorforidle.c
+- cpukit/score/src/stackallocatorforidlewkspace.c
- cpukit/score/src/stackallocatorfree.c
- cpukit/score/src/stackallocatorinit.c
- cpukit/score/src/thread.c
diff --git a/spec/build/testsuites/sptests/grp.yml b/spec/build/testsuites/sptests/grp.yml
index c8f70ed13b..b14eefb145 100644
--- a/spec/build/testsuites/sptests/grp.yml
+++ b/spec/build/testsuites/sptests/grp.yml
@@ -258,6 +258,8 @@ links:
uid: spfatal34
- role: build-dependency
uid: spfatal35
+- role: build-dependency
+ uid: spfatal36
- role: build-dependency
uid: spfifo01
- role: build-dependency
diff --git a/spec/build/testsuites/sptests/spfatal36.yml b/spec/build/testsuites/sptests/spfatal36.yml
new file mode 100644
index 0000000000..9e623e3511
--- /dev/null
+++ b/spec/build/testsuites/sptests/spfatal36.yml
@@ -0,0 +1,19 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2022 embedded brains GmbH
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/sptests/spfatal36/init.c
+stlib: []
+target: testsuites/sptests/spfatal36.exe
+type: build
+use-after: []
+use-before: []
diff --git a/testsuites/sptests/spfatal36/init.c b/testsuites/sptests/spfatal36/init.c
new file mode 100644
index 0000000000..78725e1d19
--- /dev/null
+++ b/testsuites/sptests/spfatal36/init.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 embedded brains GmbH
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../spfatal_support/spfatal.h"
+
+#include <rtems/sysinit.h>
+#include <rtems/rtems/support.h>
+
+#define FATAL_ERROR_TEST_NAME "36"
+
+#define FATAL_ERROR_DESCRIPTION "failure in idle task storage allocation"
+
+#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_CORE
+
+#define FATAL_ERROR_EXPECTED_ERROR \
+ INTERNAL_ERROR_NO_MEMORY_FOR_IDLE_TASK_STORAGE
+
+static void force_error( void )
+{
+ RTEMS_UNREACHABLE();
+}
+
+static void empty_workspace( void )
+{
+ (void) rtems_workspace_greedy_allocate( NULL, 0 );
+}
+
+RTEMS_SYSINIT_ITEM(
+ empty_workspace,
+ RTEMS_SYSINIT_IDLE_THREADS,
+ RTEMS_SYSINIT_ORDER_FIRST
+);
+
+#include "../spfatal_support/spfatalimpl.h"
diff --git a/testsuites/sptests/spfatal36/spfatal36.doc b/testsuites/sptests/spfatal36/spfatal36.doc
new file mode 100644
index 0000000000..0719e8e01c
--- /dev/null
+++ b/testsuites/sptests/spfatal36/spfatal36.doc
@@ -0,0 +1,11 @@
+This file describes the concepts tested by this test set.
+
+test set name: spfatal36
+
+directives:
+
+ - _Stack_Allocator_allocate_for_idle_workspace()
+
+concepts:
+
+ - Provoke a memory allocation failure in the directive.
diff --git a/testsuites/sptests/spinternalerror02/init.c b/testsuites/sptests/spinternalerror02/init.c
index f94759a99b..475e31e085 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_NO_MEMORY_FOR_IDLE_TASK_STORAGE
);
}
diff --git a/testsuites/sptests/spstkalloc02/init.c b/testsuites/sptests/spstkalloc02/init.c
index 3613a6a563..7fee4615ad 100644
--- a/testsuites/sptests/spstkalloc02/init.c
+++ b/testsuites/sptests/spstkalloc02/init.c
@@ -44,6 +44,7 @@ const char rtems_test_name[] = "SPSTKALLOC 2";
#include <stdio.h>
#include <inttypes.h>
+#include <rtems/malloc.h>
#include <rtems/score/heapimpl.h>
#define TASK_COUNT 5
@@ -56,6 +57,8 @@ static void task_stack_init(size_t stack_space_size);
static void *task_stack_allocate(size_t stack_size);
+static void *task_stack_allocate_for_idle(uint32_t unused, size_t *stack_size);
+
static void task_stack_free(void *addr);
static void print_info(void)
@@ -149,6 +152,7 @@ static rtems_task Init(rtems_task_argument argument)
#define CONFIGURE_TASK_STACK_ALLOCATOR_INIT task_stack_init
#define CONFIGURE_TASK_STACK_ALLOCATOR task_stack_allocate
+#define CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE task_stack_allocate_for_idle
#define CONFIGURE_TASK_STACK_DEALLOCATOR task_stack_free
#define CONFIGURE_TASK_STACK_ALLOCATOR_AVOIDS_WORK_SPACE
#define CONFIGURE_TASK_STACK_FROM_ALLOCATOR(stack_size) \
@@ -183,6 +187,15 @@ static void *task_stack_allocate(size_t stack_size)
return _Heap_Allocate(&task_stack_heap, stack_size);
}
+static void *task_stack_allocate_for_idle(uint32_t unused, size_t *stack_size)
+{
+ return rtems_heap_allocate_aligned_with_boundary(
+ *stack_size,
+ CPU_STACK_ALIGNMENT,
+ 0
+ );
+}
+
static void task_stack_free(void *addr)
{
_Heap_Free(&task_stack_heap, addr);
diff --git a/testsuites/sptests/sptls02/init.cc b/testsuites/sptests/sptls02/init.cc
index 39fc2a2a24..b453ef3f62 100644
--- a/testsuites/sptests/sptls02/init.cc
+++ b/testsuites/sptests/sptls02/init.cc
@@ -48,7 +48,7 @@ alignas(256) static thread_local long a256 = 256;
static thread_local long i0;
-alignas(512) static thread_local long a512;
+alignas(RTEMS_MINIMUM_STACK_SIZE) static thread_local long a;
int seven()
{
@@ -61,7 +61,7 @@ static void clobber()
i123 = 0xdead0001;
a256 = 0xdead0002;
i0 = 0xdead0003;
- a512 = 0xdead0004;
+ a = 0xdead0004;
}
static long f456(bool clobber)
@@ -173,8 +173,8 @@ static void checkTLSValues()
RTEMS_OBFUSCATE_VARIABLE(addr);
rtems_test_assert((addr % 256) == 0);
rtems_test_assert(i0 == 0);
- rtems_test_assert(a512 == 0);
- addr = reinterpret_cast<uintptr_t>(&a512);
+ rtems_test_assert(a == 0);
+ addr = reinterpret_cast<uintptr_t>(&a);
RTEMS_OBFUSCATE_VARIABLE(addr);
rtems_test_assert((addr % 512) == 0);
rtems_test_assert(f456(false) == 456);
diff --git a/testsuites/validation/ts-default.h b/testsuites/validation/ts-default.h
index 6e77496b90..be26055c8b 100644
--- a/testsuites/validation/ts-default.h
+++ b/testsuites/validation/ts-default.h
@@ -317,7 +317,10 @@ RTEMS_SCHEDULER_PRIORITY( a, 64 );
#define CONFIGURE_IDLE_TASK_STACK_SIZE TEST_IDLE_STACK_SIZE
static char test_idle_stacks[ CONFIGURE_MAXIMUM_PROCESSORS ][
- ( TEST_IDLE_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE )
+ RTEMS_ALIGN_UP(
+ MAX_TLS_SIZE + TEST_IDLE_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE,
+ CPU_INTERRUPT_STACK_ALIGNMENT
+ )
]
RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
RTEMS_SECTION( ".rtemsstack.idle" );
diff --git a/testsuites/validation/ts-fatal-sysinit.h b/testsuites/validation/ts-fatal-sysinit.h
index 09d86d02ea..7a2f86ecca 100644
--- a/testsuites/validation/ts-fatal-sysinit.h
+++ b/testsuites/validation/ts-fatal-sysinit.h
@@ -133,6 +133,8 @@ RTEMS_SYSINIT_ITEM(
{ .fatal = FatalInitialExtension }, \
{ .fatal = TestSuiteFatalExtension }
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
#if !defined(CONFIGURE_RTEMS_INIT_TASKS_TABLE)
#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
diff --git a/testsuites/validation/ts-idle.h b/testsuites/validation/ts-idle.h
index 071209b5ef..04feaa096d 100644
--- a/testsuites/validation/ts-idle.h
+++ b/testsuites/validation/ts-idle.h
@@ -72,6 +72,10 @@ static const T_config test_config = {
#define CONFIGURE_INITIAL_EXTENSIONS \
{ .fatal = FatalInitialExtension }
+#ifndef CONFIGURE_IDLE_TASK_STORAGE_SIZE
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+#endif
+
#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
void *IdleBody( uintptr_t ignored )
diff --git a/testsuites/validation/ts-validation-acfg-0.c b/testsuites/validation/ts-validation-acfg-0.c
index e1144dd95d..f0fd359007 100644
--- a/testsuites/validation/ts-validation-acfg-0.c
+++ b/testsuites/validation/ts-validation-acfg-0.c
@@ -72,6 +72,8 @@
const char rtems_test_name[] = "ValidationAcfg0";
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
void *IdleBody( uintptr_t ignored )
diff --git a/testsuites/validation/ts-validation-acfg-1.c b/testsuites/validation/ts-validation-acfg-1.c
index 863a672b23..b12ccb928b 100644
--- a/testsuites/validation/ts-validation-acfg-1.c
+++ b/testsuites/validation/ts-validation-acfg-1.c
@@ -94,6 +94,8 @@ static void Init( rtems_task_argument arg )
#define CONFIGURE_DISABLE_BSP_SETTINGS
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
diff --git a/testsuites/validation/ts-validation-io-kernel.c b/testsuites/validation/ts-validation-io-kernel.c
index 83234ecfff..db44303890 100644
--- a/testsuites/validation/ts-validation-io-kernel.c
+++ b/testsuites/validation/ts-validation-io-kernel.c
@@ -138,6 +138,8 @@ static void *IdleBody( uintptr_t ignored )
#define CONFIGURE_SCHEDULER_TABLE_ENTRIES { }
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
#define CONFIGURE_IDLE_TASK_BODY IdleBody
diff --git a/testsuites/validation/ts-validation-tls-1.c b/testsuites/validation/ts-validation-tls-1.c
index b9b4adc31e..d05f9e1d08 100644
--- a/testsuites/validation/ts-validation-tls-1.c
+++ b/testsuites/validation/ts-validation-tls-1.c
@@ -68,6 +68,9 @@
const char rtems_test_name[] = "ValidationTls1";
+#define CONFIGURE_IDLE_TASK_STORAGE_SIZE \
+ ( RTEMS_MINIMUM_STACK_SIZE + 4096 )
+
#include "ts-idle.h"
/** @} */
--
2.35.3
More information about the devel
mailing list