[PATCH v2] rtems: Add rtems_task_create_from_config()

Joel Sherrill joel at rtems.org
Tue Sep 8 22:43:44 UTC 2020


On Wed, Sep 2, 2020 at 11:09 AM Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:

> In contrast to rtems_task_create() this function creates a task with a
> user-provided task storage area.  The new create function uses a
> configuration structure instead of individual parameters.
>
> Add RTEMS_TASK_STORAGE_ALIGNMENT to define the recommended alignment of
> a task storage area.
>
> Add RTEMS_TASK_STORAGE_SIZE() to calculate the recommended size of a
> task storage area based on the task attributes and the size dedicated to
> the task stack and thread-local storage.  This macro may allow future
> extensions without breaking the API.
>
> Update #3959.
> ---
>
> v2:
>
> Rename function from rtems_task_build() to
> rtems_task_create_from_config().  Add RTEMS_TASK_STORAGE_ALIGNMENT and
> RTEMS_TASK_STORAGE_SIZE().  Improve documentation.
>
>  cpukit/Makefile.am                      |   1 +
>  cpukit/include/rtems/rtems/tasks.h      | 124 +++++++++++
>  cpukit/include/rtems/rtems/tasksimpl.h  |  11 +
>  cpukit/rtems/src/taskcreate.c           | 278 +++++-------------------
>  cpukit/rtems/src/taskcreatefromconfig.c | 274 +++++++++++++++++++++++
>  testsuites/sptests/sp01/init.c          |  24 +-
>  testsuites/sptests/sp01/sp01.doc        |   1 +
>  testsuites/sptests/sp01/system.h        |   2 +-
>  8 files changed, 479 insertions(+), 236 deletions(-)
>  create mode 100644 cpukit/rtems/src/taskcreatefromconfig.c
>
> diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
> index e5009e53c9..caa6a9efe6 100644
> --- a/cpukit/Makefile.am
> +++ b/cpukit/Makefile.am
> @@ -787,6 +787,7 @@ librtemscpu_a_SOURCES += rtems/src/statustoerrno.c
>  librtemscpu_a_SOURCES += rtems/src/systemeventreceive.c
>  librtemscpu_a_SOURCES += rtems/src/systemeventsend.c
>  librtemscpu_a_SOURCES += rtems/src/taskcreate.c
> +librtemscpu_a_SOURCES += rtems/src/taskcreatefromconfig.c
>  librtemscpu_a_SOURCES += rtems/src/taskdelete.c
>  librtemscpu_a_SOURCES += rtems/src/taskexit.c
>  librtemscpu_a_SOURCES += rtems/src/taskgetaffinity.c
> diff --git a/cpukit/include/rtems/rtems/tasks.h
> b/cpukit/include/rtems/rtems/tasks.h
> index 12c323e60e..a183dcafed 100644
> --- a/cpukit/include/rtems/rtems/tasks.h
> +++ b/cpukit/include/rtems/rtems/tasks.h
> @@ -21,6 +21,7 @@
>  #include <rtems/rtems/attr.h>
>  #include <rtems/rtems/status.h>
>  #include <rtems/rtems/types.h>
> +#include <rtems/score/context.h>
>  #include <rtems/score/smp.h>
>
>  #ifdef __cplusplus
> @@ -164,6 +165,129 @@ rtems_status_code rtems_task_create(
>    rtems_id            *id
>  );
>
> +/**
> + * @brief Returns the recommended task storage area size for the
> specified size
> + *   and task attributes.
> + *
> + * @param _size is the size dedicated to the task stack and thread-local
> + *   storage.
>

How does the user get the TLS size?

Need advice on that. Seems hard to get at compile time since it is a link
time aggregation.


> + *
> + * @param _attributes is the attribute set of the task using the storage
> area.
> + *
> + * @return The recommended task storage area size is returned calculated
> from
> + *   the input parameters.
> + *
> + * @see rtems_task_config
> + */
> +#define RTEMS_TASK_STORAGE_SIZE( _size, _attributes ) \
> +  ( ( _size ) + \
> +    ( ( ( _attributes ) & RTEMS_FLOATING_POINT ) != 0 ? CONTEXT_FP_SIZE :
> 0 ) )
>

