From 6942e5f99171d1cb38c2c573aba8cb9212d7efd8 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 9 Apr 2020 12:12:13 +0200 Subject: rtems: Add rtems_task_construct() In contrast to rtems_task_create() this function constructs a task with a user-provided task storage area. The new directive uses a configuration structure instead of individual parameters. 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_MINIMUM_TASKS_WITH_USER_PROVIDED_STORAGE to adjust RTEMS Workspace size estimate. Update #3959. --- cpukit/rtems/src/taskcreate.c | 282 +++++++++--------------------------------- 1 file changed, 57 insertions(+), 225 deletions(-) (limited to 'cpukit/rtems/src/taskcreate.c') diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c index 5486ac9b6e..917d931424 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) + * + * 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. * - * 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. + * 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,238 +38,51 @@ #endif #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -rtems_status_code rtems_task_create( - rtems_name name, - rtems_task_priority initial_priority, - size_t stack_size, - rtems_mode initial_modes, - rtems_attribute attribute_set, - rtems_id *id +static rtems_status_code _RTEMS_tasks_Allocate_and_prepare_stack( + Thread_Configuration *thread_config, + const rtems_task_config *config ) { - 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 ); - - 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 - ); - 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 ); + size_t size; - /* - * Initialize the core thread for this task. - */ + 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 ); - 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(); + if ( thread_config->stack_area == NULL ) { 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_status_code rtems_task_create( + rtems_name name, + rtems_task_priority initial_priority, + size_t stack_size, + rtems_mode initial_modes, + rtems_attribute attribute_set, + rtems_id *id ) { - RTEMS_API_Control *api; - - api = started->API_Extensions[ THREAD_API_RTEMS ]; - - _Event_Initialize( &api->Event ); - _Event_Initialize( &api->System_event ); -} + rtems_task_config config; -#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 ); + memset( &config, 0, sizeof( config ) ); + 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 + ); } - -RTEMS_SYSINIT_ITEM( - _RTEMS_tasks_Manager_initialization, - RTEMS_SYSINIT_CLASSIC_TASKS, - RTEMS_SYSINIT_ORDER_MIDDLE -); -- cgit v1.2.3