diff options
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/include/rtems/confdefs/percpu.h | 18 | ||||
-rw-r--r-- | cpukit/include/rtems/confdefs/wkspace.h | 16 | ||||
-rw-r--r-- | cpukit/include/rtems/config.h | 12 | ||||
-rw-r--r-- | cpukit/include/rtems/score/stack.h | 24 | ||||
-rw-r--r-- | cpukit/score/src/stackallocatorforidle.c | 59 | ||||
-rw-r--r-- | cpukit/score/src/threadcreateidle.c | 12 |
6 files changed, 133 insertions, 8 deletions
diff --git a/cpukit/include/rtems/confdefs/percpu.h b/cpukit/include/rtems/confdefs/percpu.h index badb616988..3bea8340cb 100644 --- a/cpukit/include/rtems/confdefs/percpu.h +++ b/cpukit/include/rtems/confdefs/percpu.h @@ -134,11 +134,19 @@ RTEMS_DEFINE_GLOBAL_SYMBOL( const size_t _Thread_Idle_stack_size = CONFIGURE_IDLE_TASK_STACK_SIZE; -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" ); +/* + * 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) diff --git a/cpukit/include/rtems/confdefs/wkspace.h b/cpukit/include/rtems/confdefs/wkspace.h index 1db4f2d09d..82de8633bf 100644 --- a/cpukit/include/rtems/confdefs/wkspace.h +++ b/cpukit/include/rtems/confdefs/wkspace.h @@ -167,12 +167,14 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE; #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wtautological-pointer-compare" + /* Custom allocator may or may not use the work space. */ #ifdef CONFIGURE_TASK_STACK_ALLOCATOR_AVOIDS_WORK_SPACE const bool _Stack_Allocator_avoids_workspace = true; #else const bool _Stack_Allocator_avoids_workspace = false; #endif + /* Custom allocator may or may not need initialization. */ #ifdef CONFIGURE_TASK_STACK_ALLOCATOR_INIT const Stack_Allocator_initialize _Stack_Allocator_initialize = _CONFIGURE_ASSERT_NOT_NULL( @@ -187,6 +189,7 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE; ); #endif + /* Custom allocator must include allocate and free */ const Stack_Allocator_allocate _Stack_Allocator_allocate = _CONFIGURE_ASSERT_NOT_NULL( Stack_Allocator_allocate, @@ -200,11 +203,24 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE; ); #pragma GCC diagnostic pop + +/* + * Must provide both a custom stack allocator and deallocator + */ #elif defined(CONFIGURE_TASK_STACK_ALLOCATOR) \ || defined(CONFIGURE_TASK_STACK_DEALLOCATOR) #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; +#endif + #ifdef CONFIGURE_DIRTY_MEMORY RTEMS_SYSINIT_ITEM( _Memory_Dirty_free_areas, diff --git a/cpukit/include/rtems/config.h b/cpukit/include/rtems/config.h index afcee4381b..7b15bc34a2 100644 --- a/cpukit/include/rtems/config.h +++ b/cpukit/include/rtems/config.h @@ -368,6 +368,18 @@ uint32_t rtems_configuration_get_maximum_extensions( void ); */ #define rtems_configuration_get_stack_free_hook() _Stack_Allocator_free +/** + * @ingroup RTEMSAPIConfig + * + * @brief Gets the IDLE thread stack allocator hook configured for this + * application. + * + * @return Returns the IDLE thread stack allocator hook configured for this + * application. + */ +#define rtems_configuration_get_stack_allocate_for_idle_hook() \ + (_Stack_Allocator_allocate_for_idle) + /* Generated from spec:/rtems/config/if/get-stack-space-size */ /** diff --git a/cpukit/include/rtems/score/stack.h b/cpukit/include/rtems/score/stack.h index 23421cf7ae..ffa6368ba5 100644 --- a/cpukit/include/rtems/score/stack.h +++ b/cpukit/include/rtems/score/stack.h @@ -81,6 +81,23 @@ typedef void *( *Stack_Allocator_allocate )( size_t stack_size ); typedef void ( *Stack_Allocator_free )( void *addr ); /** + * @brief Stack allocator allocate for idle handler. + * + * The allocate for idle handler is optional even when the user thread stack + * allocator and deallocator are configured. + * + * @param cpu Index of the CPU for the IDLE thread using this stack + * @param stack_size The size of the stack area to allocate in bytes. + * + * @retval NULL Not enough memory. + * @retval other Pointer to begin of stack area. + */ +typedef void *( *Stack_Allocator_allocate_for_idle )( + uint32_t cpu, + size_t stack_size +); + +/** * @brief The minimum stack size. * * Application provided via <rtems/confdefs.h>. @@ -130,6 +147,13 @@ extern const Stack_Allocator_free _Stack_Allocator_free; void _Stack_Allocator_do_initialize( void ); /** @} */ +/** + * @brief The stack allocator allocate stack for idle thread handler. + * + * Application provided via <rtems/confdefs.h>. + */ +extern const Stack_Allocator_allocate_for_idle + _Stack_Allocator_allocate_for_idle; #ifdef __cplusplus } diff --git a/cpukit/score/src/stackallocatorforidle.c b/cpukit/score/src/stackallocatorforidle.c new file mode 100644 index 0000000000..7c4fd10c7d --- /dev/null +++ b/cpukit/score/src/stackallocatorforidle.c @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2021 OAR Corporation + * + * 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/thread.h> + +/** + * @brief Default stack allocator allocate for idle handler. + * + * The allocate for idle handler is optional even when the user thread stack + * allocator and deallocator are configured. + * + * The default allocator for IDLE thread stacks gets the memory from a + * statically allocated area provided via confdefs.h. + * + * @param cpu Index of the CPU for the IDLE thread using this stack + * @param stack_size The size of the stack area to allocate in bytes. + * + * @retval NULL Not enough memory (never returned). + * @retval other Pointer to begin of stack area. + */ +static void *_Stack_Allocator_allocate_for_idle_default( + uint32_t cpu, + size_t stack_size +) +{ + return &_Thread_Idle_stacks[ cpu * stack_size ]; +} + +const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle = + _Stack_Allocator_allocate_for_idle_default; diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c index f5ffc9bad8..86e117e70f 100644 --- a/cpukit/score/src/threadcreateidle.c +++ b/cpukit/score/src/threadcreateidle.c @@ -49,9 +49,15 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu ) config.is_preemptible = true; config.stack_size = _Thread_Idle_stack_size + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE; - config.stack_area = &_Thread_Idle_stacks[ - _Per_CPU_Get_index( cpu ) * config.stack_size - ]; + + /* + * The IDLE thread stacks may be statically allocated or there may be a + * custom allocator provided just as with user threads. + */ + config.stack_area = (*_Stack_Allocator_allocate_for_idle)( + _Per_CPU_Get_index( cpu ), + config.stack_size + ); /* * The entire workspace is zeroed during its initialization. Thus, all |