If the architecture requires all threads to be FP, I don't think this will
work.


> +
> +/**
> + * @brief This variable attribute defines the recommended alignment of a
> task
> + *   storage area.
> + *
> + * @see rtems_task_config
> + */
> +#define RTEMS_TASK_STORAGE_ALIGNMENT RTEMS_ALIGNED( CPU_STACK_ALIGNMENT )
>
> Good. I assume the stack comes off the lower address range. Will
the TLS and FP areas have sufficient alignment? Is that accounted for?

I can't speak to generic TLS alignment but seems like cache alignment
is what the linker script would aim for.

FP context may have to be double aligned on many architectures.


> +/**
> + * @brief This structure defines the configuration of a task created by
> + *   rtems_task_create_from_config().
> + */
> +typedef struct {
> +  /**
> +   * @brief This member defines the name of the task.
> +   */
> +  rtems_name name;
> +
> +  /**
> +   * @brief This member defines initial priority of the task.
> +   */
> +  rtems_task_priority initial_priority;
> +
> +  /**
> +   * @brief This member shall point to the task storage area begin.
> +   *
> +   * The task storage area will contain the task stack, the thread-local
> +   * storage, and, on some architectures, the floating-point context.
>

What does this mean? I think most architectures treat the areas as
separate (FP not in integer context) and some require all tasks to be
FP. This seems inaccurate.


> +   *
> +   * There are no alignment requirements for the task storage area.  To
> avoid
> +   * memory waste, use the ::RTEMS_TASK_STORAGE_ALIGNMENT variable
> attribute to
> +   * enforce the recommended alignment of the task storage area.
> +   */
> +  void *storage_area;
> +
> +  /**
> +   * @brief This member defines size of the task storage area in bytes.
> +   *
> +   * Use the RTEMS_TASK_STORAGE_SIZE() macro to determine the recommended
> task
> +   * storage area size.
> +   */
> +  size_t storage_size;
> +
> +  /**
> +   * @brief This member defines the optional handler to free the task
> storage
> +   *   area.
> +   *
> +   * It is called when the task building aborts due to a failed task
> create
> +   * extension or the task is deleted.  It is called from task context
> under
> +   * protection of the object allocator lock.  It is allowed to call
> free() in
> +   * this handler.  The handler may be NULL.
> +   */
> +  void ( *storage_free )( void * );
>

Is it not called when the thread is deleted?


> +
> +  /**
> +   * @brief This member defines the initial modes of the task.
> +   */
> +  rtems_mode initial_modes;
> +
> +  /**
> +   * @brief This member defines the attributes of the task.
> +   */
> +  rtems_attribute attributes;
> +} rtems_task_config;
> +
> +/**
> + * @brief Creates a task according to the specified configuration.
> + *
> + * In contrast to tasks created by rtems_task_create(), the tasks created
> by
> + * this directive use a user-provided task storage area (contains the task
> + * stack).
>

Drop () and say which contains the task stack.


> + *
> + * It is not recommended to mix rtems_task_create() and
> + * rtems_task_create_from_config() in an application.  This directive is
> + * intended for applications which do not want to use the RTEMS Workspace
> and
> + * instead statically allocate all operating system resources.  The stack
> space
> + * estimate done by <rtems/confdefs.h> assumes that all tasks are created
> by
> + * rtems_task_create().  The estimate can be adjusted to take
> user-provided task
> + * storage areas into account through the ::CONFIGURE_MEMORY_OVERHEAD
> + * application configuration option or a custom task stack allocator, see
> + * ::CONFIGURE_TASK_STACK_ALLOCATOR.
>

CONFIGURE_MEMORY_OVERHEAD would have to be a negative number to
make this work. Is this explained or is there some magic I am missing?

CONFIGURE_MEMORY_OVERHEAD is intended as a backdoor if the
confdefs.h memory calculation is too low. It is not intended for general
use like this.

I would rather see something like "configure build tasks" and just subtract
that from maximum threads before multiplying by minimum stack size.
This avoids the user having to add up all their statically allocated stack
sizes.


> + *
> + * @param config is the task configuration.
> + *
> + * @param[out] id is the pointer to an object identifier variable.  The
> object
> + *   identifier of the created task will be stored in this variable, in
> case of
> + *   a successful operation.
> + *
> + * @retval RTEMS_SUCCESSFUL Successful operation.
> + *
> + * @retval RTEMS_INVALID_ADDRESS The id parameter is @c NULL.
> + *
> + * @retval RTEMS_INVALID_NAME The task name is invalid.
> + *
> + * @retval RTEMS_INVALID_PRIORITY The initial priority of the task is
> invalid.
> + *
> + * @retval RTEMS_TOO_MANY No task is available.
> + *
> + * @retval RTEMS_UNSATISFIED A task create extension failed.
> + */
> +rtems_status_code rtems_task_create_from_config(
> +  const rtems_task_config *config,
> +  rtems_id                *id
> +);
> +
>  /**
>   * @brief RTEMS Task Name to Id
>   *
> diff --git a/cpukit/include/rtems/rtems/tasksimpl.h
> b/cpukit/include/rtems/rtems/tasksimpl.h
> index c9544f8c27..a39113a283 100644
> --- a/cpukit/include/rtems/rtems/tasksimpl.h
> +++ b/cpukit/include/rtems/rtems/tasksimpl.h
> @@ -42,6 +42,17 @@ extern "C" {
>   */
>  void _RTEMS_tasks_Initialize_user_tasks( void );
>
> +typedef void ( *RTEMS_tasks_Prepare_stack )(
> +  Thread_Configuration *,
> +  const rtems_task_config *
> +);
> +
> +rtems_status_code _RTEMS_tasks_Create(
> +  const rtems_task_config   *config,
> +  rtems_id                  *id,
> +  RTEMS_tasks_Prepare_stack  prepare_stack
> +);
> +
>  RTEMS_INLINE_ROUTINE Thread_Control *_RTEMS_tasks_Allocate(void)
>  {
>    _Objects_Allocator_lock();
> diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c
> index 5486ac9b6e..1d9a4546e8 100644
> --- a/cpukit/rtems/src/taskcreate.c
> +++ b/cpukit/rtems/src/taskcreate.c
> @@ -1,17 +1,36 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
>  /**
> - *  @file
> + * @file
> + *
> + * @ingroup ClassicTasks
>   *
> - *  @brief RTEMS Task Create
> - *  @ingroup ClassicTasks
> + * @brief RTEMS Task Create
>   */
>
>  /*
> - *  COPYRIGHT (c) 1989-2014,2016.
> - *  On-Line Applications Research Corporation (OAR).
> + * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de
> )
>   *
> - *  The license and distribution terms for this file may be
> - *  found in the file LICENSE in this distribution or at
> - *  http://www.rtems.org/license/LICENSE.
> + * 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
> @@ -19,20 +38,24 @@
>  #endif
>
>  #include <rtems/rtems/tasksimpl.h>
> -#include <rtems/rtems/attrimpl.h>
> -#include <rtems/rtems/eventimpl.h>
> -#include <rtems/rtems/modesimpl.h>
> -#include <rtems/rtems/support.h>
> -#include <rtems/score/apimutex.h>
> -#include <rtems/score/schedulerimpl.h>
>  #include <rtems/score/stackimpl.h>
> -#include <rtems/score/sysstate.h>
> -#include <rtems/score/threadimpl.h>
> -#include <rtems/score/userextimpl.h>
> -#include <rtems/sysinit.h>
>
>  #include <string.h>
>
> +static void _RTEMS_tasks_Allocate_and_prepare_stack(
> +  Thread_Configuration    *thread_config,
> +  const rtems_task_config *config
> +)
> +{
> +  size_t size;
> +
> +  thread_config->stack_free = _Stack_Free;
> +  size = _Stack_Ensure_minimum( config->storage_size );
> +  size = _Stack_Extend_size( size, thread_config->is_fp );
> +  thread_config->stack_size = size;
> +  thread_config->stack_area = _Stack_Allocate( size );
> +}
> +
>  rtems_status_code rtems_task_create(
>    rtems_name           name,
>    rtems_task_priority  initial_priority,
> @@ -42,215 +65,18 @@ rtems_status_code rtems_task_create(
>    rtems_id            *id
>  )
>  {
> -  Thread_Control          *the_thread;
> -  Thread_Configuration     config;
> -#if defined(RTEMS_MULTIPROCESSING)
> -  Objects_MP_Control      *the_global_object = NULL;
> -  bool                     is_global;
> -#endif
> -  bool                     status;
> -  rtems_attribute          the_attribute_set;
> -  bool                     valid;
> -  RTEMS_API_Control       *api;
> -  ASR_Information         *asr;
> -
> -  if ( !id )
> -   return RTEMS_INVALID_ADDRESS;
> -
> -  if ( !rtems_is_name_valid( name ) )
> -    return RTEMS_INVALID_NAME;
> -
> -  /*
> -   *  Core Thread Initialize insures we get the minimum amount of
> -   *  stack space.
> -   */
> -
> -  /*
> -   *  Fix the attribute set to match the attributes which
> -   *  this processor (1) requires and (2) is able to support.
> -   *  First add in the required flags for attribute_set
> -   *  Typically this might include FP if the platform
> -   *  or application required all tasks to be fp aware.
> -   *  Then turn off the requested bits which are not supported.
> -   */
> -
> -  the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED
> );
> -  the_attribute_set =
> -    _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );
> +  rtems_task_config config;
>
>    memset( &config, 0, sizeof( config ) );
> -  config.budget_algorithm = _Modes_Is_timeslice( initial_modes ) ?
> -    THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE
> -      : THREAD_CPU_BUDGET_ALGORITHM_NONE,
> -  config.isr_level =  _Modes_Get_interrupt_level( initial_modes );
> -  config.name.name_u32 = name;
> -  config.is_fp = _Attributes_Is_floating_point( the_attribute_set );
> -  config.is_preemptible = _Modes_Is_preempt( initial_modes );
> -  config.stack_size = _Stack_Ensure_minimum( stack_size );
> -  config.stack_size = _Stack_Extend_size( config.stack_size, config.is_fp
> );
> -
> -  /*
> -   *  Validate the RTEMS API priority and convert it to the core priority
> range.
> -   */
> -
> -  if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
> -    if ( initial_priority == PRIORITY_MINIMUM ) {
> -      return RTEMS_INVALID_PRIORITY;
> -    }
> -  }
> -
> -  config.scheduler = _Thread_Scheduler_get_home( _Thread_Get_executing()
> );
> -
> -  config.priority = _RTEMS_Priority_To_core(
> -    config.scheduler,
> -    initial_priority,
> -    &valid
> +  config.name = name;
> +  config.initial_priority = initial_priority;
> +  config.storage_size = stack_size;
> +  config.initial_modes = initial_modes;
> +  config.attributes = attribute_set;
> +
> +  return _RTEMS_tasks_Create(
> +    &config,
> +    id,
> +    _RTEMS_tasks_Allocate_and_prepare_stack
>    );
> -  if ( !valid ) {
> -    return RTEMS_INVALID_PRIORITY;
> -  }
> -
> -#if defined(RTEMS_MULTIPROCESSING)
> -  if ( !_System_state_Is_multiprocessing ) {
> -    the_attribute_set = _Attributes_Clear( the_attribute_set,
> RTEMS_GLOBAL );
> -  }
> -
> -  is_global = _Attributes_Is_global( the_attribute_set );
> -#endif
> -
> -  /*
> -   *  Allocate the thread control block and -- if the task is global --
> -   *  allocate a global object control block.
> -   *
> -   *  NOTE:  This routine does not use the combined allocate and open
> -   *         global object routine (_Objects_MP_Allocate_and_open) because
> -   *         this results in a lack of control over when memory is
> allocated
> -   *         and can be freed in the event of an error.
> -   */
> -  the_thread = _RTEMS_tasks_Allocate();
> -
> -  if ( !the_thread ) {
> -    _Objects_Allocator_unlock();
> -    return RTEMS_TOO_MANY;
> -  }
> -
> -#if defined(RTEMS_MULTIPROCESSING)
> -  if ( is_global ) {
> -    the_global_object = _Objects_MP_Allocate_global_object();
> -
> -    if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
> -      _RTEMS_tasks_Free( the_thread );
> -      _Objects_Allocator_unlock();
> -      return RTEMS_TOO_MANY;
> -    }
> -  }
> -#endif
> -
> -  config.stack_free = _Stack_Free;
> -  config.stack_area = _Stack_Allocate( config.stack_size );
> -  status = ( config.stack_area != NULL );
> -
> -  /*
> -   *  Initialize the core thread for this task.
> -   */
> -
> -  if ( status ) {
> -    status = _Thread_Initialize(
> -      &_RTEMS_tasks_Information,
> -      the_thread,
> -      &config
> -    );
> -  }
> -
> -  if ( !status ) {
> -#if defined(RTEMS_MULTIPROCESSING)
> -    if ( is_global )
> -      _Objects_MP_Free_global_object( the_global_object );
> -#endif
> -    _RTEMS_tasks_Free( the_thread );
> -    _Objects_Allocator_unlock();
> -    return RTEMS_UNSATISFIED;
> -  }
> -
> -  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
> -  asr = &api->Signal;
> -
> -  asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true;
> -
> -  *id = the_thread->Object.id;
> -
> -#if defined(RTEMS_MULTIPROCESSING)
> -  the_thread->is_global = is_global;
> -  if ( is_global ) {
> -
> -    _Objects_MP_Open(
> -      &_RTEMS_tasks_Information.Objects,
> -      the_global_object,
> -      name,
> -      the_thread->Object.id
> -    );
> -
> -    _RTEMS_tasks_MP_Send_process_packet(
> -      RTEMS_TASKS_MP_ANNOUNCE_CREATE,
> -      the_thread->Object.id,
> -      name
> -    );
> -
> -   }
> -#endif
> -
> -  _Objects_Allocator_unlock();
> -  return RTEMS_SUCCESSFUL;
> -}
> -
> -static void _RTEMS_tasks_Start_extension(
> -  Thread_Control *executing,
> -  Thread_Control *started
> -)
> -{
> -  RTEMS_API_Control *api;
> -
> -  api = started->API_Extensions[ THREAD_API_RTEMS ];
> -
> -  _Event_Initialize( &api->Event );
> -  _Event_Initialize( &api->System_event );
> -}
> -
> -#if defined(RTEMS_MULTIPROCESSING)
> -static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )
> -{
> -  if ( executing->is_global ) {
> -    _Objects_MP_Close(
> -      &_RTEMS_tasks_Information.Objects,
> -      executing->Object.id
> -    );
> -    _RTEMS_tasks_MP_Send_process_packet(
> -      RTEMS_TASKS_MP_ANNOUNCE_DELETE,
> -      executing->Object.id,
> -      0                                /* Not used */
> -    );
> -  }
>  }
> -#endif
> -
> -static User_extensions_Control _RTEMS_tasks_User_extensions = {
> -  .Callouts = {
> -#if defined(RTEMS_MULTIPROCESSING)
> -    .thread_terminate = _RTEMS_tasks_Terminate_extension,
> -#endif
> -    .thread_start     = _RTEMS_tasks_Start_extension,
> -    .thread_restart   = _RTEMS_tasks_Start_extension
> -  }
> -};
> -
> -static void _RTEMS_tasks_Manager_initialization( void )
> -{
> -  _Thread_Initialize_information( &_RTEMS_tasks_Information );
> -  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
> -}
> -
> -RTEMS_SYSINIT_ITEM(
> -  _RTEMS_tasks_Manager_initialization,
> -  RTEMS_SYSINIT_CLASSIC_TASKS,
> -  RTEMS_SYSINIT_ORDER_MIDDLE
> -);
>

