From 45ee958552ca35b6834985718ecd59b27fc52f86 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 30 Sep 2022 08:06:18 +0200 Subject: config: Add CONFIGURE_IDLE_TASK_STORAGE_SIZE 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 +++++------ cpukit/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 | 63 ++++++++++++++++ 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 + testsuites/validation/ts-validation-io-kernel.c | 2 + testsuites/validation/ts-validation-tls-1.c | 3 + 26 files changed, 419 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 . 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 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 ````. + * 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..da766fd8af 100644 --- a/cpukit/include/rtems/confdefs/wkspace.h +++ b/cpukit/include/rtems/confdefs/wkspace.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -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 . + */ +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 . + */ +extern char _Stack_Allocator_allocate_for_idle_storage_areas[]; + +/** + * @brief Allocates the IDLE thread storage from the memory statically + * allocated by . + * + * @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 f82d4b954c..2b4d6823f0 100644 --- a/cpukit/include/rtems/score/thread.h +++ b/cpukit/include/rtems/score/thread.h @@ -1186,13 +1186,6 @@ Thread_Information name##_Information = { \ } \ } -/** - * @brief The idle thread stacks. - * - * Provided by the application via . - */ -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 -#include #include -/** - * @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 +#include +#include + +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 -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..f2a076724a --- /dev/null +++ b/testsuites/sptests/spfatal36/init.c @@ -0,0 +1,63 @@ +/* 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 +#include +#include + +#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) _Heap_Greedy_allocate( &_Workspace_Area, 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 #include +#include #include #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(&a512); + rtems_test_assert(a == 0); + addr = reinterpret_cast(&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" /** @} */ -- cgit v1.2.3