#3959 closed enhancement (fixed)

Add rtems_task_construct()

Reported by: Sebastian Huber Owned by: Sebastian Huber
Priority: normal Milestone: 6.1
Component: rtems Version: 6
Severity: normal Keywords: qualification
Cc: Blocked By:
Blocking:

Description (last modified by Sebastian Huber)

In RTEMS 5 a lot of development was done to allow a static allocation of resources provided by RTEMS and avoid the use of a heap. One missing piece is the support for statically allocated RTEMS tasks. The rtems_task_create() function allocates the task stack from a heap. We need an alternative function which allocates an RTEMS tasks with a user provided stack (similar to the POSIX threads).

There does need to be documentation on the allocation
strategies, when to use, limitations, and particularly the
use of rtems-exeinfo to get the TLS size. This is one case
for sure where an RTEMS Tool needs explicit mention in
both the API and configure option sections.

Proposed API:

/**
 * @brief This structure defines the configuration of a task constructed by
 *   rtems_task_construct().
 */
typedef struct {
  /**
   * @brief This member defines the name of the task.
   */
  rtems_name name;

  /**
   * @brief This member defines the 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.
   *
   * The task storage area begin address and size should be aligned by
   * #RTEMS_TASK_STORAGE_ALIGNMENT.  To avoid memory waste, use RTEMS_ALIGNED()
   * and #RTEMS_TASK_STORAGE_ALIGNMENT to enforce the recommended alignment of a
   * statically allocated 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 maximum thread-local storage size supported
   *   by the task storage area.
   *
   * Use RTEMS_ALIGN_UP() and #RTEMS_TASK_STORAGE_ALIGNMENT to adjust the size to
   * meet the minimum alignment requirement of a thread-local storage area used
   * to construct a task.
   *
   * If the value is less than the actual thread-local storage size, then the
   * task construction by rtems_task_construct() fails.
   *
   * If the is less than the task storage area size, then the task construction
   * by rtems_task_construct() fails.
   *
   * The actual thread-local storage size is determined when the application
   * executable is linked.  The ``rtems-exeinfo`` command line tool included in
   * the RTEMS Tools can be used to obtain the thread-local storage size and
   * alignment of an application executable.
   *
   * The application may configure the maximum thread-local storage size for all
   * threads explicitly through the #CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE
   * configuration option.
   */
  size_t maximum_thread_local_storage_size;

  /**
   * @brief This member defines the optional handler to free the task storage
   *   area.
   *
   * It is called on exactly two mutually exclusive occasions.  Firstly, when the
   * task construction aborts due to a failed task create extension, or secondly,
   * when 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.
   * If handler is NULL, then no action will be performed.
   */
  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 Constructs a task from the specified the task configuration.
 *
 * In contrast to tasks created by rtems_task_create(), the tasks constructed
 * 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.
 *
 * This directive is intended for applications which do not want to use the
 * RTEMS Workspace and instead statically allocate all operating system
 * resources.  It is not recommended to use rtems_task_create() and
 * rtems_task_construct() together in an application.  It is also not
 * recommended to use rtems_task_construct() for drivers or general purpose
 * libraries.  The reason for these recommendations is that the task
 * configuration needs settings which can be only given with a through
 * knowledge of the application resources.
 *
 * An application based solely on static allocation can avoid any runtime
 * memory allocators.  This can simplfiy the application architecture as well
 * as any analysis that may be required.
 *
 * 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_MINIMUM_TASKS_WITH_USER_PROVIDED_STORAGE application
 * configuration option.
 *
 * The #CONFIGURE_MAXIMUM_TASKS should include tasks constructed by
 * rtems_task_construct().
 *
 * @param config is the task configuration.
 *
 * @param[out] id is the pointer to an object identifier variable.  The
 *   identifier of the constructed task object will be stored in this variable,
 *   in case of a successful operation.
 *
 * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
 *
 * @retval ::RTEMS_INVALID_ADDRESS The id parameter was NULL.
 *
 * @retval ::RTEMS_INVALID_NAME The task name was invalid.
 *
 * @retval ::RTEMS_INVALID_PRIORITY The initial task priority was invalid.
 *
 * @retval ::RTEMS_INVALID_SIZE The thread-local storage size is greater than
 *   the maximum thread-local storage size specified in the task configuration.
 *   The thread-local storage size is determined by the thread-local variables
 *   used by the application and #CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE.
 *
 * @retval ::RTEMS_INVALID_SIZE The task storage area was too small to provide
 *   a task stack of the configured minimum size, see
 *   #CONFIGURE_MINIMUM_TASK_STACK_SIZE. 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.
 *
 * @retval ::RTEMS_TOO_MANY There was no inactive task object available to
 *   construct a task.
 *
 * @retval ::RTEMS_TOO_MANY In multiprocessing configurations, there was no
 *   inactive global object available to construct a global task.
 *
 * @retval ::RTEMS_UNSATISFIED One of the task create extensions failed during
 *   the task construction.
 *
 * @retval ::RTEMS_UNSATISFIED In SMP configurations, the non-preemption mode
 *   was not supported.
 *
 * @retval ::RTEMS_UNSATISFIED In SMP configurations, the interrupt level mode
 *   was not supported.
 */
rtems_status_code rtems_task_construct(
  const rtems_task_config *config,
  rtems_id                *id
);

Attachments (1)

0001-rtems-Add-rtems_task_build.patch (19.8 KB) - added by Sebastian Huber on 04/17/20 at 07:32:59.

Download all attachments as: .zip

Change History (25)

Changed on 04/17/20 at 07:32:59 by Sebastian Huber

comment:1 Changed on 09/02/20 at 16:03:13 by Sebastian Huber <sebastian.huber@…>

In 91c811a1/rtems:

score: Add _Freechain_Push()

Update #3959.

comment:2 Changed on 09/02/20 at 16:03:17 by Sebastian Huber <sebastian.huber@…>

In 354c2b5/rtems:

score: Add <rtems/score/freechainimpl.h>

Hide implementation details.

Update #3959.

comment:3 Changed on 09/02/20 at 16:03:20 by Sebastian Huber <sebastian.huber@…>

In 159db411/rtems:

score: Use _Freechain_Push()

The nodes are never NULL.

Update #3959.

comment:4 Changed on 09/02/20 at 16:03:24 by Sebastian Huber <sebastian.huber@…>

In d817220/rtems:

score: Add _Stack_Allocator_do_initialize()

Do the stack allocator initialization and sanity check only if a
user-provided stack allocator was configured. This avoids a dependency
of _Thread_Handler_initialization() on the stack allocator.

Update #3959.

comment:5 Changed on 09/02/20 at 16:03:27 by Sebastian Huber <sebastian.huber@…>

In 2d551030/rtems:

score: Move _Stack_Allocator_free to separate file

This decouples the task stack allocation from the deallocation.

Update #3959.

comment:6 Changed on 09/02/20 at 16:03:30 by Sebastian Huber <sebastian.huber@…>

In aedd92d/rtems:

score: Add stack free handler to TCB

This avoids a dependency to the stack free function in the thread
destruction.

Update #3959.

comment:7 Changed on 09/03/20 at 04:33:56 by Sebastian Huber

Description: modified (diff)
Summary: Add rtems_task_build()Add rtems_task_create_from_config()

comment:8 Changed on 09/11/20 at 13:47:33 by Sebastian Huber <sebastian.huber@…>

In dd734d46/rtems:

score: Fix _Thread_Initialize()

Fix an error cleanup path in SMP configurations to avoid a NULL pointer access.

Update #3959.

comment:9 Changed on 09/13/20 at 08:25:35 by Sebastian Huber

Description: modified (diff)

comment:10 Changed on 09/13/20 at 23:03:33 by Chris Johns

The following are some suggested updates. It is hard to comment on stuff in the ticket header in a way that does not change it so I hope doing this is OK?

Updated ....

/**
 * @brief This structure defines a task configuration used to create
 *        a task with user provided storage.
 *   This structure defines the configuration of a task created by
 *   rtems_task_create_from_config().
 */

With this ...

   * 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.

... I understand the alignment for a user is anything but internally the memory may be aligned and that will potentially create some waste. For example I could provide 0x1 as an address but the stack base or the start of the TLS may need to be aligned depending on the arch, _TLS_Alignment, or something. Does this need to be explained?

Updated ...

   * 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 to disable.

Updated ...

 * @brief Creates a task from the specified the task 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 recommended rtems_task_create() and rtems_task_create_from_config()
 * are not used together in an application. This means 
 * rtems_task_create_from_config() is not recommended for drivers or libraries
 * an application may use. This directive is intended for applications which
 * do not want to use the RTEMS Workspace and instead statically allocate all
 * operating system resources.
 *
 * An application based solely on static allocation can avoid any runtime
 * memory allocators. This can simplfiy the application architecture as well
 * as any analysis that may be required.
 *
 * 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.
 *
 * The #CONFIGURE_MAXIMUM_TASKS should includes tasks created with
 * rtems_task_create_from_config().

comment:11 Changed on 09/14/20 at 17:48:12 by Sebastian Huber

Yes, the storage internal alignment is something which needs to be better explained.

I think we should change RTEMS_TASK_STORAGE_ALIGNMENT to be just the alignment value and say that the maximum thread-local storage size shall have at least this alignment.

CONTEXT_FP_SIZE should be aligned by RTEMS_TASK_STORAGE_ALIGNMENT. For RTEMS_TASK_STORAGE_ALIGNMENT we should use CPU_HEAP_ALIGNMENT.

comment:12 Changed on 09/15/20 at 02:50:02 by Chris Johns

Sure. What about adding "RTEMS_TASK_STORAGE_ALIGNMENT will optimally use the provided storage"? We do not need to hand hold into the detail but we should hint at the best approach.

comment:13 Changed on 09/17/20 at 16:09:22 by Sebastian Huber <sebastian.huber@…>

In 641b31a4/rtems:

rtems: Add RTEMS_ALIGN_DOWN()

Update #3959.
Update #4074.

comment:14 Changed on 09/17/20 at 16:09:25 by Sebastian Huber <sebastian.huber@…>

In dce1cdf1/rtems:

rtems: Add RTEMS_ALIGN_UP()

Update #3959.
Update #4074.

comment:15 Changed on 09/17/20 at 16:09:32 by Sebastian Huber <sebastian.huber@…>

In 6942e5f/rtems:

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.

comment:16 Changed on 09/17/20 at 16:09:36 by Sebastian Huber <sebastian.huber@…>

In ad22c65/rtems:

doxygen: Move top-level group definitions

Update #3959.

comment:17 Changed on 09/17/20 at 16:09:39 by Sebastian Huber <sebastian.huber@…>

In 139ffa2/rtems:

validation: Add general purpose test suite

Add a general purpose test suite for validation tests.

This is the first test suite generated from a specification item in the
rtems-central repository.

Update #3959.

comment:18 Changed on 09/17/20 at 16:09:42 by Sebastian Huber <sebastian.huber@…>

In 3dd4cbb/rtems:

validation: rtems_task_construct() errors

This is the first test case generated from a specification item in the
rtems-central repository.

Update #3959.

comment:19 Changed on 09/17/20 at 16:14:45 by Sebastian Huber <sebastian.huber@…>

In 28db972/rtems-docs:

c-user: CONFIGURE_MINIMUM_TASKS_WITH_USER_PROVIDED_STORAGE

Document this application configuration option.

Update #3959.

comment:20 Changed on 09/17/20 at 16:17:25 by Sebastian Huber

Description: modified (diff)
Summary: Add rtems_task_create_from_config()Add rtems_task_construct()

comment:21 Changed on 09/17/20 at 18:08:26 by Sebastian Huber <sebastian.huber@…>

In 2f65e13/rtems:

rtems: Fix typo

Update #3959.

comment:22 Changed on 04/23/21 at 06:25:33 by Sebastian Huber <sebastian.huber@…>

In f14cf0c/rtems:

rtems: Check for NULL config in task construct

Since there are already excessive NULL pointer checks in the Classic
API, do this also in rtems_task_construct().

Update #3959.

comment:23 Changed on 06/18/21 at 09:24:45 by Sebastian Huber

Keywords: qualification added

comment:24 Changed on 09/02/21 at 05:59:46 by Sebastian Huber

Resolution: fixed
Status: assignedclosed

The new directive was documented, implemented, and tested:

https://docs.rtems.org/branches/master/c-user/task/directives.html#rtems-task-construct

Note: See TracTickets for help on using tickets.