[RTEMS 5] Add support for IDLE Thread stack allocator

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Oct 4 17:35:50 UTC 2021


On 04/10/2021 18:11, Joel Sherrill wrote:
> Add a stack allocator hook specifically for allocation of IDLE thread stacks.
> This allows the user to decide if IDLE thread stacks are statically allocated
> or handled by the same custom allocator mechanism as other thread stacks.
> 
> Closes #4520.
> ---
>   cpukit/include/rtems/confdefs/percpu.h        | 20 +++-
>   cpukit/include/rtems/confdefs/wkspace.h       | 13 +++
>   cpukit/include/rtems/config.h                 |  3 +
>   cpukit/include/rtems/score/stack.h            | 24 +++++
>   cpukit/score/src/stackallocator.c             |  3 +
>   cpukit/score/src/threadcreateidle.c           | 18 +++-
>   testsuites/sptests/spstkalloc03/init.c        | 98 +++++++++++++++++++
>   .../sptests/spstkalloc03/spstkalloc03.doc     | 19 ++++
>   .../sptests/spstkalloc03/spstkalloc03.scn     |  2 +
>   9 files changed, 192 insertions(+), 8 deletions(-)
>   create mode 100644 testsuites/sptests/spstkalloc03/init.c
>   create mode 100644 testsuites/sptests/spstkalloc03/spstkalloc03.doc
>   create mode 100644 testsuites/sptests/spstkalloc03/spstkalloc03.scn
> 
> diff --git a/cpukit/include/rtems/confdefs/percpu.h b/cpukit/include/rtems/confdefs/percpu.h
> index f3a9a4f3e7..a6ba4fece0 100644
> --- a/cpukit/include/rtems/confdefs/percpu.h
> +++ b/cpukit/include/rtems/confdefs/percpu.h
> @@ -133,11 +133,21 @@ 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.
> + */
> +  char _Thread_Idle_stacks[
> +#ifdef CONFIGURE_TASK_STACK_ALLOCATOR_FOR_IDLE

Maybe name the option CONFIGURE_IDLE_TASK_STACK_ALLOCATOR similar to 
CONFIGURE_IDLE_TASK_STACK_SIZE, CONFIGURE_IDLE_TASK_BODY, and 
CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION.

> +    1

You don't need this, see below.

> +#else
> +    _CONFIGURE_MAXIMUM_PROCESSORS
> +      * ( CONFIGURE_IDLE_TASK_STACK_SIZE + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE )
> +#endif
> +  ] RTEMS_ALIGNED( CPU_INTERRUPT_STACK_ALIGNMENT )
> +  RTEMS_SECTION( ".rtemsstack.idle" );
>   
>   #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 484dde20ea..abe4cd50af 100644
> --- a/cpukit/include/rtems/confdefs/wkspace.h
> +++ b/cpukit/include/rtems/confdefs/wkspace.h
> @@ -132,12 +132,14 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
>   
>   #if defined(CONFIGURE_TASK_STACK_ALLOCATOR) \
>     && defined(CONFIGURE_TASK_STACK_DEALLOCATOR)
> +  /* 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_TASK_STACK_ALLOCATOR_INIT;
> @@ -145,11 +147,22 @@ const uintptr_t _Stack_Space_size = _CONFIGURE_STACK_SPACE_SIZE;
>       const Stack_Allocator_initialize _Stack_Allocator_initialize = NULL;
>     #endif
>   
> +  /* Custom allocator must include allocate and free */
>     const Stack_Allocator_allocate _Stack_Allocator_allocate =
>       CONFIGURE_TASK_STACK_ALLOCATOR;
>   
>     const Stack_Allocator_free _Stack_Allocator_free =
>       CONFIGURE_TASK_STACK_DEALLOCATOR;
> +
> +  /* Custom allocator MAY include allocate IDLE thread 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;
> +  #else
> +    const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
> +      NULL;

Use _Stack_Allocator_allocate_for_idle_default instead of NULL

> +  #endif
> +
>   #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"
> diff --git a/cpukit/include/rtems/config.h b/cpukit/include/rtems/config.h
> index e82c7abf11..a826581658 100644
> --- a/cpukit/include/rtems/config.h
> +++ b/cpukit/include/rtems/config.h
> @@ -129,6 +129,9 @@ uint32_t rtems_configuration_get_maximum_extensions( void );
>   #define rtems_configuration_get_stack_free_hook() \
>     (_Stack_Allocator_free)
>   
> +#define rtems_configuration_get_stack_allocate_for_idle_hook() \
> +  (_Stack_Allocator_allocate_for_idle)
> +
>    /**
>     * This macro assists in accessing the field which indicates whether
>     * RTEMS is responsible for zeroing the Executive Workspace.
> diff --git a/cpukit/include/rtems/score/stack.h b/cpukit/include/rtems/score/stack.h
> index df1df74867..9c60b4f15e 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 The 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.
>    *
> @@ -124,6 +141,13 @@ extern const Stack_Allocator_allocate _Stack_Allocator_allocate;
>   extern const Stack_Allocator_free _Stack_Allocator_free;
>   
>   /** @} */
> +/**
> + * @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/stackallocator.c b/cpukit/score/src/stackallocator.c
> index 404b98fa1c..fd06d382a2 100644
> --- a/cpukit/score/src/stackallocator.c
> +++ b/cpukit/score/src/stackallocator.c
> @@ -39,3 +39,6 @@ const Stack_Allocator_initialize _Stack_Allocator_initialize = NULL;
>   const Stack_Allocator_allocate _Stack_Allocator_allocate = _Workspace_Allocate;
>   
>   const Stack_Allocator_free _Stack_Allocator_free = _Workspace_Free;
> +
> +const Stack_Allocator_allocate_for_idle _Stack_Allocator_allocate_for_idle =
> +        NULL;
> diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
> index 1e18ad07cc..440f67f69b 100644
> --- a/cpukit/score/src/threadcreateidle.c
> +++ b/cpukit/score/src/threadcreateidle.c
> @@ -53,9 +53,21 @@ 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 mau be statically allocated or there may be a
> +   * custom allocator provided just as with user threads.
> +   */
> +  if ( _Stack_Allocator_allocate_for_idle == NULL ) {

Please remove this if, and replace it with a default implementation 
_Stack_Allocator_allocate_for_idle_default() which just contains the 
code block below.

> +    config.stack_area = &_Thread_Idle_stacks[
> +      _Per_CPU_Get_index( cpu ) * config.stack_size
> +    ];
> +  } else {
> +    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
[...]

-- 
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber at embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


More information about the devel mailing list