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 RtemsEventValPerf
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 RtemsEventValPerf spec:/rtems/event/val/perf
0063  *
0064  * @ingroup TestsuitesPerformanceNoClock0
0065  *
0066  * @brief This test case provides a context to run @ref RTEMSAPIClassicEvent
0067  *   performance tests.
0068  *
0069  * @{
0070  */
0071 
0072 /**
0073  * @brief Test context for spec:/rtems/event/val/perf test case.
0074  */
0075 typedef struct {
0076   /**
0077    * @brief This member provides a worker identifier.
0078    */
0079   rtems_id worker_id;
0080 
0081   /**
0082    * @brief This member provides a status code.
0083    */
0084   rtems_status_code status;
0085 
0086   /**
0087    * @brief This member references the measure runtime context.
0088    */
0089   T_measure_runtime_context *context;
0090 
0091   /**
0092    * @brief This member provides the measure runtime request.
0093    */
0094   T_measure_runtime_request request;
0095 
0096   /**
0097    * @brief This member provides an optional measurement begin time point.
0098    */
0099   T_ticks begin;
0100 
0101   /**
0102    * @brief This member provides an optional measurement end time point.
0103    */
0104   T_ticks end;
0105 } RtemsEventValPerf_Context;
0106 
0107 static RtemsEventValPerf_Context
0108   RtemsEventValPerf_Instance;
0109 
0110 #define EVENT_END RTEMS_EVENT_0
0111 
0112 #define EVENT_OTHER RTEMS_EVENT_1
0113 
0114 typedef RtemsEventValPerf_Context Context;
0115 
0116 static void Send( const Context *ctx, rtems_event_set events )
0117 {
0118   SendEvents( ctx->worker_id, events );
0119 }
0120 
0121 static void Satisfy( void *arg )
0122 {
0123   Context *ctx;
0124 
0125   ctx = arg;
0126   ctx->begin = T_tick();
0127   ctx->status = rtems_event_send( ctx->worker_id, EVENT_END | EVENT_OTHER );
0128 }
0129 
0130 static void Worker( rtems_task_argument arg )
0131 {
0132   Context *ctx;
0133 
0134   ctx = (Context *) arg;
0135 
0136   while ( true ) {
0137     rtems_event_set   events;
0138     rtems_status_code sc;
0139     T_ticks           ticks;
0140 
0141     sc = rtems_event_receive(
0142       EVENT_END | EVENT_OTHER,
0143       RTEMS_EVENT_ALL | RTEMS_WAIT,
0144       RTEMS_NO_TIMEOUT,
0145       &events
0146     );
0147     ticks = T_tick();
0148     T_quiet_rsc_success( sc );
0149 
0150     if ( ( events & EVENT_END ) != 0 ) {
0151       ctx->end = ticks;
0152     }
0153   }
0154 }
0155 
0156 static void RtemsEventValPerf_Setup_Context( RtemsEventValPerf_Context *ctx )
0157 {
0158   T_measure_runtime_config config;
0159 
0160   memset( &config, 0, sizeof( config ) );
0161   config.sample_count = 100;
0162   ctx->request.arg = ctx;
0163   ctx->request.flags = T_MEASURE_RUNTIME_REPORT_SAMPLES;
0164   ctx->context = T_measure_runtime_create( &config );
0165   T_assert_not_null( ctx->context );
0166 }
0167 
0168 /**
0169  * @brief Create a mutex and a worker task.
0170  */
0171 static void RtemsEventValPerf_Setup( RtemsEventValPerf_Context *ctx )
0172 {
0173   SetSelfPriority( PRIO_NORMAL );
0174   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0175   StartTask( ctx->worker_id, Worker, ctx );
0176 }
0177 
0178 static void RtemsEventValPerf_Setup_Wrap( void *arg )
0179 {
0180   RtemsEventValPerf_Context *ctx;
0181 
0182   ctx = arg;
0183   RtemsEventValPerf_Setup_Context( ctx );
0184   RtemsEventValPerf_Setup( ctx );
0185 }
0186 
0187 /**
0188  * @brief Delete the worker task and the mutex.
0189  */
0190 static void RtemsEventValPerf_Teardown( RtemsEventValPerf_Context *ctx )
0191 {
0192   DeleteTask( ctx->worker_id );
0193   RestoreRunnerPriority();
0194 }
0195 
0196 static void RtemsEventValPerf_Teardown_Wrap( void *arg )
0197 {
0198   RtemsEventValPerf_Context *ctx;
0199 
0200   ctx = arg;
0201   RtemsEventValPerf_Teardown( ctx );
0202 }
0203 
0204 static T_fixture RtemsEventValPerf_Fixture = {
0205   .setup = RtemsEventValPerf_Setup_Wrap,
0206   .stop = NULL,
0207   .teardown = RtemsEventValPerf_Teardown_Wrap,
0208   .scope = NULL,
0209   .initial_context = &RtemsEventValPerf_Instance
0210 };
0211 
0212 /**
0213  * @defgroup RtemsEventReqPerfIsrPreempt spec:/rtems/event/req/perf-isr-preempt
0214  *
0215  * @{
0216  */
0217 
0218 /**
0219  * @brief Send two events from with interrupt context.  Satisfy the event
0220  *   condition.
0221  */
0222 static void RtemsEventReqPerfIsrPreempt_Body( RtemsEventValPerf_Context *ctx )
0223 {
0224   CallWithinISR( Satisfy, ctx );
0225 }
0226 
0227 static void RtemsEventReqPerfIsrPreempt_Body_Wrap( void *arg )
0228 {
0229   RtemsEventValPerf_Context *ctx;
0230 
0231   ctx = arg;
0232   RtemsEventReqPerfIsrPreempt_Body( ctx );
0233 }
0234 
0235 /**
0236  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0237  *   tick.
0238  */
0239 static bool RtemsEventReqPerfIsrPreempt_Teardown(
0240   RtemsEventValPerf_Context *ctx,
0241   T_ticks                   *delta,
0242   uint32_t                   tic,
0243   uint32_t                   toc,
0244   unsigned int               retry
0245 )
0246 {
0247   T_quiet_rsc_success( ctx->status );
0248 
0249   *delta = ctx->end - ctx->begin;
0250 
0251   return tic == toc;
0252 }
0253 
0254 static bool RtemsEventReqPerfIsrPreempt_Teardown_Wrap(
0255   void        *arg,
0256   T_ticks     *delta,
0257   uint32_t     tic,
0258   uint32_t     toc,
0259   unsigned int retry
0260 )
0261 {
0262   RtemsEventValPerf_Context *ctx;
0263 
0264   ctx = arg;
0265   return RtemsEventReqPerfIsrPreempt_Teardown( ctx, delta, tic, toc, retry );
0266 }
0267 
0268 /** @} */
0269 
0270 /**
0271  * @defgroup RtemsEventReqPerfOther spec:/rtems/event/req/perf-other
0272  *
0273  * @{
0274  */
0275 
0276 /**
0277  * @brief Lower the worker priority.
0278  */
0279 static void RtemsEventReqPerfOther_Setup( RtemsEventValPerf_Context *ctx )
0280 {
0281   SetPriority( ctx->worker_id, PRIO_LOW );
0282 }
0283 
0284 static void RtemsEventReqPerfOther_Setup_Wrap( void *arg )
0285 {
0286   RtemsEventValPerf_Context *ctx;
0287 
0288   ctx = arg;
0289   RtemsEventReqPerfOther_Setup( ctx );
0290 }
0291 
0292 /**
0293  * @brief Send two events.  Satisfy the event condition.
0294  */
0295 static void RtemsEventReqPerfOther_Body( RtemsEventValPerf_Context *ctx )
0296 {
0297   ctx->status = rtems_event_send( ctx->worker_id, EVENT_END | EVENT_OTHER );
0298 }
0299 
0300 static void RtemsEventReqPerfOther_Body_Wrap( void *arg )
0301 {
0302   RtemsEventValPerf_Context *ctx;
0303 
0304   ctx = arg;
0305   RtemsEventReqPerfOther_Body( ctx );
0306 }
0307 
0308 /**
0309  * @brief Restore the worker priority.  Discard samples interrupted by a clock
0310  *   tick.
0311  */
0312 static bool RtemsEventReqPerfOther_Teardown(
0313   RtemsEventValPerf_Context *ctx,
0314   T_ticks                   *delta,
0315   uint32_t                   tic,
0316   uint32_t                   toc,
0317   unsigned int               retry
0318 )
0319 {
0320   T_quiet_rsc_success( ctx->status );
0321 
0322   SetPriority( ctx->worker_id, PRIO_HIGH );
0323 
0324   return tic == toc;
0325 }
0326 
0327 static bool RtemsEventReqPerfOther_Teardown_Wrap(
0328   void        *arg,
0329   T_ticks     *delta,
0330   uint32_t     tic,
0331   uint32_t     toc,
0332   unsigned int retry
0333 )
0334 {
0335   RtemsEventValPerf_Context *ctx;
0336 
0337   ctx = arg;
0338   return RtemsEventReqPerfOther_Teardown( ctx, delta, tic, toc, retry );
0339 }
0340 
0341 /** @} */
0342 
0343 #if defined(RTEMS_SMP)
0344 /**
0345  * @defgroup RtemsEventReqPerfOtherCpu spec:/rtems/event/req/perf-other-cpu
0346  *
0347  * @{
0348  */
0349 
0350 /**
0351  * @brief Move worker to scheduler B.
0352  */
0353 static void RtemsEventReqPerfOtherCpu_Prepare( RtemsEventValPerf_Context *ctx )
0354 {
0355   SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0356 }
0357 
0358 /**
0359  * @brief Send two events.  Satisfy the event condition.
0360  */
0361 static void RtemsEventReqPerfOtherCpu_Body( RtemsEventValPerf_Context *ctx )
0362 {
0363   ctx->begin = T_tick();
0364   ctx->status = rtems_event_send( ctx->worker_id, EVENT_END | EVENT_OTHER );
0365 }
0366 
0367 static void RtemsEventReqPerfOtherCpu_Body_Wrap( void *arg )
0368 {
0369   RtemsEventValPerf_Context *ctx;
0370 
0371   ctx = arg;
0372   RtemsEventReqPerfOtherCpu_Body( ctx );
0373 }
0374 
0375 /**
0376  * @brief Make sure the worker waits for the next event.  Set the measured
0377  *   runtime. Discard samples interrupted by a clock tick.
0378  */
0379 static bool RtemsEventReqPerfOtherCpu_Teardown(
0380   RtemsEventValPerf_Context *ctx,
0381   T_ticks                   *delta,
0382   uint32_t                   tic,
0383   uint32_t                   toc,
0384   unsigned int               retry
0385 )
0386 {
0387   T_quiet_rsc_success( ctx->status );
0388 
0389   WaitForNextTask( 1, ctx->worker_id );
0390   *delta = ctx->end - ctx->begin;
0391 
0392   return tic == toc;
0393 }
0394 
0395 static bool RtemsEventReqPerfOtherCpu_Teardown_Wrap(
0396   void        *arg,
0397   T_ticks     *delta,
0398   uint32_t     tic,
0399   uint32_t     toc,
0400   unsigned int retry
0401 )
0402 {
0403   RtemsEventValPerf_Context *ctx;
0404 
0405   ctx = arg;
0406   return RtemsEventReqPerfOtherCpu_Teardown( ctx, delta, tic, toc, retry );
0407 }
0408 
0409 /**
0410  * @brief Move worker to scheduler A.
0411  */
0412 static void RtemsEventReqPerfOtherCpu_Cleanup( RtemsEventValPerf_Context *ctx )
0413 {
0414   SetScheduler( ctx->worker_id, SCHEDULER_A_ID, PRIO_HIGH );
0415 }
0416 
0417 /** @} */
0418 #endif
0419 
0420 /**
0421  * @defgroup RtemsEventReqPerfOtherNotSatisfied \
0422  *   spec:/rtems/event/req/perf-other-not-satisfied
0423  *
0424  * @{
0425  */
0426 
0427 /**
0428  * @brief Send an event.  Do not satisfy the event condition.
0429  */
0430 static void RtemsEventReqPerfOtherNotSatisfied_Body(
0431   RtemsEventValPerf_Context *ctx
0432 )
0433 {
0434   ctx->status = rtems_event_send( ctx->worker_id, EVENT_OTHER );
0435 }
0436 
0437 static void RtemsEventReqPerfOtherNotSatisfied_Body_Wrap( void *arg )
0438 {
0439   RtemsEventValPerf_Context *ctx;
0440 
0441   ctx = arg;
0442   RtemsEventReqPerfOtherNotSatisfied_Body( ctx );
0443 }
0444 
0445 /**
0446  * @brief Let the worker wait for the next set of events.  Discard samples
0447  *   interrupted by a clock tick.
0448  */
0449 static bool RtemsEventReqPerfOtherNotSatisfied_Teardown(
0450   RtemsEventValPerf_Context *ctx,
0451   T_ticks                   *delta,
0452   uint32_t                   tic,
0453   uint32_t                   toc,
0454   unsigned int               retry
0455 )
0456 {
0457   T_quiet_rsc_success( ctx->status );
0458 
0459   Send( ctx, EVENT_END );
0460 
0461   return tic == toc;
0462 }
0463 
0464 static bool RtemsEventReqPerfOtherNotSatisfied_Teardown_Wrap(
0465   void        *arg,
0466   T_ticks     *delta,
0467   uint32_t     tic,
0468   uint32_t     toc,
0469   unsigned int retry
0470 )
0471 {
0472   RtemsEventValPerf_Context *ctx;
0473 
0474   ctx = arg;
0475   return RtemsEventReqPerfOtherNotSatisfied_Teardown(
0476     ctx,
0477     delta,
0478     tic,
0479     toc,
0480     retry
0481   );
0482 }
0483 
0484 /** @} */
0485 
0486 /**
0487  * @defgroup RtemsEventReqPerfOtherPreempt \
0488  *   spec:/rtems/event/req/perf-other-preempt
0489  *
0490  * @{
0491  */
0492 
0493 /**
0494  * @brief Send two events.  Satisfy the event condition.
0495  */
0496 static void RtemsEventReqPerfOtherPreempt_Body(
0497   RtemsEventValPerf_Context *ctx
0498 )
0499 {
0500   ctx->begin = T_tick();
0501   ctx->status = rtems_event_send( ctx->worker_id, EVENT_END | EVENT_OTHER );
0502 }
0503 
0504 static void RtemsEventReqPerfOtherPreempt_Body_Wrap( void *arg )
0505 {
0506   RtemsEventValPerf_Context *ctx;
0507 
0508   ctx = arg;
0509   RtemsEventReqPerfOtherPreempt_Body( ctx );
0510 }
0511 
0512 /**
0513  * @brief Set the measured runtime.  Discard samples interrupted by a clock
0514  *   tick.
0515  */
0516 static bool RtemsEventReqPerfOtherPreempt_Teardown(
0517   RtemsEventValPerf_Context *ctx,
0518   T_ticks                   *delta,
0519   uint32_t                   tic,
0520   uint32_t                   toc,
0521   unsigned int               retry
0522 )
0523 {
0524   T_quiet_rsc_success( ctx->status );
0525 
0526   *delta = ctx->end - ctx->begin;
0527 
0528   return tic == toc;
0529 }
0530 
0531 static bool RtemsEventReqPerfOtherPreempt_Teardown_Wrap(
0532   void        *arg,
0533   T_ticks     *delta,
0534   uint32_t     tic,
0535   uint32_t     toc,
0536   unsigned int retry
0537 )
0538 {
0539   RtemsEventValPerf_Context *ctx;
0540 
0541   ctx = arg;
0542   return RtemsEventReqPerfOtherPreempt_Teardown( ctx, delta, tic, toc, retry );
0543 }
0544 
0545 /** @} */
0546 
0547 /**
0548  * @fn void T_case_body_RtemsEventValPerf( void )
0549  */
0550 T_TEST_CASE_FIXTURE( RtemsEventValPerf, &RtemsEventValPerf_Fixture )
0551 {
0552   RtemsEventValPerf_Context *ctx;
0553 
0554   ctx = T_fixture_context();
0555 
0556   ctx->request.name = "RtemsEventReqPerfIsrPreempt";
0557   ctx->request.setup = NULL;
0558   ctx->request.body = RtemsEventReqPerfIsrPreempt_Body_Wrap;
0559   ctx->request.teardown = RtemsEventReqPerfIsrPreempt_Teardown_Wrap;
0560   T_measure_runtime( ctx->context, &ctx->request );
0561 
0562   ctx->request.name = "RtemsEventReqPerfOther";
0563   ctx->request.setup = RtemsEventReqPerfOther_Setup_Wrap;
0564   ctx->request.body = RtemsEventReqPerfOther_Body_Wrap;
0565   ctx->request.teardown = RtemsEventReqPerfOther_Teardown_Wrap;
0566   T_measure_runtime( ctx->context, &ctx->request );
0567 
0568   #if defined(RTEMS_SMP)
0569   RtemsEventReqPerfOtherCpu_Prepare( ctx );
0570   ctx->request.name = "RtemsEventReqPerfOtherCpu";
0571   ctx->request.setup = NULL;
0572   ctx->request.body = RtemsEventReqPerfOtherCpu_Body_Wrap;
0573   ctx->request.teardown = RtemsEventReqPerfOtherCpu_Teardown_Wrap;
0574   T_measure_runtime( ctx->context, &ctx->request );
0575   RtemsEventReqPerfOtherCpu_Cleanup( ctx );
0576   #endif
0577 
0578   ctx->request.name = "RtemsEventReqPerfOtherNotSatisfied";
0579   ctx->request.setup = NULL;
0580   ctx->request.body = RtemsEventReqPerfOtherNotSatisfied_Body_Wrap;
0581   ctx->request.teardown = RtemsEventReqPerfOtherNotSatisfied_Teardown_Wrap;
0582   T_measure_runtime( ctx->context, &ctx->request );
0583 
0584   ctx->request.name = "RtemsEventReqPerfOtherPreempt";
0585   ctx->request.setup = NULL;
0586   ctx->request.body = RtemsEventReqPerfOtherPreempt_Body_Wrap;
0587   ctx->request.teardown = RtemsEventReqPerfOtherPreempt_Teardown_Wrap;
0588   T_measure_runtime( ctx->context, &ctx->request );
0589 }
0590 
0591 /** @} */