Is all of this just turning rtems_task_create into a wrapper for the task
create from config?


> diff --git a/cpukit/rtems/src/taskcreatefromconfig.c
> b/cpukit/rtems/src/taskcreatefromconfig.c
> new file mode 100644
> index 0000000000..952d3a3a3c
> --- /dev/null
> +++ b/cpukit/rtems/src/taskcreatefromconfig.c
> @@ -0,0 +1,274 @@
> +/**
> + * @file
> + *
> + * @ingroup ClassicTasks
> + *
> + * @brief RTEMS Task Create from Config
> + */
> +
> +/*
> + *  COPYRIGHT (c) 1989-2014,2016.
> + *  On-Line Applications Research Corporation (OAR).
> + *
> + *  The license and distribution terms for this file may be
> + *  found in the file LICENSE in this distribution or at
> + *  http://www.rtems.org/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <rtems/rtems/tasksimpl.h>
> +#include <rtems/rtems/attrimpl.h>
> +#include <rtems/rtems/eventimpl.h>
> +#include <rtems/rtems/modesimpl.h>
> +#include <rtems/rtems/support.h>
> +#include <rtems/score/apimutex.h>
> +#include <rtems/score/schedulerimpl.h>
> +#include <rtems/score/stackimpl.h>
> +#include <rtems/score/sysstate.h>
> +#include <rtems/score/threadimpl.h>
> +#include <rtems/score/userextimpl.h>
> +#include <rtems/sysinit.h>
> +
> +#include <string.h>
> +
> +static void _RTEMS_tasks_Prepare_user_stack(
> +  Thread_Configuration    *thread_config,
> +  const rtems_task_config *config
> +)
> +{
> +  thread_config->stack_size = config->storage_size;
> +  thread_config->stack_area = config->storage_area;
> +
> +  if ( config->storage_free != NULL ) {
> +    thread_config->stack_free = config->storage_free;
> +  } else {
> +    thread_config->stack_free = _Stack_Free_nothing;
> +  }
> +}
> +
> +rtems_status_code rtems_task_create_from_config(
> +  const rtems_task_config *config,
> +  rtems_id                *id
> +)
> +{
> +  return _RTEMS_tasks_Create( config, id, _RTEMS_tasks_Prepare_user_stack
> );
> +}
> +
> +rtems_status_code _RTEMS_tasks_Create(
> +  const rtems_task_config   *config,
> +  rtems_id                  *id,
> +  RTEMS_tasks_Prepare_stack  prepare_stack
> +)
> +{
> +  Thread_Control          *the_thread;
> +  Thread_Configuration     thread_config;
> +#if defined(RTEMS_MULTIPROCESSING)
> +  Objects_MP_Control      *the_global_object = NULL;
> +  bool                     is_global;
> +#endif
> +  bool                     status;
> +  rtems_attribute          attributes;
> +  bool                     valid;
> +  RTEMS_API_Control       *api;
> +  ASR_Information         *asr;
> +
> +  if ( !id )
> +   return RTEMS_INVALID_ADDRESS;
> +
> +  if ( !rtems_is_name_valid( config->name ) )
> +    return RTEMS_INVALID_NAME;
> +
> +  /*
> +   *  Core Thread Initialize insures we get the minimum amount of
> +   *  stack space.
> +   */
> +
> +  /*
> +   *  Fix the attribute set to match the attributes which
> +   *  this processor (1) requires and (2) is able to support.
> +   *  First add in the required flags for attributes
> +   *  Typically this might include FP if the platform
> +   *  or application required all tasks to be fp aware.
> +   *  Then turn off the requested bits which are not supported.
> +   */
> +
> +  attributes = _Attributes_Set( config->attributes, ATTRIBUTES_REQUIRED );
> +  attributes = _Attributes_Clear( attributes, ATTRIBUTES_NOT_SUPPORTED );
> +
> +  memset( &thread_config, 0, sizeof( thread_config ) );
> +  thread_config.budget_algorithm = _Modes_Is_timeslice(
> config->initial_modes ) ?
> +    THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE
> +      : THREAD_CPU_BUDGET_ALGORITHM_NONE,
> +  thread_config.isr_level =  _Modes_Get_interrupt_level(
> config->initial_modes );
> +  thread_config.name.name_u32 = config->name;
> +  thread_config.is_fp = _Attributes_Is_floating_point( attributes );
> +  thread_config.is_preemptible = _Modes_Is_preempt( config->initial_modes
> );
> +
> +  /*
> +   *  Validate the RTEMS API priority and convert it to the core priority
> range.
> +   */
> +
> +  if ( !_Attributes_Is_system_task( attributes ) ) {
> +    if ( config->initial_priority == PRIORITY_MINIMUM ) {
> +      return RTEMS_INVALID_PRIORITY;
> +    }
> +  }
> +
> +  thread_config.scheduler =
> +    _Thread_Scheduler_get_home( _Thread_Get_executing() );
> +
> +  thread_config.priority = _RTEMS_Priority_To_core(
> +    thread_config.scheduler,
> +    config->initial_priority,
> +    &valid
> +  );
> +  if ( !valid ) {
> +    return RTEMS_INVALID_PRIORITY;
> +  }
> +
> +#if defined(RTEMS_MULTIPROCESSING)
> +  if ( !_System_state_Is_multiprocessing ) {
> +    attributes = _Attributes_Clear( attributes, RTEMS_GLOBAL );
> +  }
> +
> +  is_global = _Attributes_Is_global( attributes );
> +#endif
> +
> +  /*
> +   *  Allocate the thread control block and -- if the task is global --
> +   *  allocate a global object control block.
> +   *
> +   *  NOTE:  This routine does not use the combined allocate and open
> +   *         global object routine (_Objects_MP_Allocate_and_open) because
> +   *         this results in a lack of control over when memory is
> allocated
> +   *         and can be freed in the event of an error.
> +   */
> +  the_thread = _RTEMS_tasks_Allocate();
> +
> +  if ( !the_thread ) {
> +    _Objects_Allocator_unlock();
> +    return RTEMS_TOO_MANY;
> +  }
> +
> +#if defined(RTEMS_MULTIPROCESSING)
> +  if ( is_global ) {
> +    the_global_object = _Objects_MP_Allocate_global_object();
> +
> +    if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
> +      _RTEMS_tasks_Free( the_thread );
> +      _Objects_Allocator_unlock();
> +      return RTEMS_TOO_MANY;
> +    }
> +  }
> +#endif
> +
> +  ( *prepare_stack )( &thread_config, config );
> +  status = ( thread_config.stack_area != NULL );
> +
> +  /*
> +   *  Initialize the core thread for this task.
> +   */
> +
> +  if ( status ) {
> +    status = _Thread_Initialize(
> +      &_RTEMS_tasks_Information,
> +      the_thread,
> +      &thread_config
> +    );
> +  }
> +
> +  if ( !status ) {
> +#if defined(RTEMS_MULTIPROCESSING)
> +    if ( is_global )
> +      _Objects_MP_Free_global_object( the_global_object );
> +#endif
> +    _RTEMS_tasks_Free( the_thread );
> +    _Objects_Allocator_unlock();
> +    return RTEMS_UNSATISFIED;
> +  }
> +
> +  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
> +  asr = &api->Signal;
> +
> +  asr->is_enabled = !_Modes_Is_asr_disabled( config->initial_modes );
> +
> +  *id = the_thread->Object.id;
> +
> +#if defined(RTEMS_MULTIPROCESSING)
> +  the_thread->is_global = is_global;
> +  if ( is_global ) {
> +
> +    _Objects_MP_Open(
> +      &_RTEMS_tasks_Information.Objects,
> +      the_global_object,
> +      config->name,
> +      the_thread->Object.id
> +    );
> +
> +    _RTEMS_tasks_MP_Send_process_packet(
> +      RTEMS_TASKS_MP_ANNOUNCE_CREATE,
> +      the_thread->Object.id,
> +      config->name
> +    );
> +
> +   }
> +#endif
> +
> +  _Objects_Allocator_unlock();
> +  return RTEMS_SUCCESSFUL;
> +}
> +
> +static void _RTEMS_tasks_Start_extension(
> +  Thread_Control *executing,
> +  Thread_Control *started
> +)
> +{
> +  RTEMS_API_Control *api;
> +
> +  api = started->API_Extensions[ THREAD_API_RTEMS ];
> +
> +  _Event_Initialize( &api->Event );
> +  _Event_Initialize( &api->System_event );
> +}
> +
> +#if defined(RTEMS_MULTIPROCESSING)
> +static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )
> +{
> +  if ( executing->is_global ) {
> +    _Objects_MP_Close(
> +      &_RTEMS_tasks_Information.Objects,
> +      executing->Object.id
> +    );
> +    _RTEMS_tasks_MP_Send_process_packet(
> +      RTEMS_TASKS_MP_ANNOUNCE_DELETE,
> +      executing->Object.id,
> +      0                                /* Not used */
> +    );
> +  }
> +}
> +#endif
> +
> +static User_extensions_Control _RTEMS_tasks_User_extensions = {
> +  .Callouts = {
> +#if defined(RTEMS_MULTIPROCESSING)
> +    .thread_terminate = _RTEMS_tasks_Terminate_extension,
> +#endif
> +    .thread_start     = _RTEMS_tasks_Start_extension,
> +    .thread_restart   = _RTEMS_tasks_Start_extension
> +  }
> +};
> +
> +static void _RTEMS_tasks_Manager_initialization( void )
> +{
> +  _Thread_Initialize_information( &_RTEMS_tasks_Information );
> +  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
> +}
> +
> +RTEMS_SYSINIT_ITEM(
> +  _RTEMS_tasks_Manager_initialization,
> +  RTEMS_SYSINIT_CLASSIC_TASKS,
> +  RTEMS_SYSINIT_ORDER_MIDDLE
> +);
> diff --git a/testsuites/sptests/sp01/init.c
> b/testsuites/sptests/sp01/init.c
> index 2719c84fc8..a0a332987d 100644
> --- a/testsuites/sptests/sp01/init.c
> +++ b/testsuites/sptests/sp01/init.c
> @@ -16,6 +16,19 @@
>
>  const char rtems_test_name[] = "SP 1";
>
> +RTEMS_TASK_STORAGE_ALIGNMENT static char Task_1_storage[
> +  RTEMS_TASK_STORAGE_SIZE( 2 * RTEMS_MINIMUM_STACK_SIZE,
> RTEMS_FLOATING_POINT )
>

This line appears to be too long.


> +];
> +
> +static const rtems_task_config Task_1_config = {
> +  .name = rtems_build_name( 'T', 'A', '1', ' ' ),
> +  .initial_priority = 1,
> +  .storage_area = Task_1_storage,
> +  .storage_size = sizeof( Task_1_storage ),
> +  .initial_modes = RTEMS_DEFAULT_MODES,
> +  .attributes = RTEMS_FLOATING_POINT
> +};
> +
>  rtems_task Init(
>    rtems_task_argument argument
>  )
> @@ -30,15 +43,8 @@ rtems_task Init(
>    status = rtems_clock_set( &time );
>    directive_failed( status, "rtems_clock_set" );
>
> -  status = rtems_task_create(
> -    rtems_build_name( 'T', 'A', '1', ' ' ),
> -    1,
> -    RTEMS_MINIMUM_STACK_SIZE * 2,
> -    RTEMS_DEFAULT_MODES,
> -    RTEMS_DEFAULT_ATTRIBUTES,
> -    &id
> -  );
> -  directive_failed( status, "rtems_task_create of TA1" );
> +  status = rtems_task_create_from_config( &Task_1_config, &id );
> +  directive_failed( status, "rtems_task_create_from_config of TA1" );
>
>    status = rtems_task_start( id, Task_1_through_3, 1 );
>    directive_failed( status, "rtems_task_start of TA1" );
> diff --git a/testsuites/sptests/sp01/sp01.doc
> b/testsuites/sptests/sp01/sp01.doc
> index d7d9f5d902..62bbe956d3 100644
> --- a/testsuites/sptests/sp01/sp01.doc
> +++ b/testsuites/sptests/sp01/sp01.doc
> @@ -9,6 +9,7 @@
>  test name:  sp01
>
>  directives:
> +  rtems_task_build
>    rtems_task_create
>    rtems_task_start
>    rtems_task_wake_after
> diff --git a/testsuites/sptests/sp01/system.h
> b/testsuites/sptests/sp01/system.h
> index bde5328aa9..e2047b4d3a 100644
> --- a/testsuites/sptests/sp01/system.h
> +++ b/testsuites/sptests/sp01/system.h
> @@ -28,7 +28,7 @@ rtems_task Task_1_through_3(
>
>  #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
>
> -#define CONFIGURE_EXTRA_TASK_STACKS         (4 * RTEMS_MINIMUM_STACK_SIZE)
> +#define CONFIGURE_EXTRA_TASK_STACKS         (2 * RTEMS_MINIMUM_STACK_SIZE)
>  #define CONFIGURE_MAXIMUM_TASKS             4
>

This seems to be missing lowering the computation for number of
minimum stacks reserved

--joel


>
>  #include <rtems/confdefs.h>
> --
> 2.26.2
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20200908/61ed3aa6/attachment-0001.html>


More information about the devel mailing list