Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:52

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsTaskValPerf
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
0049  */
0050 
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include <rtems.h>
0056 
0057 #include "ts-config.h"
0058 #include "tx-support.h"
0059 
0060 #include <rtems/test.h>
0061 
0062 /**
0063  * @defgroup RtemsTaskValPerf spec:/rtems/task/val/perf
0064  *
0065  * @ingroup TestsuitesPerformanceNoClock0
0066  *
0067  * @brief This test case provides a context to run @ref RTEMSAPIClassicTasks
0068  *   performance tests.
0069  *
0070  * @{
0071  */
0072 
0073 /**
0074  * @brief Test context for spec:/rtems/task/val/perf test case.
0075  */
0076 typedef struct {
0077   /**
0078    * @brief This member provides a worker identifier.
0079    */
0080   rtems_id worker_id;
0081 
0082   /**
0083    * @brief This member provides a second worker identifier.
0084    */
0085   rtems_id worker_2_id;
0086 
0087   /**
0088    * @brief This member provides a status code.
0089    */
0090   rtems_status_code status;
0091 
0092   /**
0093    * @brief This member references the measure runtime context.
0094    */
0095   T_measure_runtime_context *context;
0096 
0097   /**
0098    * @brief This member provides the measure runtime request.
0099    */
0100   T_measure_runtime_request request;
0101 
0102   /**
0103    * @brief This member provides an optional measurement begin time point.
0104    */
0105   T_ticks begin;
0106 
0107   /**
0108    * @brief This member provides an optional measurement end time point.
0109    */
0110   T_ticks end;
0111 } RtemsTaskValPerf_Context;
0112 
0113 static RtemsTaskValPerf_Context
0114   RtemsTaskValPerf_Instance;
0115 
0116 #define EVENT_RESTART RTEMS_EVENT_0
0117 
0118 #define EVENT_SET_END RTEMS_EVENT_1
0119 
0120 #define EVENT_BUSY RTEMS_EVENT_2
0121 
0122 typedef RtemsTaskValPerf_Context Context;
0123 
0124 RTEMS_ALIGNED( RTEMS_TASK_STORAGE_ALIGNMENT ) static char task_storage[
0125   RTEMS_TASK_STORAGE_SIZE(
0126     TEST_MAXIMUM_TLS_SIZE + TEST_MINIMUM_STACK_SIZE,
0127     RTEMS_DEFAULT_ATTRIBUTES
0128   )
0129 ];
0130 
0131 static const rtems_task_config config = {
0132   .name = OBJECT_NAME,
0133   .initial_priority = PRIO_NORMAL,
0134   .storage_area = task_storage,
0135   .storage_size = sizeof( task_storage ),
0136   .maximum_thread_local_storage_size = 0,
0137   .initial_modes = RTEMS_DEFAULT_MODES,
0138   .attributes = RTEMS_DEFAULT_ATTRIBUTES
0139 };
0140 
0141 static void Send( const Context *ctx, rtems_event_set events )
0142 {
0143   SendEvents( ctx->worker_id, events );
0144 }
0145 
0146 static void Worker( rtems_task_argument arg )
0147 {
0148   Context *ctx;
0149 
0150   ctx = (Context *) arg;
0151   ctx->end = T_tick();
0152 
0153   while ( true ) {
0154     rtems_event_set events;
0155     T_ticks         ticks;
0156 
0157     events = ReceiveAnyEvents();
0158     ticks = T_tick();
0159 
0160     if ( ( events & EVENT_RESTART ) != 0 ) {
0161       ctx->begin = T_tick();
0162       (void) rtems_task_restart( RTEMS_SELF, (rtems_task_argument) ctx );
0163     }
0164 
0165     if ( ( events & EVENT_SET_END ) != 0 ) {
0166       ctx->end = ticks;
0167     }
0168 
0169     if ( ( events & EVENT_BUSY ) != 0 ) {
0170       (void) _CPU_Thread_Idle_body( 0 );
0171     }
0172   }
0173 }
0174 
0175 static void RtemsTaskValPerf_Setup_Context( RtemsTaskValPerf_Context *ctx )
0176 {
0177   T_measure_runtime_config config;
0178 
0179   memset( &config, 0, sizeof( config ) );
0180   config.sample_count = 100;
0181   ctx->request.arg = ctx;
0182   ctx->request.flags = T_MEASURE_RUNTIME_REPORT_SAMPLES;
0183   ctx->context = T_measure_runtime_create( &config );
0184   T_assert_not_null( ctx->context );
0185 }
0186 
0187 /**
0188  * @brief Set the runner priority.
0189  */
0190 static void RtemsTaskValPerf_Setup( RtemsTaskValPerf_Context *ctx )
0191 {
0192   SetSelfPriority( PRIO_NORMAL );
0193 }
0194 
0195 static void RtemsTaskValPerf_Setup_Wrap( void *arg )
0196 {
0197   RtemsTaskValPerf_Context *ctx;
0198 
0199   ctx = arg;
0200   RtemsTaskValPerf_Setup_Context( ctx );
0201   RtemsTaskValPerf_Setup( ctx );
0202 }
0203 
0204 /**
0205  * @brief Restore the runner priority.
0206  */
0207 static void RtemsTaskValPerf_Teardown( RtemsTaskValPerf_Context *ctx )
0208 {
0209   RestoreRunnerPriority();
0210 }
0211 
0212 static void RtemsTaskValPerf_Teardown_Wrap( void *arg )
0213 {
0214   RtemsTaskValPerf_Context *ctx;
0215 
0216   ctx = arg;
0217   RtemsTaskValPerf_Teardown( ctx );
0218 }
0219 
0220 static T_fixture RtemsTaskValPerf_Fixture = {
0221   .setup = RtemsTaskValPerf_Setup_Wrap,
0222   .stop = NULL,
0223   .teardown = RtemsTaskValPerf_Teardown_Wrap,
0224   .scope = NULL,
0225   .initial_context = &RtemsTaskValPerf_Instance
0226 };
0227 
0228 /**
0229  * @defgroup RtemsTaskReqPerfConstruct spec:/rtems/task/req/perf-construct
0230  *
0231  * @{
0232  */
0233 
0234 /**
0235  * @brief Construct a worker task.
0236  */
0237 static void RtemsTaskReqPerfConstruct_Body( RtemsTaskValPerf_Context *ctx )
0238 {
0239   ctx->status = rtems_task_construct( &config, &ctx->worker_id );
0240 }
0241 
0242 static void RtemsTaskReqPerfConstruct_Body_Wrap( void *arg )
0243 {
0244   RtemsTaskValPerf_Context *ctx;
0245 
0246   ctx = arg;
0247   RtemsTaskReqPerfConstruct_Body( ctx );
0248 }
0249 
0250 /**
0251  * @brief Delete the worker.  Discard samples interrupted by a clock tick.
0252  */
0253 static bool RtemsTaskReqPerfConstruct_Teardown(
0254   RtemsTaskValPerf_Context *ctx,
0255   T_ticks                  *delta,
0256   uint32_t                  tic,
0257   uint32_t                  toc,
0258   unsigned int              retry
0259 )
0260 {
0261   T_quiet_rsc_success( ctx->status );
0262 
0263   DeleteTask( ctx->worker_id );
0264   KillZombies();
0265 
0266   return tic == toc;
0267 }
0268 
0269 static bool RtemsTaskReqPerfConstruct_Teardown_Wrap(
0270   void        *arg,
0271   T_ticks     *delta,
0272   uint32_t     tic,
0273   uint32_t     toc,
0274   unsigned int retry
0275 )
0276 {
0277   RtemsTaskValPerf_Context *ctx;
0278 
0279   ctx = arg;
0280   return RtemsTaskReqPerfConstruct_Teardown( ctx, delta, tic, toc, retry );
0281 }
0282 
0283 /** @} */
0284 
0285 /**
0286  * @defgroup RtemsTaskReqPerfRestart spec:/rtems/task/req/perf-restart
0287  *
0288  * @{
0289  */
0290 
0291 /**
0292  * @brief Create and start a worker task.
0293  */
0294 static void RtemsTaskReqPerfRestart_Prepare( RtemsTaskValPerf_Context *ctx )
0295 {
0296   ctx->worker_id = CreateTask( "WORK", PRIO_LOW );
0297   StartTask( ctx->worker_id, Worker, ctx );
0298 }
0299 
0300 /**
0301  * @brief Restart the worker task.
0302  */
0303 static void RtemsTaskReqPerfRestart_Body( RtemsTaskValPerf_Context *ctx )
0304 {
0305   ctx->status = rtems_task_restart(
0306     ctx->worker_id,
0307     (rtems_task_argument) ctx
0308   );
0309 }
0310 
0311 static void RtemsTaskReqPerfRestart_Body_Wrap( void *arg )
0312 {
0313   RtemsTaskValPerf_Context *ctx;
0314 
0315   ctx = arg;
0316   RtemsTaskReqPerfRestart_Body( ctx );
0317 }
0318 
0319 /**
0320  * @brief Discard samples interrupted by a clock tick.
0321  */
0322 static bool RtemsTaskReqPerfRestart_Teardown(
0323   RtemsTaskValPerf_Context *ctx,
0324   T_ticks                  *delta,
0325   uint32_t                  tic,
0326   uint32_t                  toc,
0327   unsigned int              retry
0328 )
0329 {
0330   T_quiet_rsc_success( ctx->status );
0331 
0332   return tic == toc;
0333 }
0334 
0335 static bool RtemsTaskReqPerfRestart_Teardown_Wrap(
0336   void        *arg,
0337   T_ticks     *delta,
0338   uint32_t     tic,
0339   uint32_t     toc,
0340   unsigned int retry
0341 )
0342 {
0343   RtemsTaskValPerf_Context *ctx;
0344 
0345   ctx = arg;
0346   return RtemsTaskReqPerfRestart_Teardown( ctx, delta, tic, toc, retry );
0347 }
0348 
0349 /**
0350  * @brief Delete the worker task.
0351  */
0352 static void RtemsTaskReqPerfRestart_Cleanup( RtemsTaskValPerf_Context *ctx )
0353 {
0354   DeleteTask( ctx->worker_id );
0355 }
0356 
0357 /** @} */
0358 
0359 /**
0360  * @defgroup RtemsTaskReqPerfRestartPreempt \
0361  *   spec:/rtems/task/req/perf-restart-preempt
0362  *
0363  * @{
0364  */
0365 
0366 /**
0367  * @brief Create and start a worker task.
0368  */
0369 static void RtemsTaskReqPerfRestartPreempt_Prepare(
0370   RtemsTaskValPerf_Context *ctx
0371 )
0372 {
0373   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0374   StartTask( ctx->worker_id, Worker, ctx );
0375 }
0376 
0377 /**
0378  * @brief Restart the worker task.
0379  */
0380 static void RtemsTaskReqPerfRestartPreempt_Body(
0381   RtemsTaskValPerf_Context *ctx
0382 )
0383 {
0384   ctx->begin = T_tick();
0385   ctx->status = rtems_task_restart(
0386     ctx->worker_id,
0387     (rtems_task_argument) ctx
0388   );
0389 }
0390 
0391 static void RtemsTaskReqPerfRestartPreempt_Body_Wrap( void *arg )
0392 {
0393   RtemsTaskValPerf_Context *ctx;
0394 
0395   ctx = arg;
0396   RtemsTaskReqPerfRestartPreempt_Body( ctx );
0397 }
0398 
0399 /**
0400  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0401  *   tick.
0402  */
0403 static bool RtemsTaskReqPerfRestartPreempt_Teardown(
0404   RtemsTaskValPerf_Context *ctx,
0405   T_ticks                  *delta,
0406   uint32_t                  tic,
0407   uint32_t                  toc,
0408   unsigned int              retry
0409 )
0410 {
0411   T_quiet_rsc_success( ctx->status );
0412 
0413   *delta = ctx->end - ctx->begin;
0414 
0415   return tic == toc;
0416 }
0417 
0418 static bool RtemsTaskReqPerfRestartPreempt_Teardown_Wrap(
0419   void        *arg,
0420   T_ticks     *delta,
0421   uint32_t     tic,
0422   uint32_t     toc,
0423   unsigned int retry
0424 )
0425 {
0426   RtemsTaskValPerf_Context *ctx;
0427 
0428   ctx = arg;
0429   return RtemsTaskReqPerfRestartPreempt_Teardown(
0430     ctx,
0431     delta,
0432     tic,
0433     toc,
0434     retry
0435   );
0436 }
0437 
0438 /**
0439  * @brief Delete the worker task.
0440  */
0441 static void RtemsTaskReqPerfRestartPreempt_Cleanup(
0442   RtemsTaskValPerf_Context *ctx
0443 )
0444 {
0445   DeleteTask( ctx->worker_id );
0446 }
0447 
0448 /** @} */
0449 
0450 /**
0451  * @defgroup RtemsTaskReqPerfRestartSelf spec:/rtems/task/req/perf-restart-self
0452  *
0453  * @{
0454  */
0455 
0456 /**
0457  * @brief Create and start a worker task.
0458  */
0459 static void RtemsTaskReqPerfRestartSelf_Prepare(
0460   RtemsTaskValPerf_Context *ctx
0461 )
0462 {
0463   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0464   StartTask( ctx->worker_id, Worker, ctx );
0465 }
0466 
0467 /**
0468  * @brief Restart the worker task.
0469  */
0470 static void RtemsTaskReqPerfRestartSelf_Body( RtemsTaskValPerf_Context *ctx )
0471 {
0472   Send( ctx, EVENT_RESTART );
0473 }
0474 
0475 static void RtemsTaskReqPerfRestartSelf_Body_Wrap( void *arg )
0476 {
0477   RtemsTaskValPerf_Context *ctx;
0478 
0479   ctx = arg;
0480   RtemsTaskReqPerfRestartSelf_Body( ctx );
0481 }
0482 
0483 /**
0484  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0485  *   tick.
0486  */
0487 static bool RtemsTaskReqPerfRestartSelf_Teardown(
0488   RtemsTaskValPerf_Context *ctx,
0489   T_ticks                  *delta,
0490   uint32_t                  tic,
0491   uint32_t                  toc,
0492   unsigned int              retry
0493 )
0494 {
0495   T_quiet_rsc_success( ctx->status );
0496 
0497   *delta = ctx->end - ctx->begin;
0498 
0499   return tic == toc;
0500 }
0501 
0502 static bool RtemsTaskReqPerfRestartSelf_Teardown_Wrap(
0503   void        *arg,
0504   T_ticks     *delta,
0505   uint32_t     tic,
0506   uint32_t     toc,
0507   unsigned int retry
0508 )
0509 {
0510   RtemsTaskValPerf_Context *ctx;
0511 
0512   ctx = arg;
0513   return RtemsTaskReqPerfRestartSelf_Teardown( ctx, delta, tic, toc, retry );
0514 }
0515 
0516 /**
0517  * @brief Delete the worker task.
0518  */
0519 static void RtemsTaskReqPerfRestartSelf_Cleanup(
0520   RtemsTaskValPerf_Context *ctx
0521 )
0522 {
0523   DeleteTask( ctx->worker_id );
0524 }
0525 
0526 /** @} */
0527 
0528 #if defined(RTEMS_SMP)
0529 /**
0530  * @defgroup RtemsTaskReqPerfSetSchedulerMove \
0531  *   spec:/rtems/task/req/perf-set-scheduler-move
0532  *
0533  * @{
0534  */
0535 
0536 /**
0537  * @brief Set the runner affinity.
0538  */
0539 static void RtemsTaskReqPerfSetSchedulerMove_Prepare(
0540   RtemsTaskValPerf_Context *ctx
0541 )
0542 {
0543   SetSelfAffinityAll();
0544 }
0545 
0546 /**
0547  * @brief Set the scheduler of the runner.
0548  */
0549 static void RtemsTaskReqPerfSetSchedulerMove_Body(
0550   RtemsTaskValPerf_Context *ctx
0551 )
0552 {
0553   ctx->status = rtems_task_set_scheduler(
0554     RTEMS_SELF,
0555     SCHEDULER_B_ID,
0556     PRIO_NORMAL
0557   );
0558 }
0559 
0560 static void RtemsTaskReqPerfSetSchedulerMove_Body_Wrap( void *arg )
0561 {
0562   RtemsTaskValPerf_Context *ctx;
0563 
0564   ctx = arg;
0565   RtemsTaskReqPerfSetSchedulerMove_Body( ctx );
0566 }
0567 
0568 /**
0569  * @brief Discard samples interrupted by a clock tick.
0570  */
0571 static bool RtemsTaskReqPerfSetSchedulerMove_Teardown(
0572   RtemsTaskValPerf_Context *ctx,
0573   T_ticks                  *delta,
0574   uint32_t                  tic,
0575   uint32_t                  toc,
0576   unsigned int              retry
0577 )
0578 {
0579   T_quiet_rsc_success( ctx->status );
0580 
0581   SetSelfScheduler( SCHEDULER_A_ID, PRIO_NORMAL );
0582 
0583   return tic == toc;
0584 }
0585 
0586 static bool RtemsTaskReqPerfSetSchedulerMove_Teardown_Wrap(
0587   void        *arg,
0588   T_ticks     *delta,
0589   uint32_t     tic,
0590   uint32_t     toc,
0591   unsigned int retry
0592 )
0593 {
0594   RtemsTaskValPerf_Context *ctx;
0595 
0596   ctx = arg;
0597   return RtemsTaskReqPerfSetSchedulerMove_Teardown(
0598     ctx,
0599     delta,
0600     tic,
0601     toc,
0602     retry
0603   );
0604 }
0605 
0606 /**
0607  * @brief Restore the runner affinity.
0608  */
0609 static void RtemsTaskReqPerfSetSchedulerMove_Cleanup(
0610   RtemsTaskValPerf_Context *ctx
0611 )
0612 {
0613   SetSelfAffinityOne( 0 );
0614 }
0615 
0616 /** @} */
0617 #endif
0618 
0619 /**
0620  * @defgroup RtemsTaskReqPerfSetSchedulerNop \
0621  *   spec:/rtems/task/req/perf-set-scheduler-nop
0622  *
0623  * @{
0624  */
0625 
0626 /**
0627  * @brief Set the scheduler of the runner.
0628  */
0629 static void RtemsTaskReqPerfSetSchedulerNop_Body(
0630   RtemsTaskValPerf_Context *ctx
0631 )
0632 {
0633   ctx->status = rtems_task_set_scheduler(
0634     RTEMS_SELF,
0635     SCHEDULER_A_ID,
0636     PRIO_NORMAL
0637   );
0638 }
0639 
0640 static void RtemsTaskReqPerfSetSchedulerNop_Body_Wrap( void *arg )
0641 {
0642   RtemsTaskValPerf_Context *ctx;
0643 
0644   ctx = arg;
0645   RtemsTaskReqPerfSetSchedulerNop_Body( ctx );
0646 }
0647 
0648 /**
0649  * @brief Discard samples interrupted by a clock tick.
0650  */
0651 static bool RtemsTaskReqPerfSetSchedulerNop_Teardown(
0652   RtemsTaskValPerf_Context *ctx,
0653   T_ticks                  *delta,
0654   uint32_t                  tic,
0655   uint32_t                  toc,
0656   unsigned int              retry
0657 )
0658 {
0659   T_quiet_rsc_success( ctx->status );
0660 
0661   return tic == toc;
0662 }
0663 
0664 static bool RtemsTaskReqPerfSetSchedulerNop_Teardown_Wrap(
0665   void        *arg,
0666   T_ticks     *delta,
0667   uint32_t     tic,
0668   uint32_t     toc,
0669   unsigned int retry
0670 )
0671 {
0672   RtemsTaskValPerf_Context *ctx;
0673 
0674   ctx = arg;
0675   return RtemsTaskReqPerfSetSchedulerNop_Teardown(
0676     ctx,
0677     delta,
0678     tic,
0679     toc,
0680     retry
0681   );
0682 }
0683 
0684 /** @} */
0685 
0686 #if defined(RTEMS_SMP)
0687 /**
0688  * @defgroup RtemsTaskReqPerfSetSchedulerOther \
0689  *   spec:/rtems/task/req/perf-set-scheduler-other
0690  *
0691  * @{
0692  */
0693 
0694 /**
0695  * @brief Create and start a worker task for scheduler B.
0696  */
0697 static void RtemsTaskReqPerfSetSchedulerOther_Prepare(
0698   RtemsTaskValPerf_Context *ctx
0699 )
0700 {
0701   ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL );
0702   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0703   StartTask( ctx->worker_id, Worker, ctx );
0704 }
0705 
0706 /**
0707  * @brief Move the worker to scheduler A.
0708  */
0709 static void RtemsTaskReqPerfSetSchedulerOther_Body(
0710   RtemsTaskValPerf_Context *ctx
0711 )
0712 {
0713   ctx->status = rtems_task_set_scheduler(
0714     ctx->worker_id,
0715     SCHEDULER_A_ID,
0716     PRIO_LOW
0717   );
0718 }
0719 
0720 static void RtemsTaskReqPerfSetSchedulerOther_Body_Wrap( void *arg )
0721 {
0722   RtemsTaskValPerf_Context *ctx;
0723 
0724   ctx = arg;
0725   RtemsTaskReqPerfSetSchedulerOther_Body( ctx );
0726 }
0727 
0728 /**
0729  * @brief Move the worker back to scheduler B.  Discard samples interrupted by
0730  *   a clock tick.
0731  */
0732 static bool RtemsTaskReqPerfSetSchedulerOther_Teardown(
0733   RtemsTaskValPerf_Context *ctx,
0734   T_ticks                  *delta,
0735   uint32_t                  tic,
0736   uint32_t                  toc,
0737   unsigned int              retry
0738 )
0739 {
0740   T_quiet_rsc_success( ctx->status );
0741 
0742   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0743 
0744   return tic == toc;
0745 }
0746 
0747 static bool RtemsTaskReqPerfSetSchedulerOther_Teardown_Wrap(
0748   void        *arg,
0749   T_ticks     *delta,
0750   uint32_t     tic,
0751   uint32_t     toc,
0752   unsigned int retry
0753 )
0754 {
0755   RtemsTaskValPerf_Context *ctx;
0756 
0757   ctx = arg;
0758   return RtemsTaskReqPerfSetSchedulerOther_Teardown(
0759     ctx,
0760     delta,
0761     tic,
0762     toc,
0763     retry
0764   );
0765 }
0766 
0767 /**
0768  * @brief Delete the worker task.
0769  */
0770 static void RtemsTaskReqPerfSetSchedulerOther_Cleanup(
0771   RtemsTaskValPerf_Context *ctx
0772 )
0773 {
0774   DeleteTask( ctx->worker_id );
0775 }
0776 
0777 /** @} */
0778 #endif
0779 
0780 #if defined(RTEMS_SMP)
0781 /**
0782  * @defgroup RtemsTaskReqPerfSetSchedulerPreempt \
0783  *   spec:/rtems/task/req/perf-set-scheduler-preempt
0784  *
0785  * @{
0786  */
0787 
0788 /**
0789  * @brief Create and start two worker tasks for scheduler B.  Make the second
0790  *   worker busy.
0791  */
0792 static void RtemsTaskReqPerfSetSchedulerPreempt_Prepare(
0793   RtemsTaskValPerf_Context *ctx
0794 )
0795 {
0796   ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL );
0797   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0798   StartTask( ctx->worker_id, Worker, ctx );
0799   Send( ctx, EVENT_SET_END );
0800   WaitForNextTask( 1, ctx->worker_id );
0801 
0802   ctx->worker_2_id = CreateTask( "WRK2", PRIO_NORMAL );
0803   SetScheduler( ctx->worker_2_id, SCHEDULER_B_ID, PRIO_HIGH );
0804   StartTask( ctx->worker_2_id, Worker, ctx );
0805   SendEvents( ctx->worker_2_id, EVENT_BUSY );
0806   SuspendTask( ctx->worker_2_id );
0807 }
0808 
0809 /**
0810  * @brief Move the worker to scheduler B.  Make the worker ready to set the end
0811  *   time.
0812  */
0813 static void RtemsTaskReqPerfSetSchedulerPreempt_Setup(
0814   RtemsTaskValPerf_Context *ctx
0815 )
0816 {
0817   ResumeTask( ctx->worker_2_id );
0818   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0819   Send( ctx, EVENT_SET_END );
0820 }
0821 
0822 static void RtemsTaskReqPerfSetSchedulerPreempt_Setup_Wrap( void *arg )
0823 {
0824   RtemsTaskValPerf_Context *ctx;
0825 
0826   ctx = arg;
0827   RtemsTaskReqPerfSetSchedulerPreempt_Setup( ctx );
0828 }
0829 
0830 /**
0831  * @brief Move the worker to scheduler A.
0832  */
0833 static void RtemsTaskReqPerfSetSchedulerPreempt_Body(
0834   RtemsTaskValPerf_Context *ctx
0835 )
0836 {
0837   ctx->begin = T_tick();
0838   ctx->status = rtems_task_set_scheduler(
0839     ctx->worker_id,
0840     SCHEDULER_A_ID,
0841     PRIO_HIGH
0842   );
0843 }
0844 
0845 static void RtemsTaskReqPerfSetSchedulerPreempt_Body_Wrap( void *arg )
0846 {
0847   RtemsTaskValPerf_Context *ctx;
0848 
0849   ctx = arg;
0850   RtemsTaskReqPerfSetSchedulerPreempt_Body( ctx );
0851 }
0852 
0853 /**
0854  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0855  *   tick.
0856  */
0857 static bool RtemsTaskReqPerfSetSchedulerPreempt_Teardown(
0858   RtemsTaskValPerf_Context *ctx,
0859   T_ticks                  *delta,
0860   uint32_t                  tic,
0861   uint32_t                  toc,
0862   unsigned int              retry
0863 )
0864 {
0865   T_quiet_rsc_success( ctx->status );
0866 
0867   *delta = ctx->end - ctx->begin;
0868   SuspendTask( ctx->worker_2_id );
0869 
0870   return tic == toc;
0871 }
0872 
0873 static bool RtemsTaskReqPerfSetSchedulerPreempt_Teardown_Wrap(
0874   void        *arg,
0875   T_ticks     *delta,
0876   uint32_t     tic,
0877   uint32_t     toc,
0878   unsigned int retry
0879 )
0880 {
0881   RtemsTaskValPerf_Context *ctx;
0882 
0883   ctx = arg;
0884   return RtemsTaskReqPerfSetSchedulerPreempt_Teardown(
0885     ctx,
0886     delta,
0887     tic,
0888     toc,
0889     retry
0890   );
0891 }
0892 
0893 /**
0894  * @brief Delete the worker tasks.
0895  */
0896 static void RtemsTaskReqPerfSetSchedulerPreempt_Cleanup(
0897   RtemsTaskValPerf_Context *ctx
0898 )
0899 {
0900   ResumeTask( ctx->worker_2_id );
0901   DeleteTask( ctx->worker_2_id );
0902   DeleteTask( ctx->worker_id );
0903 }
0904 
0905 /** @} */
0906 #endif
0907 
0908 /**
0909  * @defgroup RtemsTaskReqPerfStart spec:/rtems/task/req/perf-start
0910  *
0911  * @{
0912  */
0913 
0914 /**
0915  * @brief Create a worker task.
0916  */
0917 static void RtemsTaskReqPerfStart_Setup( RtemsTaskValPerf_Context *ctx )
0918 {
0919   ctx->worker_id = CreateTask( "WORK", PRIO_LOW );
0920 }
0921 
0922 static void RtemsTaskReqPerfStart_Setup_Wrap( void *arg )
0923 {
0924   RtemsTaskValPerf_Context *ctx;
0925 
0926   ctx = arg;
0927   RtemsTaskReqPerfStart_Setup( ctx );
0928 }
0929 
0930 /**
0931  * @brief Start the worker task.
0932  */
0933 static void RtemsTaskReqPerfStart_Body( RtemsTaskValPerf_Context *ctx )
0934 {
0935   ctx->status = rtems_task_start(
0936     ctx->worker_id,
0937     Worker,
0938     (rtems_task_argument) ctx
0939   );
0940 }
0941 
0942 static void RtemsTaskReqPerfStart_Body_Wrap( void *arg )
0943 {
0944   RtemsTaskValPerf_Context *ctx;
0945 
0946   ctx = arg;
0947   RtemsTaskReqPerfStart_Body( ctx );
0948 }
0949 
0950 /**
0951  * @brief Delete the worker.  Discard samples interrupted by a clock tick.
0952  */
0953 static bool RtemsTaskReqPerfStart_Teardown(
0954   RtemsTaskValPerf_Context *ctx,
0955   T_ticks                  *delta,
0956   uint32_t                  tic,
0957   uint32_t                  toc,
0958   unsigned int              retry
0959 )
0960 {
0961   T_quiet_rsc_success( ctx->status );
0962 
0963   DeleteTask( ctx->worker_id );
0964 
0965   return tic == toc;
0966 }
0967 
0968 static bool RtemsTaskReqPerfStart_Teardown_Wrap(
0969   void        *arg,
0970   T_ticks     *delta,
0971   uint32_t     tic,
0972   uint32_t     toc,
0973   unsigned int retry
0974 )
0975 {
0976   RtemsTaskValPerf_Context *ctx;
0977 
0978   ctx = arg;
0979   return RtemsTaskReqPerfStart_Teardown( ctx, delta, tic, toc, retry );
0980 }
0981 
0982 /** @} */
0983 
0984 /**
0985  * @defgroup RtemsTaskReqPerfStartPreempt \
0986  *   spec:/rtems/task/req/perf-start-preempt
0987  *
0988  * @{
0989  */
0990 
0991 /**
0992  * @brief Create a worker task.
0993  */
0994 static void RtemsTaskReqPerfStartPreempt_Setup( RtemsTaskValPerf_Context *ctx )
0995 {
0996   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0997 }
0998 
0999 static void RtemsTaskReqPerfStartPreempt_Setup_Wrap( void *arg )
1000 {
1001   RtemsTaskValPerf_Context *ctx;
1002 
1003   ctx = arg;
1004   RtemsTaskReqPerfStartPreempt_Setup( ctx );
1005 }
1006 
1007 /**
1008  * @brief Start the worker task.
1009  */
1010 static void RtemsTaskReqPerfStartPreempt_Body( RtemsTaskValPerf_Context *ctx )
1011 {
1012   ctx->begin = T_tick();
1013   ctx->status = rtems_task_start(
1014     ctx->worker_id,
1015     Worker,
1016     (rtems_task_argument) ctx
1017   );
1018 }
1019 
1020 static void RtemsTaskReqPerfStartPreempt_Body_Wrap( void *arg )
1021 {
1022   RtemsTaskValPerf_Context *ctx;
1023 
1024   ctx = arg;
1025   RtemsTaskReqPerfStartPreempt_Body( ctx );
1026 }
1027 
1028 /**
1029  * @brief Set the measured runtime.  Delete the worker.  Discard samples
1030  *   interrupted by a clock tick.
1031  */
1032 static bool RtemsTaskReqPerfStartPreempt_Teardown(
1033   RtemsTaskValPerf_Context *ctx,
1034   T_ticks                  *delta,
1035   uint32_t                  tic,
1036   uint32_t                  toc,
1037   unsigned int              retry
1038 )
1039 {
1040   T_quiet_rsc_success( ctx->status );
1041 
1042   *delta = ctx->end - ctx->begin;
1043   DeleteTask( ctx->worker_id );
1044 
1045   return tic == toc;
1046 }
1047 
1048 static bool RtemsTaskReqPerfStartPreempt_Teardown_Wrap(
1049   void        *arg,
1050   T_ticks     *delta,
1051   uint32_t     tic,
1052   uint32_t     toc,
1053   unsigned int retry
1054 )
1055 {
1056   RtemsTaskValPerf_Context *ctx;
1057 
1058   ctx = arg;
1059   return RtemsTaskReqPerfStartPreempt_Teardown( ctx, delta, tic, toc, retry );
1060 }
1061 
1062 /** @} */
1063 
1064 /**
1065  * @fn void T_case_body_RtemsTaskValPerf( void )
1066  */
1067 T_TEST_CASE_FIXTURE( RtemsTaskValPerf, &RtemsTaskValPerf_Fixture )
1068 {
1069   RtemsTaskValPerf_Context *ctx;
1070 
1071   ctx = T_fixture_context();
1072 
1073   ctx->request.name = "RtemsTaskReqPerfConstruct";
1074   ctx->request.setup = NULL;
1075   ctx->request.body = RtemsTaskReqPerfConstruct_Body_Wrap;
1076   ctx->request.teardown = RtemsTaskReqPerfConstruct_Teardown_Wrap;
1077   T_measure_runtime( ctx->context, &ctx->request );
1078 
1079   RtemsTaskReqPerfRestart_Prepare( ctx );
1080   ctx->request.name = "RtemsTaskReqPerfRestart";
1081   ctx->request.setup = NULL;
1082   ctx->request.body = RtemsTaskReqPerfRestart_Body_Wrap;
1083   ctx->request.teardown = RtemsTaskReqPerfRestart_Teardown_Wrap;
1084   T_measure_runtime( ctx->context, &ctx->request );
1085   RtemsTaskReqPerfRestart_Cleanup( ctx );
1086 
1087   RtemsTaskReqPerfRestartPreempt_Prepare( ctx );
1088   ctx->request.name = "RtemsTaskReqPerfRestartPreempt";
1089   ctx->request.setup = NULL;
1090   ctx->request.body = RtemsTaskReqPerfRestartPreempt_Body_Wrap;
1091   ctx->request.teardown = RtemsTaskReqPerfRestartPreempt_Teardown_Wrap;
1092   T_measure_runtime( ctx->context, &ctx->request );
1093   RtemsTaskReqPerfRestartPreempt_Cleanup( ctx );
1094 
1095   RtemsTaskReqPerfRestartSelf_Prepare( ctx );
1096   ctx->request.name = "RtemsTaskReqPerfRestartSelf";
1097   ctx->request.setup = NULL;
1098   ctx->request.body = RtemsTaskReqPerfRestartSelf_Body_Wrap;
1099   ctx->request.teardown = RtemsTaskReqPerfRestartSelf_Teardown_Wrap;
1100   T_measure_runtime( ctx->context, &ctx->request );
1101   RtemsTaskReqPerfRestartSelf_Cleanup( ctx );
1102 
1103   #if defined(RTEMS_SMP)
1104   RtemsTaskReqPerfSetSchedulerMove_Prepare( ctx );
1105   ctx->request.name = "RtemsTaskReqPerfSetSchedulerMove";
1106   ctx->request.setup = NULL;
1107   ctx->request.body = RtemsTaskReqPerfSetSchedulerMove_Body_Wrap;
1108   ctx->request.teardown = RtemsTaskReqPerfSetSchedulerMove_Teardown_Wrap;
1109   T_measure_runtime( ctx->context, &ctx->request );
1110   RtemsTaskReqPerfSetSchedulerMove_Cleanup( ctx );
1111   #endif
1112 
1113   ctx->request.name = "RtemsTaskReqPerfSetSchedulerNop";
1114   ctx->request.setup = NULL;
1115   ctx->request.body = RtemsTaskReqPerfSetSchedulerNop_Body_Wrap;
1116   ctx->request.teardown = RtemsTaskReqPerfSetSchedulerNop_Teardown_Wrap;
1117   T_measure_runtime( ctx->context, &ctx->request );
1118 
1119   #if defined(RTEMS_SMP)
1120   RtemsTaskReqPerfSetSchedulerOther_Prepare( ctx );
1121   ctx->request.name = "RtemsTaskReqPerfSetSchedulerOther";
1122   ctx->request.setup = NULL;
1123   ctx->request.body = RtemsTaskReqPerfSetSchedulerOther_Body_Wrap;
1124   ctx->request.teardown = RtemsTaskReqPerfSetSchedulerOther_Teardown_Wrap;
1125   T_measure_runtime( ctx->context, &ctx->request );
1126   RtemsTaskReqPerfSetSchedulerOther_Cleanup( ctx );
1127   #endif
1128 
1129   #if defined(RTEMS_SMP)
1130   RtemsTaskReqPerfSetSchedulerPreempt_Prepare( ctx );
1131   ctx->request.name = "RtemsTaskReqPerfSetSchedulerPreempt";
1132   ctx->request.setup = RtemsTaskReqPerfSetSchedulerPreempt_Setup_Wrap;
1133   ctx->request.body = RtemsTaskReqPerfSetSchedulerPreempt_Body_Wrap;
1134   ctx->request.teardown = RtemsTaskReqPerfSetSchedulerPreempt_Teardown_Wrap;
1135   T_measure_runtime( ctx->context, &ctx->request );
1136   RtemsTaskReqPerfSetSchedulerPreempt_Cleanup( ctx );
1137   #endif
1138 
1139   ctx->request.name = "RtemsTaskReqPerfStart";
1140   ctx->request.setup = RtemsTaskReqPerfStart_Setup_Wrap;
1141   ctx->request.body = RtemsTaskReqPerfStart_Body_Wrap;
1142   ctx->request.teardown = RtemsTaskReqPerfStart_Teardown_Wrap;
1143   T_measure_runtime( ctx->context, &ctx->request );
1144 
1145   ctx->request.name = "RtemsTaskReqPerfStartPreempt";
1146   ctx->request.setup = RtemsTaskReqPerfStartPreempt_Setup_Wrap;
1147   ctx->request.body = RtemsTaskReqPerfStartPreempt_Body_Wrap;
1148   ctx->request.teardown = RtemsTaskReqPerfStartPreempt_Teardown_Wrap;
1149   T_measure_runtime( ctx->context, &ctx->request );
1150 }
1151 
1152 /** @} */