<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Aug 21, 2020 at 6:51 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.<br></blockquote><div><br></div><div>And all the creation parameters are in a structure which this log doesn't mention.</div><div><br></div><div>How is the user supposed to know how large the "task storage area" should be</div><div>The sp01 modifications seem to be a bit deceptive because the area is just declared</div><div>in terms of stack size. I would expect some user facing macros that capture the</div><div>size required for a non-FP and FP task. If FP is all tasks, then both would give</div><div>the same base value. Perhaps even take the requested stack size.</div><div><br></div><div>How does the user account for any memory that is needed for alignment? </div><div>Declaring a byte array is almost certainly not aligned sufficiently for a</div><div>structure with larger elements and the stack itself may need to be cache</div><div>line size aligned.</div><div><br></div><div>I spotted multiple places in this patch where variables and parameters</div><div>are not aligned properly. </div><div><br></div><div>But more important than formatting, I think the user facing part is too error </div><div>prone as it appears to be defined. It still counts as a user facing task which </div><div>means confdefs.h will include it in its stack calculations and that is used</div><div>to reserve memory which will never be used. Similarly maximum tasks</div><div>is used to reserve work space memory for various structures. </div><div><br></div><div>I don't think this one is ready. It needs API discussion more than basic</div><div>feature discussion.</div><div><br></div><div>--joel</div><div><br></div><div><br><br><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>
Close #3959.<br>
---<br>
 cpukit/Makefile.am                     |   1 +<br>
 cpukit/include/rtems/rtems/tasks.h     |  65 ++++++<br>
 cpukit/include/rtems/rtems/tasksimpl.h |  11 +<br>
 cpukit/rtems/src/taskbuild.c           | 273 ++++++++++++++++++++++++<br>
 cpukit/rtems/src/taskcreate.c          | 274 +++++--------------------<br>
 testsuites/sptests/sp01/init.c         |  22 +-<br>
 testsuites/sptests/sp01/sp01.doc       |   1 +<br>
 testsuites/sptests/sp01/system.h       |   2 +-<br>
 8 files changed, 413 insertions(+), 236 deletions(-)<br>
 create mode 100644 cpukit/rtems/src/taskbuild.c<br>
<br>
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am<br>
index bc56822cf8..e382478eac 100644<br>
--- a/cpukit/Makefile.am<br>
+++ b/cpukit/Makefile.am<br>
@@ -785,6 +785,7 @@ librtemscpu_a_SOURCES += rtems/src/statustext.c<br>
 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/taskbuild.c<br>
 librtemscpu_a_SOURCES += rtems/src/taskcreate.c<br>
 librtemscpu_a_SOURCES += rtems/src/taskdelete.c<br>
 librtemscpu_a_SOURCES += rtems/src/taskexit.c<br>
diff --git a/cpukit/include/rtems/rtems/tasks.h b/cpukit/include/rtems/rtems/tasks.h<br>
index 12c323e60e..dff811686a 100644<br>
--- a/cpukit/include/rtems/rtems/tasks.h<br>
+++ b/cpukit/include/rtems/rtems/tasks.h<br>
@@ -164,6 +164,71 @@ rtems_status_code rtems_task_create(<br>
   rtems_id            *id<br>
 );<br>
<br>
+/**<br>
+ * @brief This structure defines the configuration of a task to build with<br>
+ *   rtems_task_build().<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>
+   */<br>
+  void *storage_area;<br>
+<br>
+  /**<br>
+   * @brief This member defines size of the task storage area in bytes.<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 may be NULL.<br>
+   */<br>
+  void ( *storage_free )( void * );<br>
+<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 Builds a task according to the specified configuration.<br>
+ *<br>
+ * @param config The task configuration.<br>
+ * @param[out] id The task identifier of the new task.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successful operation.<br>
+ * @retval RTEMS_INVALID_ADDRESS The id parameter is @c NULL.<br>
+ * @retval RTEMS_INVALID_NAME The task name is invalid.<br>
+ * @retval RTEMS_INVALID_PRIORITY The initial priority of the task is invalid.<br>
+ * @retval RTEMS_TOO_MANY No task is available.<br>
+ * @retval RTEMS_UNSATISFIED A task create extension failed.<br>
+ */<br>
+rtems_status_code rtems_task_build(<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..b1c1f38899 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_Build(<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/taskbuild.c b/cpukit/rtems/src/taskbuild.c<br>
new file mode 100644<br>
index 0000000000..28f9f536f6<br>
--- /dev/null<br>
+++ b/cpukit/rtems/src/taskbuild.c<br>
@@ -0,0 +1,273 @@<br>
+/**<br>
+ *  @file<br>
+ *<br>
+ *  @brief RTEMS Task Create<br>
+ *  @ingroup ClassicTasks<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_build(<br>
+  const rtems_task_config *config,<br>
+  rtems_id                *id<br>
+)<br>
+{<br>
+  return _RTEMS_tasks_Build( config, id, _RTEMS_tasks_Prepare_user_stack );<br>
+}<br>
+<br>
+rtems_status_code _RTEMS_tasks_Build(<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/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c<br>
index 5486ac9b6e..3a0badf285 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,14 @@ 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>
-  );<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>
+  <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>
-  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>
+  return _RTEMS_tasks_Build( &config, id, _RTEMS_tasks_Allocate_and_prepare_stack );<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..f25300e5bb 100644<br>
--- a/testsuites/sptests/sp01/init.c<br>
+++ b/testsuites/sptests/sp01/init.c<br>
@@ -16,6 +16,17 @@<br>
<br>
 const char rtems_test_name[] = "SP 1";<br>
<br>
+static char Task_1_storage[ 2 * RTEMS_MINIMUM_STACK_SIZE ];<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_DEFAULT_ATTRIBUTES<br>
+};<br>
+<br>
 rtems_task Init(<br>
   rtems_task_argument argument<br>
 )<br>
@@ -30,15 +41,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_build( &Task_1_config, &id );<br>
+  directive_failed( status, "rtems_task_build 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>
<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>