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. Add application configuration option CONFIGURE_TASKS_CREATED_FROM_CONFIG to adjust RTEMS Workspace size estimate. 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. v3: Add CONFIGURE_TASKS_CREATED_FROM_CONFIG. Fix RTEMS_TASK_STORAGE_SIZE() if CPU_ALL_TASKS_ARE_FP == TRUE. cpukit/Makefile.am | 1 + cpukit/doxygen/appl-config.h | 23 ++ cpukit/include/rtems/confdefs/threads.h | 8 + cpukit/include/rtems/confdefs/wkspace.h | 4 +- cpukit/include/rtems/rtems/tasks.h | 131 +++++++++++ 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 | 3 +- 11 files changed, 521 insertions(+), 237 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/doxygen/appl-config.h b/cpukit/doxygen/appl-config.h index cd4664f7c8..5813192fd5 100644 --- a/cpukit/doxygen/appl-config.h +++ b/cpukit/doxygen/appl-config.h @@ -864,6 +864,29 @@ */ #define CONFIGURE_MAXIMUM_USER_EXTENSIONS +/** + * @brief This configuration option is an integer define. + * + * The value of this configuration option defines the count of Classic API + * Tasks which are created by rtems_task_create_from_config(). + * + * @par Default Value + * The default value is 0. + * + * @par Value Constraints + * The value of this configuration option shall be greater than or equal to 0 + * and less than or equal to #CONFIGURE_MAXIMUM_TASKS. + * + * @par Notes + * By default, the calculation for the required memory in the RTEMS Workspace + * for tasks assumes that all Classic API Tasks are created by + * rtems_task_create(). This configuration option can be used to reduce the + * required memory for the system-provided task storage areas since tasks + * created by rtems_task_create_from_config() use a user-provided task storage + * area. + */ +#define CONFIGURE_TASKS_CREATED_FROM_CONFIG + /** @} */ /** diff --git a/cpukit/include/rtems/confdefs/threads.h b/cpukit/include/rtems/confdefs/threads.h index 33b8c5cee2..32d0c63d98 100644 --- a/cpukit/include/rtems/confdefs/threads.h +++ b/cpukit/include/rtems/confdefs/threads.h @@ -60,6 +60,14 @@ #define _CONFIGURE_TASKS ( CONFIGURE_MAXIMUM_TASKS + _CONFIGURE_LIBBLOCK_TASKS ) +#ifndef CONFIGURE_TASKS_CREATED_FROM_CONFIG + #define CONFIGURE_TASKS_CREATED_FROM_CONFIG 0 +#endif + +#if CONFIGURE_TASKS_CREATED_FROM_CONFIG > CONFIGURE_MAXIMUM_TASKS + #error "CONFIGURE_TASKS_CREATED_FROM_CONFIG shall be less than or equal to CONFIGURE_MAXIMUM_TASKS" +#endif + #ifndef CONFIGURE_MAXIMUM_POSIX_THREADS #define CONFIGURE_MAXIMUM_POSIX_THREADS 0 #endif diff --git a/cpukit/include/rtems/confdefs/wkspace.h b/cpukit/include/rtems/confdefs/wkspace.h index de476dbf82..215cdcb141 100644 --- a/cpukit/include/rtems/confdefs/wkspace.h +++ b/cpukit/include/rtems/confdefs/wkspace.h @@ -100,7 +100,9 @@ + _CONFIGURE_POSIX_INIT_THREAD_STACK_EXTRA \ + _CONFIGURE_LIBBLOCK_TASKS_STACK_EXTRA \ + CONFIGURE_EXTRA_TASK_STACKS \ - + rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) \ + + rtems_resource_maximum_per_allocation( \ + _CONFIGURE_TASKS - CONFIGURE_TASKS_CREATED_FROM_CONFIG \ + ) \ * _Configure_From_stackspace( CONFIGURE_MINIMUM_TASK_STACK_SIZE ) \ + rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS ) \ * _Configure_From_stackspace( CONFIGURE_MINIMUM_POSIX_THREAD_STACK_SIZE ) \ diff --git a/cpukit/include/rtems/rtems/tasks.h b/cpukit/include/rtems/rtems/tasks.h index 12c323e60e..513e3e9eaf 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,136 @@ 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. + * + * @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 + */ +#if CPU_ALL_TASKS_ARE_FP == TURE + #define RTEMS_TASK_STORAGE_SIZE( _size, _attributes ) \ + ( ( _size ) + CONTEXT_FP_SIZE ) +#else + #define RTEMS_TASK_STORAGE_SIZE( _size, _attributes ) \ + ( ( _size ) + ( ( ( _attributes ) & RTEMS_FLOATING_POINT ) != 0 ? \ + CONTEXT_FP_SIZE : 0 ) ) +#endif + +/** + * @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 ) + +/** + * @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 the floating-point context on architectures with a separate + * floating-point context. + * + * 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 creation 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 * ); + + /** + * @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. 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. + * + * 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_TASKS_CREATED_FROM_CONFIG + * application configuration option or a custom task stack allocator, see + * ::CONFIGURE_TASK_STACK_ALLOCATOR. + * + * @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 -); 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 ) +]; + +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..54eef464fb 100644 --- a/testsuites/sptests/sp01/sp01.doc +++ b/testsuites/sptests/sp01/sp01.doc @@ -10,6 +10,7 @@ test name: sp01 directives: rtems_task_create + rtems_task_create_from_config rtems_task_start rtems_task_wake_after rtems_clock_set diff --git a/testsuites/sptests/sp01/system.h b/testsuites/sptests/sp01/system.h index bde5328aa9..c6d5f2d347 100644 --- a/testsuites/sptests/sp01/system.h +++ b/testsuites/sptests/sp01/system.h @@ -28,8 +28,9 @@ 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 (3 * RTEMS_MINIMUM_STACK_SIZE) #define CONFIGURE_MAXIMUM_TASKS 4 +#define CONFIGURE_TASKS_CREATED_FROM_CONFIG 1 #include <rtems/confdefs.h> -- 2.26.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel