Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsBarrierValPerf
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 "tx-support.h"
0058 
0059 #include <rtems/test.h>
0060 
0061 /**
0062  * @defgroup RtemsBarrierValPerf spec:/rtems/barrier/val/perf
0063  *
0064  * @ingroup TestsuitesPerformanceNoClock0
0065  *
0066  * @brief This test case provides a context to run @ref RTEMSAPIClassicBarrier
0067  *   performance tests.
0068  *
0069  * @{
0070  */
0071 
0072 /**
0073  * @brief Test context for spec:/rtems/barrier/val/perf test case.
0074  */
0075 typedef struct {
0076   /**
0077    * @brief This member provides a barrier identifier.
0078    */
0079   rtems_id barrier_id;
0080 
0081   /**
0082    * @brief This member provides a worker identifier.
0083    */
0084   rtems_id worker_id;
0085 
0086   /**
0087    * @brief This member provides a status code.
0088    */
0089   rtems_status_code status;
0090 
0091   /**
0092    * @brief This member references the measure runtime context.
0093    */
0094   T_measure_runtime_context *context;
0095 
0096   /**
0097    * @brief This member provides the measure runtime request.
0098    */
0099   T_measure_runtime_request request;
0100 
0101   /**
0102    * @brief This member provides an optional measurement begin time point.
0103    */
0104   T_ticks begin;
0105 
0106   /**
0107    * @brief This member provides an optional measurement end time point.
0108    */
0109   T_ticks end;
0110 } RtemsBarrierValPerf_Context;
0111 
0112 static RtemsBarrierValPerf_Context
0113   RtemsBarrierValPerf_Instance;
0114 
0115 typedef RtemsBarrierValPerf_Context Context;
0116 
0117 static void BarrierWaitWorker( rtems_task_argument arg )
0118 {
0119   Context *ctx;
0120 
0121   ctx = (Context *) arg;
0122 
0123   while ( true ) {
0124     rtems_status_code sc;
0125 
0126     sc = rtems_barrier_wait( ctx->barrier_id, RTEMS_NO_TIMEOUT );
0127     ctx->end = T_tick();
0128     T_quiet_rsc_success( sc );
0129   }
0130 }
0131 
0132 static void RtemsBarrierValPerf_Setup_Context(
0133   RtemsBarrierValPerf_Context *ctx
0134 )
0135 {
0136   T_measure_runtime_config config;
0137 
0138   memset( &config, 0, sizeof( config ) );
0139   config.sample_count = 100;
0140   ctx->request.arg = ctx;
0141   ctx->request.flags = T_MEASURE_RUNTIME_REPORT_SAMPLES;
0142   ctx->context = T_measure_runtime_create( &config );
0143   T_assert_not_null( ctx->context );
0144 }
0145 
0146 static void RtemsBarrierValPerf_Setup_Wrap( void *arg )
0147 {
0148   RtemsBarrierValPerf_Context *ctx;
0149 
0150   ctx = arg;
0151   RtemsBarrierValPerf_Setup_Context( ctx );
0152 }
0153 
0154 static T_fixture RtemsBarrierValPerf_Fixture = {
0155   .setup = RtemsBarrierValPerf_Setup_Wrap,
0156   .stop = NULL,
0157   .teardown = NULL,
0158   .scope = NULL,
0159   .initial_context = &RtemsBarrierValPerf_Instance
0160 };
0161 
0162 /**
0163  * @defgroup RtemsBarrierReqPerfReleaseAuto \
0164  *   spec:/rtems/barrier/req/perf-release-auto
0165  *
0166  * @{
0167  */
0168 
0169 /**
0170  * @brief Create an automatic release barrier.
0171  */
0172 static void RtemsBarrierReqPerfReleaseAuto_Prepare(
0173   RtemsBarrierValPerf_Context *ctx
0174 )
0175 {
0176   rtems_status_code sc;
0177 
0178   sc = rtems_barrier_create(
0179     OBJECT_NAME,
0180     RTEMS_BARRIER_AUTOMATIC_RELEASE,
0181     1,
0182     &ctx->barrier_id
0183   );
0184   T_rsc_success( sc );
0185 }
0186 
0187 /**
0188  * @brief Automatically release the barrier.
0189  */
0190 static void RtemsBarrierReqPerfReleaseAuto_Body(
0191   RtemsBarrierValPerf_Context *ctx
0192 )
0193 {
0194   ctx->status = rtems_barrier_wait( ctx->barrier_id, RTEMS_NO_TIMEOUT );
0195 }
0196 
0197 static void RtemsBarrierReqPerfReleaseAuto_Body_Wrap( void *arg )
0198 {
0199   RtemsBarrierValPerf_Context *ctx;
0200 
0201   ctx = arg;
0202   RtemsBarrierReqPerfReleaseAuto_Body( ctx );
0203 }
0204 
0205 /**
0206  * @brief Discard samples interrupted by a clock tick.
0207  */
0208 static bool RtemsBarrierReqPerfReleaseAuto_Teardown(
0209   RtemsBarrierValPerf_Context *ctx,
0210   T_ticks                     *delta,
0211   uint32_t                     tic,
0212   uint32_t                     toc,
0213   unsigned int                 retry
0214 )
0215 {
0216   T_quiet_rsc_success( ctx->status );
0217 
0218   return tic == toc;
0219 }
0220 
0221 static bool RtemsBarrierReqPerfReleaseAuto_Teardown_Wrap(
0222   void        *arg,
0223   T_ticks     *delta,
0224   uint32_t     tic,
0225   uint32_t     toc,
0226   unsigned int retry
0227 )
0228 {
0229   RtemsBarrierValPerf_Context *ctx;
0230 
0231   ctx = arg;
0232   return RtemsBarrierReqPerfReleaseAuto_Teardown(
0233     ctx,
0234     delta,
0235     tic,
0236     toc,
0237     retry
0238   );
0239 }
0240 
0241 /**
0242  * @brief Delete the barrier and the worker.
0243  */
0244 static void RtemsBarrierReqPerfReleaseAuto_Cleanup(
0245   RtemsBarrierValPerf_Context *ctx
0246 )
0247 {
0248   rtems_status_code sc;
0249 
0250   sc = rtems_barrier_delete( ctx->barrier_id );
0251   T_rsc_success( sc );
0252 }
0253 
0254 /** @} */
0255 
0256 #if defined(RTEMS_SMP)
0257 /**
0258  * @defgroup RtemsBarrierReqPerfReleaseAutoOtherCpu \
0259  *   spec:/rtems/barrier/req/perf-release-auto-other-cpu
0260  *
0261  * @{
0262  */
0263 
0264 /**
0265  * @brief Create an automatic release barrier.  Create and start a worker task.
0266  */
0267 static void RtemsBarrierReqPerfReleaseAutoOtherCpu_Prepare(
0268   RtemsBarrierValPerf_Context *ctx
0269 )
0270 {
0271   rtems_status_code sc;
0272 
0273   sc = rtems_barrier_create(
0274     OBJECT_NAME,
0275     RTEMS_BARRIER_AUTOMATIC_RELEASE,
0276     2,
0277     &ctx->barrier_id
0278   );
0279   T_rsc_success( sc );
0280 
0281   ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL );
0282   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0283   StartTask( ctx->worker_id, BarrierWaitWorker, ctx );
0284   WaitForNextTask( 1, ctx->worker_id );
0285 }
0286 
0287 /**
0288  * @brief Automatically release the barrier.
0289  */
0290 static void RtemsBarrierReqPerfReleaseAutoOtherCpu_Body(
0291   RtemsBarrierValPerf_Context *ctx
0292 )
0293 {
0294   ctx->begin = T_tick();
0295   ctx->status = rtems_barrier_wait( ctx->barrier_id, RTEMS_NO_TIMEOUT );
0296 }
0297 
0298 static void RtemsBarrierReqPerfReleaseAutoOtherCpu_Body_Wrap( void *arg )
0299 {
0300   RtemsBarrierValPerf_Context *ctx;
0301 
0302   ctx = arg;
0303   RtemsBarrierReqPerfReleaseAutoOtherCpu_Body( ctx );
0304 }
0305 
0306 /**
0307  * @brief Make sure the worker waits for the next event.  Set the measured
0308  *   runtime. Discard samples interrupted by a clock tick.
0309  */
0310 static bool RtemsBarrierReqPerfReleaseAutoOtherCpu_Teardown(
0311   RtemsBarrierValPerf_Context *ctx,
0312   T_ticks                     *delta,
0313   uint32_t                     tic,
0314   uint32_t                     toc,
0315   unsigned int                 retry
0316 )
0317 {
0318   T_quiet_rsc_success( ctx->status );
0319 
0320   WaitForNextTask( 1, ctx->worker_id );
0321   *delta = ctx->end - ctx->begin;
0322 
0323   return tic == toc;
0324 }
0325 
0326 static bool RtemsBarrierReqPerfReleaseAutoOtherCpu_Teardown_Wrap(
0327   void        *arg,
0328   T_ticks     *delta,
0329   uint32_t     tic,
0330   uint32_t     toc,
0331   unsigned int retry
0332 )
0333 {
0334   RtemsBarrierValPerf_Context *ctx;
0335 
0336   ctx = arg;
0337   return RtemsBarrierReqPerfReleaseAutoOtherCpu_Teardown(
0338     ctx,
0339     delta,
0340     tic,
0341     toc,
0342     retry
0343   );
0344 }
0345 
0346 /**
0347  * @brief Delete the barrier and the worker.
0348  */
0349 static void RtemsBarrierReqPerfReleaseAutoOtherCpu_Cleanup(
0350   RtemsBarrierValPerf_Context *ctx
0351 )
0352 {
0353   rtems_status_code sc;
0354 
0355   DeleteTask( ctx->worker_id );
0356 
0357   sc = rtems_barrier_delete( ctx->barrier_id );
0358   T_rsc_success( sc );
0359 }
0360 
0361 /** @} */
0362 #endif
0363 
0364 /**
0365  * @defgroup RtemsBarrierReqPerfReleaseManual \
0366  *   spec:/rtems/barrier/req/perf-release-manual
0367  *
0368  * @{
0369  */
0370 
0371 /**
0372  * @brief Create a manual release barrier.  Create and start a worker task.
0373  */
0374 static void RtemsBarrierReqPerfReleaseManual_Prepare(
0375   RtemsBarrierValPerf_Context *ctx
0376 )
0377 {
0378   rtems_status_code sc;
0379 
0380   sc = rtems_barrier_create(
0381     OBJECT_NAME,
0382     RTEMS_BARRIER_MANUAL_RELEASE,
0383     0,
0384     &ctx->barrier_id
0385   );
0386   T_rsc_success( sc );
0387 
0388   SetSelfPriority( PRIO_NORMAL );
0389   ctx->worker_id = CreateTask( "WORK", PRIO_NORMAL );
0390   StartTask( ctx->worker_id, BarrierWaitWorker, ctx );
0391 }
0392 
0393 /**
0394  * @brief Make sure the worker task is fully blocked on the barrier.
0395  */
0396 static void RtemsBarrierReqPerfReleaseManual_Setup(
0397   RtemsBarrierValPerf_Context *ctx
0398 )
0399 {
0400   Yield();
0401 }
0402 
0403 static void RtemsBarrierReqPerfReleaseManual_Setup_Wrap( void *arg )
0404 {
0405   RtemsBarrierValPerf_Context *ctx;
0406 
0407   ctx = arg;
0408   RtemsBarrierReqPerfReleaseManual_Setup( ctx );
0409 }
0410 
0411 /**
0412  * @brief Release the barrier.
0413  */
0414 static void RtemsBarrierReqPerfReleaseManual_Body(
0415   RtemsBarrierValPerf_Context *ctx
0416 )
0417 {
0418   uint32_t count;
0419 
0420   ctx->status = rtems_barrier_release( ctx->barrier_id, &count );
0421 }
0422 
0423 static void RtemsBarrierReqPerfReleaseManual_Body_Wrap( void *arg )
0424 {
0425   RtemsBarrierValPerf_Context *ctx;
0426 
0427   ctx = arg;
0428   RtemsBarrierReqPerfReleaseManual_Body( ctx );
0429 }
0430 
0431 /**
0432  * @brief Discard samples interrupted by a clock tick.
0433  */
0434 static bool RtemsBarrierReqPerfReleaseManual_Teardown(
0435   RtemsBarrierValPerf_Context *ctx,
0436   T_ticks                     *delta,
0437   uint32_t                     tic,
0438   uint32_t                     toc,
0439   unsigned int                 retry
0440 )
0441 {
0442   T_quiet_rsc_success( ctx->status );
0443 
0444   return tic == toc;
0445 }
0446 
0447 static bool RtemsBarrierReqPerfReleaseManual_Teardown_Wrap(
0448   void        *arg,
0449   T_ticks     *delta,
0450   uint32_t     tic,
0451   uint32_t     toc,
0452   unsigned int retry
0453 )
0454 {
0455   RtemsBarrierValPerf_Context *ctx;
0456 
0457   ctx = arg;
0458   return RtemsBarrierReqPerfReleaseManual_Teardown(
0459     ctx,
0460     delta,
0461     tic,
0462     toc,
0463     retry
0464   );
0465 }
0466 
0467 /**
0468  * @brief Delete the barrier and the worker.
0469  */
0470 static void RtemsBarrierReqPerfReleaseManual_Cleanup(
0471   RtemsBarrierValPerf_Context *ctx
0472 )
0473 {
0474   rtems_status_code sc;
0475 
0476   DeleteTask( ctx->worker_id );
0477 
0478   sc = rtems_barrier_delete( ctx->barrier_id );
0479   T_rsc_success( sc );
0480 
0481   RestoreRunnerPriority();
0482 }
0483 
0484 /** @} */
0485 
0486 /**
0487  * @defgroup RtemsBarrierReqPerfReleaseManualPreempt \
0488  *   spec:/rtems/barrier/req/perf-release-manual-preempt
0489  *
0490  * @{
0491  */
0492 
0493 /**
0494  * @brief Create a manual release barrier.  Create and start a worker task.
0495  */
0496 static void RtemsBarrierReqPerfReleaseManualPreempt_Prepare(
0497   RtemsBarrierValPerf_Context *ctx
0498 )
0499 {
0500   rtems_status_code sc;
0501 
0502   sc = rtems_barrier_create(
0503     OBJECT_NAME,
0504     RTEMS_BARRIER_MANUAL_RELEASE,
0505     0,
0506     &ctx->barrier_id
0507   );
0508   T_rsc_success( sc );
0509 
0510   SetSelfPriority( PRIO_NORMAL );
0511   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0512   StartTask( ctx->worker_id, BarrierWaitWorker, ctx );
0513 }
0514 
0515 /**
0516  * @brief Release the barrier.
0517  */
0518 static void RtemsBarrierReqPerfReleaseManualPreempt_Body(
0519   RtemsBarrierValPerf_Context *ctx
0520 )
0521 {
0522   uint32_t count;
0523 
0524   ctx->begin = T_tick();
0525   ctx->status = rtems_barrier_release( ctx->barrier_id, &count );
0526 }
0527 
0528 static void RtemsBarrierReqPerfReleaseManualPreempt_Body_Wrap( void *arg )
0529 {
0530   RtemsBarrierValPerf_Context *ctx;
0531 
0532   ctx = arg;
0533   RtemsBarrierReqPerfReleaseManualPreempt_Body( ctx );
0534 }
0535 
0536 /**
0537  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0538  *   tick.
0539  */
0540 static bool RtemsBarrierReqPerfReleaseManualPreempt_Teardown(
0541   RtemsBarrierValPerf_Context *ctx,
0542   T_ticks                     *delta,
0543   uint32_t                     tic,
0544   uint32_t                     toc,
0545   unsigned int                 retry
0546 )
0547 {
0548   T_quiet_rsc_success( ctx->status );
0549 
0550   *delta = ctx->end - ctx->begin;
0551 
0552   return tic == toc;
0553 }
0554 
0555 static bool RtemsBarrierReqPerfReleaseManualPreempt_Teardown_Wrap(
0556   void        *arg,
0557   T_ticks     *delta,
0558   uint32_t     tic,
0559   uint32_t     toc,
0560   unsigned int retry
0561 )
0562 {
0563   RtemsBarrierValPerf_Context *ctx;
0564 
0565   ctx = arg;
0566   return RtemsBarrierReqPerfReleaseManualPreempt_Teardown(
0567     ctx,
0568     delta,
0569     tic,
0570     toc,
0571     retry
0572   );
0573 }
0574 
0575 /**
0576  * @brief Delete the barrier and the worker.
0577  */
0578 static void RtemsBarrierReqPerfReleaseManualPreempt_Cleanup(
0579   RtemsBarrierValPerf_Context *ctx
0580 )
0581 {
0582   rtems_status_code sc;
0583 
0584   DeleteTask( ctx->worker_id );
0585 
0586   sc = rtems_barrier_delete( ctx->barrier_id );
0587   T_rsc_success( sc );
0588 
0589   RestoreRunnerPriority();
0590 }
0591 
0592 /** @} */
0593 
0594 /**
0595  * @fn void T_case_body_RtemsBarrierValPerf( void )
0596  */
0597 T_TEST_CASE_FIXTURE( RtemsBarrierValPerf, &RtemsBarrierValPerf_Fixture )
0598 {
0599   RtemsBarrierValPerf_Context *ctx;
0600 
0601   ctx = T_fixture_context();
0602 
0603   RtemsBarrierReqPerfReleaseAuto_Prepare( ctx );
0604   ctx->request.name = "RtemsBarrierReqPerfReleaseAuto";
0605   ctx->request.setup = NULL;
0606   ctx->request.body = RtemsBarrierReqPerfReleaseAuto_Body_Wrap;
0607   ctx->request.teardown = RtemsBarrierReqPerfReleaseAuto_Teardown_Wrap;
0608   T_measure_runtime( ctx->context, &ctx->request );
0609   RtemsBarrierReqPerfReleaseAuto_Cleanup( ctx );
0610 
0611   #if defined(RTEMS_SMP)
0612   RtemsBarrierReqPerfReleaseAutoOtherCpu_Prepare( ctx );
0613   ctx->request.name = "RtemsBarrierReqPerfReleaseAutoOtherCpu";
0614   ctx->request.setup = NULL;
0615   ctx->request.body = RtemsBarrierReqPerfReleaseAutoOtherCpu_Body_Wrap;
0616   ctx->request.teardown = RtemsBarrierReqPerfReleaseAutoOtherCpu_Teardown_Wrap;
0617   T_measure_runtime( ctx->context, &ctx->request );
0618   RtemsBarrierReqPerfReleaseAutoOtherCpu_Cleanup( ctx );
0619   #endif
0620 
0621   RtemsBarrierReqPerfReleaseManual_Prepare( ctx );
0622   ctx->request.name = "RtemsBarrierReqPerfReleaseManual";
0623   ctx->request.setup = RtemsBarrierReqPerfReleaseManual_Setup_Wrap;
0624   ctx->request.body = RtemsBarrierReqPerfReleaseManual_Body_Wrap;
0625   ctx->request.teardown = RtemsBarrierReqPerfReleaseManual_Teardown_Wrap;
0626   T_measure_runtime( ctx->context, &ctx->request );
0627   RtemsBarrierReqPerfReleaseManual_Cleanup( ctx );
0628 
0629   RtemsBarrierReqPerfReleaseManualPreempt_Prepare( ctx );
0630   ctx->request.name = "RtemsBarrierReqPerfReleaseManualPreempt";
0631   ctx->request.setup = NULL;
0632   ctx->request.body = RtemsBarrierReqPerfReleaseManualPreempt_Body_Wrap;
0633   ctx->request.teardown = RtemsBarrierReqPerfReleaseManualPreempt_Teardown_Wrap;
0634   T_measure_runtime( ctx->context, &ctx->request );
0635   RtemsBarrierReqPerfReleaseManualPreempt_Cleanup( ctx );
0636 }
0637 
0638 /** @} */