<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Sep 2, 2020 at 11:09 AM Sebastian Huber <<a href="mailto:sebastian.huber@embedded-brains.de">sebastian.huber@embedded-brains.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">In contrast to rtems_task_create() this function creates a task with a<br>
user-provided task storage area. The new create function uses a<br>
configuration structure instead of individual parameters.<br>
<br>
Add RTEMS_TASK_STORAGE_ALIGNMENT to define the recommended alignment of<br>
a task storage area.<br>
<br>
Add RTEMS_TASK_STORAGE_SIZE() to calculate the recommended size of a<br>
task storage area based on the task attributes and the size dedicated to<br>
the task stack and thread-local storage. This macro may allow future<br>
extensions without breaking the API.<br>
<br>
Update #3959.<br>
---<br>
<br>
v2:<br>
<br>
Rename function from rtems_task_build() to<br>
rtems_task_create_from_config(). Add RTEMS_TASK_STORAGE_ALIGNMENT and<br>
RTEMS_TASK_STORAGE_SIZE(). Improve documentation.<br>
<br>
cpukit/Makefile.am | 1 +<br>
cpukit/include/rtems/rtems/tasks.h | 124 +++++++++++<br>
cpukit/include/rtems/rtems/tasksimpl.h | 11 +<br>
cpukit/rtems/src/taskcreate.c | 278 +++++-------------------<br>
cpukit/rtems/src/taskcreatefromconfig.c | 274 +++++++++++++++++++++++<br>
testsuites/sptests/sp01/init.c | 24 +-<br>
testsuites/sptests/sp01/sp01.doc | 1 +<br>
testsuites/sptests/sp01/system.h | 2 +-<br>
8 files changed, 479 insertions(+), 236 deletions(-)<br>
create mode 100644 cpukit/rtems/src/taskcreatefromconfig.c<br>
<br>
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am<br>
index e5009e53c9..caa6a9efe6 100644<br>
--- a/cpukit/Makefile.am<br>
+++ b/cpukit/Makefile.am<br>
@@ -787,6 +787,7 @@ librtemscpu_a_SOURCES += rtems/src/statustoerrno.c<br>
librtemscpu_a_SOURCES += rtems/src/systemeventreceive.c<br>
librtemscpu_a_SOURCES += rtems/src/systemeventsend.c<br>
librtemscpu_a_SOURCES += rtems/src/taskcreate.c<br>
+librtemscpu_a_SOURCES += rtems/src/taskcreatefromconfig.c<br>
librtemscpu_a_SOURCES += rtems/src/taskdelete.c<br>
librtemscpu_a_SOURCES += rtems/src/taskexit.c<br>
librtemscpu_a_SOURCES += rtems/src/taskgetaffinity.c<br>
diff --git a/cpukit/include/rtems/rtems/tasks.h b/cpukit/include/rtems/rtems/tasks.h<br>
index 12c323e60e..a183dcafed 100644<br>
--- a/cpukit/include/rtems/rtems/tasks.h<br>
+++ b/cpukit/include/rtems/rtems/tasks.h<br>
@@ -21,6 +21,7 @@<br>
#include <rtems/rtems/attr.h><br>
#include <rtems/rtems/status.h><br>
#include <rtems/rtems/types.h><br>
+#include <rtems/score/context.h><br>
#include <rtems/score/smp.h><br>
<br>
#ifdef __cplusplus<br>
@@ -164,6 +165,129 @@ rtems_status_code rtems_task_create(<br>
rtems_id *id<br>
);<br>
<br>
+/**<br>
+ * @brief Returns the recommended task storage area size for the specified size<br>
+ * and task attributes.<br>
+ *<br>
+ * @param _size is the size dedicated to the task stack and thread-local<br>
+ * storage.<br></blockquote><div><br></div><div>How does the user get the TLS size? </div><div><br></div><div>Need advice on that. Seems hard to get at compile time since it is a link</div><div>time aggregation. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ *<br>
+ * @param _attributes is the attribute set of the task using the storage area.<br>
+ *<br>
+ * @return The recommended task storage area size is returned calculated from<br>
+ * the input parameters.<br>
+ *<br>
+ * @see rtems_task_config<br>
+ */<br>
+#define RTEMS_TASK_STORAGE_SIZE( _size, _attributes ) \<br>
+ ( ( _size ) + \<br>
+ ( ( ( _attributes ) & RTEMS_FLOATING_POINT ) != 0 ? CONTEXT_FP_SIZE : 0 ) )<br></blockquote><div><br></div><div>If the architecture requires all threads to be FP, I don't think this will work.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+/**<br>
+ * @brief This variable attribute defines the recommended alignment of a task<br>
+ * storage area.<br>
+ *<br>
+ * @see rtems_task_config<br>
+ */<br>
+#define RTEMS_TASK_STORAGE_ALIGNMENT RTEMS_ALIGNED( CPU_STACK_ALIGNMENT )<br>
<br></blockquote><div>Good. I assume the stack comes off the lower address range. Will </div><div>the TLS and FP areas have sufficient alignment? Is that accounted for?</div><div><br></div><div>I can't speak to generic TLS alignment but seems like cache alignment </div><div>is what the linker script would aim for.</div><div><br></div><div>FP context may have to be double aligned on many architectures.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+/**<br>
+ * @brief This structure defines the configuration of a task created by<br>
+ * rtems_task_create_from_config().<br>
+ */<br>
+typedef struct {<br>
+ /**<br>
+ * @brief This member defines the name of the task.<br>
+ */<br>
+ rtems_name name;<br>
+<br>
+ /**<br>
+ * @brief This member defines initial priority of the task.<br>
+ */<br>
+ rtems_task_priority initial_priority;<br>
+<br>
+ /**<br>
+ * @brief This member shall point to the task storage area begin.<br>
+ *<br>
+ * The task storage area will contain the task stack, the thread-local<br>
+ * storage, and, on some architectures, the floating-point context.<br></blockquote><div><br></div><div>What does this mean? I think most architectures treat the areas as</div><div>separate (FP not in integer context) and some require all tasks to be </div><div>FP. This seems inaccurate.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ *<br>
+ * There are no alignment requirements for the task storage area. To avoid<br>
+ * memory waste, use the ::RTEMS_TASK_STORAGE_ALIGNMENT variable attribute to<br>
+ * enforce the recommended alignment of the task storage area.<br>
+ */<br>
+ void *storage_area;<br>
+<br>
+ /**<br>
+ * @brief This member defines size of the task storage area in bytes.<br>
+ *<br>
+ * Use the RTEMS_TASK_STORAGE_SIZE() macro to determine the recommended task<br>
+ * storage area size.<br>
+ */<br>
+ size_t storage_size;<br>
+<br>
+ /**<br>
+ * @brief This member defines the optional handler to free the task storage<br>
+ * area.<br>
+ *<br>
+ * It is called when the task building aborts due to a failed task create<br>
+ * extension or the task is deleted. It is called from task context under<br>
+ * protection of the object allocator lock. It is allowed to call free() in<br>
+ * this handler. The handler may be NULL.<br>
+ */<br>
+ void ( *storage_free )( void * );<br></blockquote><div><br></div><div>Is it not called when the thread is deleted? </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+ /**<br>
+ * @brief This member defines the initial modes of the task.<br>
+ */<br>
+ rtems_mode initial_modes;<br>
+<br>
+ /**<br>
+ * @brief This member defines the attributes of the task.<br>
+ */<br>
+ rtems_attribute attributes;<br>
+} rtems_task_config;<br>
+<br>
+/**<br>
+ * @brief Creates a task according to the specified configuration.<br>
+ *<br>
+ * In contrast to tasks created by rtems_task_create(), the tasks created by<br>
+ * this directive use a user-provided task storage area (contains the task<br>
+ * stack).<br></blockquote><div><br></div><div>Drop () and say which contains the task stack.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ * <br>
+ * It is not recommended to mix rtems_task_create() and<br>
+ * rtems_task_create_from_config() in an application. This directive is<br>
+ * intended for applications which do not want to use the RTEMS Workspace and<br>
+ * instead statically allocate all operating system resources. The stack space<br>
+ * estimate done by <rtems/confdefs.h> assumes that all tasks are created by<br>
+ * rtems_task_create(). The estimate can be adjusted to take user-provided task<br>
+ * storage areas into account through the ::CONFIGURE_MEMORY_OVERHEAD<br>
+ * application configuration option or a custom task stack allocator, see<br>
+ * ::CONFIGURE_TASK_STACK_ALLOCATOR.<br></blockquote><div><br></div><div>CONFIGURE_MEMORY_OVERHEAD would have to be a negative number to</div><div>make this work. Is this explained or is there some magic I am missing?</div><div><br></div><div>CONFIGURE_MEMORY_OVERHEAD is intended as a backdoor if the</div><div>confdefs.h memory calculation is too low. It is not intended for general</div><div>use like this.</div><div><br></div><div>I would rather see something like "configure build tasks" and just subtract</div><div>that from maximum threads before multiplying by minimum stack size.</div><div>This avoids the user having to add up all their statically allocated stack</div><div>sizes.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ *<br>
+ * @param config is the task configuration.<br>
+ *<br>
+ * @param[out] id is the pointer to an object identifier variable. The object<br>
+ * identifier of the created task will be stored in this variable, in case of<br>
+ * a successful operation.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successful operation.<br>
+ *<br>
+ * @retval RTEMS_INVALID_ADDRESS The id parameter is @c NULL.<br>
+ *<br>
+ * @retval RTEMS_INVALID_NAME The task name is invalid.<br>
+ *<br>
+ * @retval RTEMS_INVALID_PRIORITY The initial priority of the task is invalid.<br>
+ *<br>
+ * @retval RTEMS_TOO_MANY No task is available.<br>
+ *<br>
+ * @retval RTEMS_UNSATISFIED A task create extension failed.<br>
+ */<br>
+rtems_status_code rtems_task_create_from_config(<br>
+ const rtems_task_config *config,<br>
+ rtems_id *id<br>
+);<br>
+<br>
/**<br>
* @brief RTEMS Task Name to Id<br>
*<br>
diff --git a/cpukit/include/rtems/rtems/tasksimpl.h b/cpukit/include/rtems/rtems/tasksimpl.h<br>
index c9544f8c27..a39113a283 100644<br>
--- a/cpukit/include/rtems/rtems/tasksimpl.h<br>
+++ b/cpukit/include/rtems/rtems/tasksimpl.h<br>
@@ -42,6 +42,17 @@ extern "C" {<br>
*/<br>
void _RTEMS_tasks_Initialize_user_tasks( void );<br>
<br>
+typedef void ( *RTEMS_tasks_Prepare_stack )(<br>
+ Thread_Configuration *,<br>
+ const rtems_task_config *<br>
+);<br>
+<br>
+rtems_status_code _RTEMS_tasks_Create(<br>
+ const rtems_task_config *config,<br>
+ rtems_id *id,<br>
+ RTEMS_tasks_Prepare_stack prepare_stack<br>
+);<br>
+<br>
RTEMS_INLINE_ROUTINE Thread_Control *_RTEMS_tasks_Allocate(void)<br>
{<br>
_Objects_Allocator_lock();<br>
diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c<br>
index 5486ac9b6e..1d9a4546e8 100644<br>
--- a/cpukit/rtems/src/taskcreate.c<br>
+++ b/cpukit/rtems/src/taskcreate.c<br>
@@ -1,17 +1,36 @@<br>
+/* SPDX-License-Identifier: BSD-2-Clause */<br>
+<br>
/**<br>
- * @file<br>
+ * @file<br>
+ *<br>
+ * @ingroup ClassicTasks<br>
*<br>
- * @brief RTEMS Task Create<br>
- * @ingroup ClassicTasks<br>
+ * @brief RTEMS Task Create<br>
*/<br>
<br>
/*<br>
- * COPYRIGHT (c) 1989-2014,2016.<br>
- * On-Line Applications Research Corporation (OAR).<br>
+ * Copyright (C) 2020 embedded brains GmbH (<a href="http://www.embedded-brains.de" rel="noreferrer" target="_blank">http://www.embedded-brains.de</a>)<br>
*<br>
- * The license and distribution terms for this file may be<br>
- * found in the file LICENSE in this distribution or at<br>
- * <a href="http://www.rtems.org/license/LICENSE" rel="noreferrer" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ * Redistribution and use in source and binary forms, with or without<br>
+ * modification, are permitted provided that the following conditions<br>
+ * are met:<br>
+ * 1. Redistributions of source code must retain the above copyright<br>
+ * notice, this list of conditions and the following disclaimer.<br>
+ * 2. Redistributions in binary form must reproduce the above copyright<br>
+ * notice, this list of conditions and the following disclaimer in the<br>
+ * documentation and/or other materials provided with the distribution.<br>
+ *<br>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"<br>
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE<br>
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE<br>
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE<br>
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR<br>
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF<br>
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS<br>
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN<br>
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)<br>
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE<br>
+ * POSSIBILITY OF SUCH DAMAGE.<br>
*/<br>
<br>
#ifdef HAVE_CONFIG_H<br>
@@ -19,20 +38,24 @@<br>
#endif<br>
<br>
#include <rtems/rtems/tasksimpl.h><br>
-#include <rtems/rtems/attrimpl.h><br>
-#include <rtems/rtems/eventimpl.h><br>
-#include <rtems/rtems/modesimpl.h><br>
-#include <rtems/rtems/support.h><br>
-#include <rtems/score/apimutex.h><br>
-#include <rtems/score/schedulerimpl.h><br>
#include <rtems/score/stackimpl.h><br>
-#include <rtems/score/sysstate.h><br>
-#include <rtems/score/threadimpl.h><br>
-#include <rtems/score/userextimpl.h><br>
-#include <rtems/sysinit.h><br>
<br>
#include <string.h><br>
<br>
+static void _RTEMS_tasks_Allocate_and_prepare_stack(<br>
+ Thread_Configuration *thread_config,<br>
+ const rtems_task_config *config<br>
+)<br>
+{<br>
+ size_t size;<br>
+<br>
+ thread_config->stack_free = _Stack_Free;<br>
+ size = _Stack_Ensure_minimum( config->storage_size );<br>
+ size = _Stack_Extend_size( size, thread_config->is_fp );<br>
+ thread_config->stack_size = size;<br>
+ thread_config->stack_area = _Stack_Allocate( size );<br>
+}<br>
+<br>
rtems_status_code rtems_task_create(<br>
rtems_name name,<br>
rtems_task_priority initial_priority,<br>
@@ -42,215 +65,18 @@ rtems_status_code rtems_task_create(<br>
rtems_id *id<br>
)<br>
{<br>
- Thread_Control *the_thread;<br>
- Thread_Configuration config;<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- Objects_MP_Control *the_global_object = NULL;<br>
- bool is_global;<br>
-#endif<br>
- bool status;<br>
- rtems_attribute the_attribute_set;<br>
- bool valid;<br>
- RTEMS_API_Control *api;<br>
- ASR_Information *asr;<br>
-<br>
- if ( !id )<br>
- return RTEMS_INVALID_ADDRESS;<br>
-<br>
- if ( !rtems_is_name_valid( name ) )<br>
- return RTEMS_INVALID_NAME;<br>
-<br>
- /*<br>
- * Core Thread Initialize insures we get the minimum amount of<br>
- * stack space.<br>
- */<br>
-<br>
- /*<br>
- * Fix the attribute set to match the attributes which<br>
- * this processor (1) requires and (2) is able to support.<br>
- * First add in the required flags for attribute_set<br>
- * Typically this might include FP if the platform<br>
- * or application required all tasks to be fp aware.<br>
- * Then turn off the requested bits which are not supported.<br>
- */<br>
-<br>
- the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );<br>
- the_attribute_set =<br>
- _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );<br>
+ rtems_task_config config;<br>
<br>
memset( &config, 0, sizeof( config ) );<br>
- config.budget_algorithm = _Modes_Is_timeslice( initial_modes ) ?<br>
- THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE<br>
- : THREAD_CPU_BUDGET_ALGORITHM_NONE,<br>
- config.isr_level = _Modes_Get_interrupt_level( initial_modes );<br>
- config.name.name_u32 = name;<br>
- config.is_fp = _Attributes_Is_floating_point( the_attribute_set );<br>
- config.is_preemptible = _Modes_Is_preempt( initial_modes );<br>
- config.stack_size = _Stack_Ensure_minimum( stack_size );<br>
- config.stack_size = _Stack_Extend_size( config.stack_size, config.is_fp );<br>
-<br>
- /*<br>
- * Validate the RTEMS API priority and convert it to the core priority range.<br>
- */<br>
-<br>
- if ( !_Attributes_Is_system_task( the_attribute_set ) ) {<br>
- if ( initial_priority == PRIORITY_MINIMUM ) {<br>
- return RTEMS_INVALID_PRIORITY;<br>
- }<br>
- }<br>
-<br>
- config.scheduler = _Thread_Scheduler_get_home( _Thread_Get_executing() );<br>
-<br>
- config.priority = _RTEMS_Priority_To_core(<br>
- config.scheduler,<br>
- initial_priority,<br>
- &valid<br>
+ <a href="http://config.name" rel="noreferrer" target="_blank">config.name</a> = name;<br>
+ config.initial_priority = initial_priority;<br>
+ config.storage_size = stack_size;<br>
+ config.initial_modes = initial_modes;<br>
+ config.attributes = attribute_set;<br>
+<br>
+ return _RTEMS_tasks_Create(<br>
+ &config,<br>
+ id,<br>
+ _RTEMS_tasks_Allocate_and_prepare_stack<br>
);<br>
- if ( !valid ) {<br>
- return RTEMS_INVALID_PRIORITY;<br>
- }<br>
-<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- if ( !_System_state_Is_multiprocessing ) {<br>
- the_attribute_set = _Attributes_Clear( the_attribute_set, RTEMS_GLOBAL );<br>
- }<br>
-<br>
- is_global = _Attributes_Is_global( the_attribute_set );<br>
-#endif<br>
-<br>
- /*<br>
- * Allocate the thread control block and -- if the task is global --<br>
- * allocate a global object control block.<br>
- *<br>
- * NOTE: This routine does not use the combined allocate and open<br>
- * global object routine (_Objects_MP_Allocate_and_open) because<br>
- * this results in a lack of control over when memory is allocated<br>
- * and can be freed in the event of an error.<br>
- */<br>
- the_thread = _RTEMS_tasks_Allocate();<br>
-<br>
- if ( !the_thread ) {<br>
- _Objects_Allocator_unlock();<br>
- return RTEMS_TOO_MANY;<br>
- }<br>
-<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- if ( is_global ) {<br>
- the_global_object = _Objects_MP_Allocate_global_object();<br>
-<br>
- if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {<br>
- _RTEMS_tasks_Free( the_thread );<br>
- _Objects_Allocator_unlock();<br>
- return RTEMS_TOO_MANY;<br>
- }<br>
- }<br>
-#endif<br>
-<br>
- config.stack_free = _Stack_Free;<br>
- config.stack_area = _Stack_Allocate( config.stack_size );<br>
- status = ( config.stack_area != NULL );<br>
-<br>
- /*<br>
- * Initialize the core thread for this task.<br>
- */<br>
-<br>
- if ( status ) {<br>
- status = _Thread_Initialize(<br>
- &_RTEMS_tasks_Information,<br>
- the_thread,<br>
- &config<br>
- );<br>
- }<br>
-<br>
- if ( !status ) {<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- if ( is_global )<br>
- _Objects_MP_Free_global_object( the_global_object );<br>
-#endif<br>
- _RTEMS_tasks_Free( the_thread );<br>
- _Objects_Allocator_unlock();<br>
- return RTEMS_UNSATISFIED;<br>
- }<br>
-<br>
- api = the_thread->API_Extensions[ THREAD_API_RTEMS ];<br>
- asr = &api->Signal;<br>
-<br>
- asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true;<br>
-<br>
- *id = the_thread->Object.id;<br>
-<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- the_thread->is_global = is_global;<br>
- if ( is_global ) {<br>
-<br>
- _Objects_MP_Open(<br>
- &_RTEMS_tasks_Information.Objects,<br>
- the_global_object,<br>
- name,<br>
- the_thread->Object.id<br>
- );<br>
-<br>
- _RTEMS_tasks_MP_Send_process_packet(<br>
- RTEMS_TASKS_MP_ANNOUNCE_CREATE,<br>
- the_thread->Object.id,<br>
- name<br>
- );<br>
-<br>
- }<br>
-#endif<br>
-<br>
- _Objects_Allocator_unlock();<br>
- return RTEMS_SUCCESSFUL;<br>
-}<br>
-<br>
-static void _RTEMS_tasks_Start_extension(<br>
- Thread_Control *executing,<br>
- Thread_Control *started<br>
-)<br>
-{<br>
- RTEMS_API_Control *api;<br>
-<br>
- api = started->API_Extensions[ THREAD_API_RTEMS ];<br>
-<br>
- _Event_Initialize( &api->Event );<br>
- _Event_Initialize( &api->System_event );<br>
-}<br>
-<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
-static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )<br>
-{<br>
- if ( executing->is_global ) {<br>
- _Objects_MP_Close(<br>
- &_RTEMS_tasks_Information.Objects,<br>
- executing->Object.id<br>
- );<br>
- _RTEMS_tasks_MP_Send_process_packet(<br>
- RTEMS_TASKS_MP_ANNOUNCE_DELETE,<br>
- executing->Object.id,<br>
- 0 /* Not used */<br>
- );<br>
- }<br>
}<br>
-#endif<br>
-<br>
-static User_extensions_Control _RTEMS_tasks_User_extensions = {<br>
- .Callouts = {<br>
-#if defined(RTEMS_MULTIPROCESSING)<br>
- .thread_terminate = _RTEMS_tasks_Terminate_extension,<br>
-#endif<br>
- .thread_start = _RTEMS_tasks_Start_extension,<br>
- .thread_restart = _RTEMS_tasks_Start_extension<br>
- }<br>
-};<br>
-<br>
-static void _RTEMS_tasks_Manager_initialization( void )<br>
-{<br>
- _Thread_Initialize_information( &_RTEMS_tasks_Information );<br>
- _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );<br>
-}<br>
-<br>
-RTEMS_SYSINIT_ITEM(<br>
- _RTEMS_tasks_Manager_initialization,<br>
- RTEMS_SYSINIT_CLASSIC_TASKS,<br>
- RTEMS_SYSINIT_ORDER_MIDDLE<br>
-);<br></blockquote><div><br></div><div>Is all of this just turning rtems_task_create into a wrapper for the task create from config?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
diff --git a/cpukit/rtems/src/taskcreatefromconfig.c b/cpukit/rtems/src/taskcreatefromconfig.c<br>
new file mode 100644<br>
index 0000000000..952d3a3a3c<br>
--- /dev/null<br>
+++ b/cpukit/rtems/src/taskcreatefromconfig.c<br>
@@ -0,0 +1,274 @@<br>
+/**<br>
+ * @file<br>
+ *<br>
+ * @ingroup ClassicTasks<br>
+ *<br>
+ * @brief RTEMS Task Create from Config<br>
+ */<br>
+<br>
+/*<br>
+ * COPYRIGHT (c) 1989-2014,2016.<br>
+ * On-Line Applications Research Corporation (OAR).<br>
+ *<br>
+ * The license and distribution terms for this file may be<br>
+ * found in the file LICENSE in this distribution or at<br>
+ * <a href="http://www.rtems.org/license/LICENSE" rel="noreferrer" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifdef HAVE_CONFIG_H<br>
+#include "config.h"<br>
+#endif<br>
+<br>
+#include <rtems/rtems/tasksimpl.h><br>
+#include <rtems/rtems/attrimpl.h><br>
+#include <rtems/rtems/eventimpl.h><br>
+#include <rtems/rtems/modesimpl.h><br>
+#include <rtems/rtems/support.h><br>
+#include <rtems/score/apimutex.h><br>
+#include <rtems/score/schedulerimpl.h><br>
+#include <rtems/score/stackimpl.h><br>
+#include <rtems/score/sysstate.h><br>
+#include <rtems/score/threadimpl.h><br>
+#include <rtems/score/userextimpl.h><br>
+#include <rtems/sysinit.h><br>
+<br>
+#include <string.h><br>
+<br>
+static void _RTEMS_tasks_Prepare_user_stack(<br>
+ Thread_Configuration *thread_config,<br>
+ const rtems_task_config *config<br>
+)<br>
+{<br>
+ thread_config->stack_size = config->storage_size;<br>
+ thread_config->stack_area = config->storage_area;<br>
+<br>
+ if ( config->storage_free != NULL ) {<br>
+ thread_config->stack_free = config->storage_free;<br>
+ } else {<br>
+ thread_config->stack_free = _Stack_Free_nothing;<br>
+ }<br>
+}<br>
+<br>
+rtems_status_code rtems_task_create_from_config(<br>
+ const rtems_task_config *config,<br>
+ rtems_id *id<br>
+)<br>
+{<br>
+ return _RTEMS_tasks_Create( config, id, _RTEMS_tasks_Prepare_user_stack );<br>
+}<br>
+<br>
+rtems_status_code _RTEMS_tasks_Create(<br>
+ const rtems_task_config *config,<br>
+ rtems_id *id,<br>
+ RTEMS_tasks_Prepare_stack prepare_stack<br>
+)<br>
+{<br>
+ Thread_Control *the_thread;<br>
+ Thread_Configuration thread_config;<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ Objects_MP_Control *the_global_object = NULL;<br>
+ bool is_global;<br>
+#endif<br>
+ bool status;<br>
+ rtems_attribute attributes;<br>
+ bool valid;<br>
+ RTEMS_API_Control *api;<br>
+ ASR_Information *asr;<br>
+<br>
+ if ( !id )<br>
+ return RTEMS_INVALID_ADDRESS;<br>
+<br>
+ if ( !rtems_is_name_valid( config->name ) )<br>
+ return RTEMS_INVALID_NAME;<br>
+<br>
+ /*<br>
+ * Core Thread Initialize insures we get the minimum amount of<br>
+ * stack space.<br>
+ */<br>
+<br>
+ /*<br>
+ * Fix the attribute set to match the attributes which<br>
+ * this processor (1) requires and (2) is able to support.<br>
+ * First add in the required flags for attributes<br>
+ * Typically this might include FP if the platform<br>
+ * or application required all tasks to be fp aware.<br>
+ * Then turn off the requested bits which are not supported.<br>
+ */<br>
+<br>
+ attributes = _Attributes_Set( config->attributes, ATTRIBUTES_REQUIRED );<br>
+ attributes = _Attributes_Clear( attributes, ATTRIBUTES_NOT_SUPPORTED );<br>
+<br>
+ memset( &thread_config, 0, sizeof( thread_config ) );<br>
+ thread_config.budget_algorithm = _Modes_Is_timeslice( config->initial_modes ) ?<br>
+ THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE<br>
+ : THREAD_CPU_BUDGET_ALGORITHM_NONE,<br>
+ thread_config.isr_level = _Modes_Get_interrupt_level( config->initial_modes );<br>
+ thread_config.name.name_u32 = config->name;<br>
+ thread_config.is_fp = _Attributes_Is_floating_point( attributes );<br>
+ thread_config.is_preemptible = _Modes_Is_preempt( config->initial_modes );<br>
+<br>
+ /*<br>
+ * Validate the RTEMS API priority and convert it to the core priority range.<br>
+ */<br>
+<br>
+ if ( !_Attributes_Is_system_task( attributes ) ) {<br>
+ if ( config->initial_priority == PRIORITY_MINIMUM ) {<br>
+ return RTEMS_INVALID_PRIORITY;<br>
+ }<br>
+ }<br>
+<br>
+ thread_config.scheduler =<br>
+ _Thread_Scheduler_get_home( _Thread_Get_executing() );<br>
+<br>
+ thread_config.priority = _RTEMS_Priority_To_core(<br>
+ thread_config.scheduler,<br>
+ config->initial_priority,<br>
+ &valid<br>
+ );<br>
+ if ( !valid ) {<br>
+ return RTEMS_INVALID_PRIORITY;<br>
+ }<br>
+<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ if ( !_System_state_Is_multiprocessing ) {<br>
+ attributes = _Attributes_Clear( attributes, RTEMS_GLOBAL );<br>
+ }<br>
+<br>
+ is_global = _Attributes_Is_global( attributes );<br>
+#endif<br>
+<br>
+ /*<br>
+ * Allocate the thread control block and -- if the task is global --<br>
+ * allocate a global object control block.<br>
+ *<br>
+ * NOTE: This routine does not use the combined allocate and open<br>
+ * global object routine (_Objects_MP_Allocate_and_open) because<br>
+ * this results in a lack of control over when memory is allocated<br>
+ * and can be freed in the event of an error.<br>
+ */<br>
+ the_thread = _RTEMS_tasks_Allocate();<br>
+<br>
+ if ( !the_thread ) {<br>
+ _Objects_Allocator_unlock();<br>
+ return RTEMS_TOO_MANY;<br>
+ }<br>
+<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ if ( is_global ) {<br>
+ the_global_object = _Objects_MP_Allocate_global_object();<br>
+<br>
+ if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {<br>
+ _RTEMS_tasks_Free( the_thread );<br>
+ _Objects_Allocator_unlock();<br>
+ return RTEMS_TOO_MANY;<br>
+ }<br>
+ }<br>
+#endif<br>
+<br>
+ ( *prepare_stack )( &thread_config, config );<br>
+ status = ( thread_config.stack_area != NULL );<br>
+<br>
+ /*<br>
+ * Initialize the core thread for this task.<br>
+ */<br>
+<br>
+ if ( status ) {<br>
+ status = _Thread_Initialize(<br>
+ &_RTEMS_tasks_Information,<br>
+ the_thread,<br>
+ &thread_config<br>
+ );<br>
+ }<br>
+<br>
+ if ( !status ) {<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ if ( is_global )<br>
+ _Objects_MP_Free_global_object( the_global_object );<br>
+#endif<br>
+ _RTEMS_tasks_Free( the_thread );<br>
+ _Objects_Allocator_unlock();<br>
+ return RTEMS_UNSATISFIED;<br>
+ }<br>
+<br>
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];<br>
+ asr = &api->Signal;<br>
+<br>
+ asr->is_enabled = !_Modes_Is_asr_disabled( config->initial_modes );<br>
+<br>
+ *id = the_thread->Object.id;<br>
+<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ the_thread->is_global = is_global;<br>
+ if ( is_global ) {<br>
+<br>
+ _Objects_MP_Open(<br>
+ &_RTEMS_tasks_Information.Objects,<br>
+ the_global_object,<br>
+ config->name,<br>
+ the_thread->Object.id<br>
+ );<br>
+<br>
+ _RTEMS_tasks_MP_Send_process_packet(<br>
+ RTEMS_TASKS_MP_ANNOUNCE_CREATE,<br>
+ the_thread->Object.id,<br>
+ config->name<br>
+ );<br>
+<br>
+ }<br>
+#endif<br>
+<br>
+ _Objects_Allocator_unlock();<br>
+ return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+static void _RTEMS_tasks_Start_extension(<br>
+ Thread_Control *executing,<br>
+ Thread_Control *started<br>
+)<br>
+{<br>
+ RTEMS_API_Control *api;<br>
+<br>
+ api = started->API_Extensions[ THREAD_API_RTEMS ];<br>
+<br>
+ _Event_Initialize( &api->Event );<br>
+ _Event_Initialize( &api->System_event );<br>
+}<br>
+<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )<br>
+{<br>
+ if ( executing->is_global ) {<br>
+ _Objects_MP_Close(<br>
+ &_RTEMS_tasks_Information.Objects,<br>
+ executing->Object.id<br>
+ );<br>
+ _RTEMS_tasks_MP_Send_process_packet(<br>
+ RTEMS_TASKS_MP_ANNOUNCE_DELETE,<br>
+ executing->Object.id,<br>
+ 0 /* Not used */<br>
+ );<br>
+ }<br>
+}<br>
+#endif<br>
+<br>
+static User_extensions_Control _RTEMS_tasks_User_extensions = {<br>
+ .Callouts = {<br>
+#if defined(RTEMS_MULTIPROCESSING)<br>
+ .thread_terminate = _RTEMS_tasks_Terminate_extension,<br>
+#endif<br>
+ .thread_start = _RTEMS_tasks_Start_extension,<br>
+ .thread_restart = _RTEMS_tasks_Start_extension<br>
+ }<br>
+};<br>
+<br>
+static void _RTEMS_tasks_Manager_initialization( void )<br>
+{<br>
+ _Thread_Initialize_information( &_RTEMS_tasks_Information );<br>
+ _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );<br>
+}<br>
+<br>
+RTEMS_SYSINIT_ITEM(<br>
+ _RTEMS_tasks_Manager_initialization,<br>
+ RTEMS_SYSINIT_CLASSIC_TASKS,<br>
+ RTEMS_SYSINIT_ORDER_MIDDLE<br>
+);<br>
diff --git a/testsuites/sptests/sp01/init.c b/testsuites/sptests/sp01/init.c<br>
index 2719c84fc8..a0a332987d 100644<br>
--- a/testsuites/sptests/sp01/init.c<br>
+++ b/testsuites/sptests/sp01/init.c<br>
@@ -16,6 +16,19 @@<br>
<br>
const char rtems_test_name[] = "SP 1";<br>
<br>
+RTEMS_TASK_STORAGE_ALIGNMENT static char Task_1_storage[<br>
+ RTEMS_TASK_STORAGE_SIZE( 2 * RTEMS_MINIMUM_STACK_SIZE, RTEMS_FLOATING_POINT )<br></blockquote><div><br></div><div>This line appears to be too long.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+];<br>
+<br>
+static const rtems_task_config Task_1_config = {<br>
+ .name = rtems_build_name( 'T', 'A', '1', ' ' ),<br>
+ .initial_priority = 1,<br>
+ .storage_area = Task_1_storage,<br>
+ .storage_size = sizeof( Task_1_storage ),<br>
+ .initial_modes = RTEMS_DEFAULT_MODES,<br>
+ .attributes = RTEMS_FLOATING_POINT<br>
+};<br>
+<br>
rtems_task Init(<br>
rtems_task_argument argument<br>
)<br>
@@ -30,15 +43,8 @@ rtems_task Init(<br>
status = rtems_clock_set( &time );<br>
directive_failed( status, "rtems_clock_set" );<br>
<br>
- status = rtems_task_create(<br>
- rtems_build_name( 'T', 'A', '1', ' ' ),<br>
- 1,<br>
- RTEMS_MINIMUM_STACK_SIZE * 2,<br>
- RTEMS_DEFAULT_MODES,<br>
- RTEMS_DEFAULT_ATTRIBUTES,<br>
- &id<br>
- );<br>
- directive_failed( status, "rtems_task_create of TA1" );<br>
+ status = rtems_task_create_from_config( &Task_1_config, &id );<br>
+ directive_failed( status, "rtems_task_create_from_config of TA1" );<br>
<br>
status = rtems_task_start( id, Task_1_through_3, 1 );<br>
directive_failed( status, "rtems_task_start of TA1" );<br>
diff --git a/testsuites/sptests/sp01/sp01.doc b/testsuites/sptests/sp01/sp01.doc<br>
index d7d9f5d902..62bbe956d3 100644<br>
--- a/testsuites/sptests/sp01/sp01.doc<br>
+++ b/testsuites/sptests/sp01/sp01.doc<br>
@@ -9,6 +9,7 @@<br>
test name: sp01<br>
<br>
directives:<br>
+ rtems_task_build<br>
rtems_task_create<br>
rtems_task_start<br>
rtems_task_wake_after<br>
diff --git a/testsuites/sptests/sp01/system.h b/testsuites/sptests/sp01/system.h<br>
index bde5328aa9..e2047b4d3a 100644<br>
--- a/testsuites/sptests/sp01/system.h<br>
+++ b/testsuites/sptests/sp01/system.h<br>
@@ -28,7 +28,7 @@ rtems_task Task_1_through_3(<br>
<br>
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE<br>
<br>
-#define CONFIGURE_EXTRA_TASK_STACKS (4 * RTEMS_MINIMUM_STACK_SIZE)<br>
+#define CONFIGURE_EXTRA_TASK_STACKS (2 * RTEMS_MINIMUM_STACK_SIZE)<br>
#define CONFIGURE_MAXIMUM_TASKS 4<br></blockquote><div><br></div><div>This seems to be missing lowering the computation for number of</div><div>minimum stacks reserved</div><div><br></div><div>--joel</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
#include <rtems/confdefs.h><br>
-- <br>
2.26.2<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div></div>