diff options
Diffstat (limited to 'testsuites/validation/tc-task-performance.c')
-rw-r--r-- | testsuites/validation/tc-task-performance.c | 1152 |
1 files changed, 1152 insertions, 0 deletions
diff --git a/testsuites/validation/tc-task-performance.c b/testsuites/validation/tc-task-performance.c new file mode 100644 index 0000000000..3fac8f4f4e --- /dev/null +++ b/testsuites/validation/tc-task-performance.c @@ -0,0 +1,1152 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RtemsTaskValPerf + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * + * 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. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> + +#include "ts-config.h" +#include "tx-support.h" + +#include <rtems/test.h> + +/** + * @defgroup RtemsTaskValPerf spec:/rtems/task/val/perf + * + * @ingroup TestsuitesPerformanceNoClock0 + * + * @brief This test case provides a context to run @ref RTEMSAPIClassicTasks + * performance tests. + * + * @{ + */ + +/** + * @brief Test context for spec:/rtems/task/val/perf test case. + */ +typedef struct { + /** + * @brief This member provides a worker identifier. + */ + rtems_id worker_id; + + /** + * @brief This member provides a second worker identifier. + */ + rtems_id worker_2_id; + + /** + * @brief This member provides a status code. + */ + rtems_status_code status; + + /** + * @brief This member references the measure runtime context. + */ + T_measure_runtime_context *context; + + /** + * @brief This member provides the measure runtime request. + */ + T_measure_runtime_request request; + + /** + * @brief This member provides an optional measurement begin time point. + */ + T_ticks begin; + + /** + * @brief This member provides an optional measurement end time point. + */ + T_ticks end; +} RtemsTaskValPerf_Context; + +static RtemsTaskValPerf_Context + RtemsTaskValPerf_Instance; + +#define EVENT_RESTART RTEMS_EVENT_0 + +#define EVENT_SET_END RTEMS_EVENT_1 + +#define EVENT_BUSY RTEMS_EVENT_2 + +typedef RtemsTaskValPerf_Context Context; + +RTEMS_ALIGNED( RTEMS_TASK_STORAGE_ALIGNMENT ) static char task_storage[ + RTEMS_TASK_STORAGE_SIZE( + TEST_MAXIMUM_TLS_SIZE + TEST_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_ATTRIBUTES + ) +]; + +static const rtems_task_config config = { + .name = OBJECT_NAME, + .initial_priority = PRIO_NORMAL, + .storage_area = task_storage, + .storage_size = sizeof( task_storage ), + .maximum_thread_local_storage_size = 0, + .initial_modes = RTEMS_DEFAULT_MODES, + .attributes = RTEMS_DEFAULT_ATTRIBUTES +}; + +static void Send( const Context *ctx, rtems_event_set events ) +{ + SendEvents( ctx->worker_id, events ); +} + +static void Worker( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = (Context *) arg; + ctx->end = T_tick(); + + while ( true ) { + rtems_event_set events; + T_ticks ticks; + + events = ReceiveAnyEvents(); + ticks = T_tick(); + + if ( ( events & EVENT_RESTART ) != 0 ) { + ctx->begin = T_tick(); + (void) rtems_task_restart( RTEMS_SELF, (rtems_task_argument) ctx ); + } + + if ( ( events & EVENT_SET_END ) != 0 ) { + ctx->end = ticks; + } + + if ( ( events & EVENT_BUSY ) != 0 ) { + (void) _CPU_Thread_Idle_body( 0 ); + } + } +} + +static void RtemsTaskValPerf_Setup_Context( RtemsTaskValPerf_Context *ctx ) +{ + T_measure_runtime_config config; + + memset( &config, 0, sizeof( config ) ); + config.sample_count = 100; + ctx->request.arg = ctx; + ctx->request.flags = T_MEASURE_RUNTIME_REPORT_SAMPLES; + ctx->context = T_measure_runtime_create( &config ); + T_assert_not_null( ctx->context ); +} + +/** + * @brief Set the runner priority. + */ +static void RtemsTaskValPerf_Setup( RtemsTaskValPerf_Context *ctx ) +{ + SetSelfPriority( PRIO_NORMAL ); +} + +static void RtemsTaskValPerf_Setup_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskValPerf_Setup_Context( ctx ); + RtemsTaskValPerf_Setup( ctx ); +} + +/** + * @brief Restore the runner priority. + */ +static void RtemsTaskValPerf_Teardown( RtemsTaskValPerf_Context *ctx ) +{ + RestoreRunnerPriority(); +} + +static void RtemsTaskValPerf_Teardown_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskValPerf_Teardown( ctx ); +} + +static T_fixture RtemsTaskValPerf_Fixture = { + .setup = RtemsTaskValPerf_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskValPerf_Teardown_Wrap, + .scope = NULL, + .initial_context = &RtemsTaskValPerf_Instance +}; + +/** + * @defgroup RtemsTaskReqPerfConstruct spec:/rtems/task/req/perf-construct + * + * @{ + */ + +/** + * @brief Construct a worker task. + */ +static void RtemsTaskReqPerfConstruct_Body( RtemsTaskValPerf_Context *ctx ) +{ + ctx->status = rtems_task_construct( &config, &ctx->worker_id ); +} + +static void RtemsTaskReqPerfConstruct_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfConstruct_Body( ctx ); +} + +/** + * @brief Delete the worker. Discard samples interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfConstruct_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + DeleteTask( ctx->worker_id ); + KillZombies(); + + return tic == toc; +} + +static bool RtemsTaskReqPerfConstruct_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfConstruct_Teardown( ctx, delta, tic, toc, retry ); +} + +/** @} */ + +/** + * @defgroup RtemsTaskReqPerfRestart spec:/rtems/task/req/perf-restart + * + * @{ + */ + +/** + * @brief Create and start a worker task. + */ +static void RtemsTaskReqPerfRestart_Prepare( RtemsTaskValPerf_Context *ctx ) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +/** + * @brief Restart the worker task. + */ +static void RtemsTaskReqPerfRestart_Body( RtemsTaskValPerf_Context *ctx ) +{ + ctx->status = rtems_task_restart( + ctx->worker_id, + (rtems_task_argument) ctx + ); +} + +static void RtemsTaskReqPerfRestart_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfRestart_Body( ctx ); +} + +/** + * @brief Discard samples interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfRestart_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfRestart_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfRestart_Teardown( ctx, delta, tic, toc, retry ); +} + +/** + * @brief Delete the worker task. + */ +static void RtemsTaskReqPerfRestart_Cleanup( RtemsTaskValPerf_Context *ctx ) +{ + DeleteTask( ctx->worker_id ); +} + +/** @} */ + +/** + * @defgroup RtemsTaskReqPerfRestartPreempt \ + * spec:/rtems/task/req/perf-restart-preempt + * + * @{ + */ + +/** + * @brief Create and start a worker task. + */ +static void RtemsTaskReqPerfRestartPreempt_Prepare( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +/** + * @brief Restart the worker task. + */ +static void RtemsTaskReqPerfRestartPreempt_Body( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->begin = T_tick(); + ctx->status = rtems_task_restart( + ctx->worker_id, + (rtems_task_argument) ctx + ); +} + +static void RtemsTaskReqPerfRestartPreempt_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfRestartPreempt_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsTaskReqPerfRestartPreempt_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + + return tic == toc; +} + +static bool RtemsTaskReqPerfRestartPreempt_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfRestartPreempt_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Delete the worker task. + */ +static void RtemsTaskReqPerfRestartPreempt_Cleanup( + RtemsTaskValPerf_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +/** @} */ + +/** + * @defgroup RtemsTaskReqPerfRestartSelf spec:/rtems/task/req/perf-restart-self + * + * @{ + */ + +/** + * @brief Create and start a worker task. + */ +static void RtemsTaskReqPerfRestartSelf_Prepare( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +/** + * @brief Restart the worker task. + */ +static void RtemsTaskReqPerfRestartSelf_Body( RtemsTaskValPerf_Context *ctx ) +{ + Send( ctx, EVENT_RESTART ); +} + +static void RtemsTaskReqPerfRestartSelf_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfRestartSelf_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsTaskReqPerfRestartSelf_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + + return tic == toc; +} + +static bool RtemsTaskReqPerfRestartSelf_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfRestartSelf_Teardown( ctx, delta, tic, toc, retry ); +} + +/** + * @brief Delete the worker task. + */ +static void RtemsTaskReqPerfRestartSelf_Cleanup( + RtemsTaskValPerf_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +/** @} */ + +#if defined(RTEMS_SMP) +/** + * @defgroup RtemsTaskReqPerfSetSchedulerMove \ + * spec:/rtems/task/req/perf-set-scheduler-move + * + * @{ + */ + +/** + * @brief Set the runner affinity. + */ +static void RtemsTaskReqPerfSetSchedulerMove_Prepare( + RtemsTaskValPerf_Context *ctx +) +{ + SetSelfAffinityAll(); +} + +/** + * @brief Set the scheduler of the runner. + */ +static void RtemsTaskReqPerfSetSchedulerMove_Body( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->status = rtems_task_set_scheduler( + RTEMS_SELF, + SCHEDULER_B_ID, + PRIO_NORMAL + ); +} + +static void RtemsTaskReqPerfSetSchedulerMove_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfSetSchedulerMove_Body( ctx ); +} + +/** + * @brief Discard samples interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfSetSchedulerMove_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + SetSelfScheduler( SCHEDULER_A_ID, PRIO_NORMAL ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfSetSchedulerMove_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfSetSchedulerMove_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Restore the runner affinity. + */ +static void RtemsTaskReqPerfSetSchedulerMove_Cleanup( + RtemsTaskValPerf_Context *ctx +) +{ + SetSelfAffinityOne( 0 ); +} + +/** @} */ +#endif + +/** + * @defgroup RtemsTaskReqPerfSetSchedulerNop \ + * spec:/rtems/task/req/perf-set-scheduler-nop + * + * @{ + */ + +/** + * @brief Set the scheduler of the runner. + */ +static void RtemsTaskReqPerfSetSchedulerNop_Body( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->status = rtems_task_set_scheduler( + RTEMS_SELF, + SCHEDULER_A_ID, + PRIO_NORMAL + ); +} + +static void RtemsTaskReqPerfSetSchedulerNop_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfSetSchedulerNop_Body( ctx ); +} + +/** + * @brief Discard samples interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfSetSchedulerNop_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfSetSchedulerNop_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfSetSchedulerNop_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** @} */ + +#if defined(RTEMS_SMP) +/** + * @defgroup RtemsTaskReqPerfSetSchedulerOther \ + * spec:/rtems/task/req/perf-set-scheduler-other + * + * @{ + */ + +/** + * @brief Create and start a worker task for scheduler B. + */ +static void RtemsTaskReqPerfSetSchedulerOther_Prepare( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL ); + SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +/** + * @brief Move the worker to scheduler A. + */ +static void RtemsTaskReqPerfSetSchedulerOther_Body( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->status = rtems_task_set_scheduler( + ctx->worker_id, + SCHEDULER_A_ID, + PRIO_LOW + ); +} + +static void RtemsTaskReqPerfSetSchedulerOther_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfSetSchedulerOther_Body( ctx ); +} + +/** + * @brief Move the worker back to scheduler B. Discard samples interrupted by + * a clock tick. + */ +static bool RtemsTaskReqPerfSetSchedulerOther_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfSetSchedulerOther_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfSetSchedulerOther_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Delete the worker task. + */ +static void RtemsTaskReqPerfSetSchedulerOther_Cleanup( + RtemsTaskValPerf_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +/** @} */ +#endif + +#if defined(RTEMS_SMP) +/** + * @defgroup RtemsTaskReqPerfSetSchedulerPreempt \ + * spec:/rtems/task/req/perf-set-scheduler-preempt + * + * @{ + */ + +/** + * @brief Create and start two worker tasks for scheduler B. Make the second + * worker busy. + */ +static void RtemsTaskReqPerfSetSchedulerPreempt_Prepare( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL ); + SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL ); + StartTask( ctx->worker_id, Worker, ctx ); + Send( ctx, EVENT_SET_END ); + WaitForNextTask( 1, ctx->worker_id ); + + ctx->worker_2_id = CreateTask( "WRK2", PRIO_NORMAL ); + SetScheduler( ctx->worker_2_id, SCHEDULER_B_ID, PRIO_HIGH ); + StartTask( ctx->worker_2_id, Worker, ctx ); + SendEvents( ctx->worker_2_id, EVENT_BUSY ); + SuspendTask( ctx->worker_2_id ); +} + +/** + * @brief Move the worker to scheduler B. Make the worker ready to set the end + * time. + */ +static void RtemsTaskReqPerfSetSchedulerPreempt_Setup( + RtemsTaskValPerf_Context *ctx +) +{ + ResumeTask( ctx->worker_2_id ); + SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL ); + Send( ctx, EVENT_SET_END ); +} + +static void RtemsTaskReqPerfSetSchedulerPreempt_Setup_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfSetSchedulerPreempt_Setup( ctx ); +} + +/** + * @brief Move the worker to scheduler A. + */ +static void RtemsTaskReqPerfSetSchedulerPreempt_Body( + RtemsTaskValPerf_Context *ctx +) +{ + ctx->begin = T_tick(); + ctx->status = rtems_task_set_scheduler( + ctx->worker_id, + SCHEDULER_A_ID, + PRIO_HIGH + ); +} + +static void RtemsTaskReqPerfSetSchedulerPreempt_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfSetSchedulerPreempt_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsTaskReqPerfSetSchedulerPreempt_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + SuspendTask( ctx->worker_2_id ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfSetSchedulerPreempt_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfSetSchedulerPreempt_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Delete the worker tasks. + */ +static void RtemsTaskReqPerfSetSchedulerPreempt_Cleanup( + RtemsTaskValPerf_Context *ctx +) +{ + ResumeTask( ctx->worker_2_id ); + DeleteTask( ctx->worker_2_id ); + DeleteTask( ctx->worker_id ); +} + +/** @} */ +#endif + +/** + * @defgroup RtemsTaskReqPerfStart spec:/rtems/task/req/perf-start + * + * @{ + */ + +/** + * @brief Create a worker task. + */ +static void RtemsTaskReqPerfStart_Setup( RtemsTaskValPerf_Context *ctx ) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); +} + +static void RtemsTaskReqPerfStart_Setup_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfStart_Setup( ctx ); +} + +/** + * @brief Start the worker task. + */ +static void RtemsTaskReqPerfStart_Body( RtemsTaskValPerf_Context *ctx ) +{ + ctx->status = rtems_task_start( + ctx->worker_id, + Worker, + (rtems_task_argument) ctx + ); +} + +static void RtemsTaskReqPerfStart_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfStart_Body( ctx ); +} + +/** + * @brief Delete the worker. Discard samples interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfStart_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + DeleteTask( ctx->worker_id ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfStart_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfStart_Teardown( ctx, delta, tic, toc, retry ); +} + +/** @} */ + +/** + * @defgroup RtemsTaskReqPerfStartPreempt \ + * spec:/rtems/task/req/perf-start-preempt + * + * @{ + */ + +/** + * @brief Create a worker task. + */ +static void RtemsTaskReqPerfStartPreempt_Setup( RtemsTaskValPerf_Context *ctx ) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); +} + +static void RtemsTaskReqPerfStartPreempt_Setup_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfStartPreempt_Setup( ctx ); +} + +/** + * @brief Start the worker task. + */ +static void RtemsTaskReqPerfStartPreempt_Body( RtemsTaskValPerf_Context *ctx ) +{ + ctx->begin = T_tick(); + ctx->status = rtems_task_start( + ctx->worker_id, + Worker, + (rtems_task_argument) ctx + ); +} + +static void RtemsTaskReqPerfStartPreempt_Body_Wrap( void *arg ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + RtemsTaskReqPerfStartPreempt_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Delete the worker. Discard samples + * interrupted by a clock tick. + */ +static bool RtemsTaskReqPerfStartPreempt_Teardown( + RtemsTaskValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + DeleteTask( ctx->worker_id ); + + return tic == toc; +} + +static bool RtemsTaskReqPerfStartPreempt_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = arg; + return RtemsTaskReqPerfStartPreempt_Teardown( ctx, delta, tic, toc, retry ); +} + +/** @} */ + +/** + * @fn void T_case_body_RtemsTaskValPerf( void ) + */ +T_TEST_CASE_FIXTURE( RtemsTaskValPerf, &RtemsTaskValPerf_Fixture ) +{ + RtemsTaskValPerf_Context *ctx; + + ctx = T_fixture_context(); + + ctx->request.name = "RtemsTaskReqPerfConstruct"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfConstruct_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfConstruct_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + RtemsTaskReqPerfRestart_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfRestart"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfRestart_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfRestart_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfRestart_Cleanup( ctx ); + + RtemsTaskReqPerfRestartPreempt_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfRestartPreempt"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfRestartPreempt_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfRestartPreempt_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfRestartPreempt_Cleanup( ctx ); + + RtemsTaskReqPerfRestartSelf_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfRestartSelf"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfRestartSelf_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfRestartSelf_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfRestartSelf_Cleanup( ctx ); + + #if defined(RTEMS_SMP) + RtemsTaskReqPerfSetSchedulerMove_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfSetSchedulerMove"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfSetSchedulerMove_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfSetSchedulerMove_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfSetSchedulerMove_Cleanup( ctx ); + #endif + + ctx->request.name = "RtemsTaskReqPerfSetSchedulerNop"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfSetSchedulerNop_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfSetSchedulerNop_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + #if defined(RTEMS_SMP) + RtemsTaskReqPerfSetSchedulerOther_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfSetSchedulerOther"; + ctx->request.setup = NULL; + ctx->request.body = RtemsTaskReqPerfSetSchedulerOther_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfSetSchedulerOther_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfSetSchedulerOther_Cleanup( ctx ); + #endif + + #if defined(RTEMS_SMP) + RtemsTaskReqPerfSetSchedulerPreempt_Prepare( ctx ); + ctx->request.name = "RtemsTaskReqPerfSetSchedulerPreempt"; + ctx->request.setup = RtemsTaskReqPerfSetSchedulerPreempt_Setup_Wrap; + ctx->request.body = RtemsTaskReqPerfSetSchedulerPreempt_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfSetSchedulerPreempt_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsTaskReqPerfSetSchedulerPreempt_Cleanup( ctx ); + #endif + + ctx->request.name = "RtemsTaskReqPerfStart"; + ctx->request.setup = RtemsTaskReqPerfStart_Setup_Wrap; + ctx->request.body = RtemsTaskReqPerfStart_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfStart_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + ctx->request.name = "RtemsTaskReqPerfStartPreempt"; + ctx->request.setup = RtemsTaskReqPerfStartPreempt_Setup_Wrap; + ctx->request.body = RtemsTaskReqPerfStartPreempt_Body_Wrap; + ctx->request.teardown = RtemsTaskReqPerfStartPreempt_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); +} + +/** @} */ |