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 CReqClockNanosleep
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 <errno.h>
0056 #include <limits.h>
0057 #include <rtems.h>
0058 #include <time.h>
0059 #include <rtems/test-scheduler.h>
0060 #include <rtems/score/timecounter.h>
0061 
0062 #include "tx-support.h"
0063 
0064 #include <rtems/test.h>
0065 
0066 /**
0067  * @defgroup CReqClockNanosleep spec:/c/req/clock-nanosleep
0068  *
0069  * @ingroup TestsuitesValidationNoClock0
0070  *
0071  * @{
0072  */
0073 
0074 typedef enum {
0075   CReqClockNanosleep_Pre_ClockId_Monotonic,
0076   CReqClockNanosleep_Pre_ClockId_Realtime,
0077   CReqClockNanosleep_Pre_ClockId_Invalid,
0078   CReqClockNanosleep_Pre_ClockId_NA
0079 } CReqClockNanosleep_Pre_ClockId;
0080 
0081 typedef enum {
0082   CReqClockNanosleep_Pre_Abstime_Yes,
0083   CReqClockNanosleep_Pre_Abstime_No,
0084   CReqClockNanosleep_Pre_Abstime_NA
0085 } CReqClockNanosleep_Pre_Abstime;
0086 
0087 typedef enum {
0088   CReqClockNanosleep_Pre_RQTp_Valid,
0089   CReqClockNanosleep_Pre_RQTp_Null,
0090   CReqClockNanosleep_Pre_RQTp_NA
0091 } CReqClockNanosleep_Pre_RQTp;
0092 
0093 typedef enum {
0094   CReqClockNanosleep_Pre_RQTpNSec_Valid,
0095   CReqClockNanosleep_Pre_RQTpNSec_Invalid,
0096   CReqClockNanosleep_Pre_RQTpNSec_NA
0097 } CReqClockNanosleep_Pre_RQTpNSec;
0098 
0099 typedef enum {
0100   CReqClockNanosleep_Pre_RQTpSec_Negative,
0101   CReqClockNanosleep_Pre_RQTpSec_FarFuture,
0102   CReqClockNanosleep_Pre_RQTpSec_Future,
0103   CReqClockNanosleep_Pre_RQTpSec_PastOrNow,
0104   CReqClockNanosleep_Pre_RQTpSec_NA
0105 } CReqClockNanosleep_Pre_RQTpSec;
0106 
0107 typedef enum {
0108   CReqClockNanosleep_Pre_RMTp_Valid,
0109   CReqClockNanosleep_Pre_RMTp_Null,
0110   CReqClockNanosleep_Pre_RMTp_NA
0111 } CReqClockNanosleep_Pre_RMTp;
0112 
0113 typedef enum {
0114   CReqClockNanosleep_Post_Status_Zero,
0115   CReqClockNanosleep_Post_Status_ENOTSUP,
0116   CReqClockNanosleep_Post_Status_EINVAL,
0117   CReqClockNanosleep_Post_Status_NA
0118 } CReqClockNanosleep_Post_Status;
0119 
0120 typedef enum {
0121   CReqClockNanosleep_Post_Timer_Inactive,
0122   CReqClockNanosleep_Post_Timer_Monotonic,
0123   CReqClockNanosleep_Post_Timer_Realtime,
0124   CReqClockNanosleep_Post_Timer_NA
0125 } CReqClockNanosleep_Post_Timer;
0126 
0127 typedef enum {
0128   CReqClockNanosleep_Post_Expire_Last,
0129   CReqClockNanosleep_Post_Expire_Absolute,
0130   CReqClockNanosleep_Post_Expire_Relative,
0131   CReqClockNanosleep_Post_Expire_NA
0132 } CReqClockNanosleep_Post_Expire;
0133 
0134 typedef enum {
0135   CReqClockNanosleep_Post_Scheduler_Block,
0136   CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0137   CReqClockNanosleep_Post_Scheduler_Nop,
0138   CReqClockNanosleep_Post_Scheduler_NA
0139 } CReqClockNanosleep_Post_Scheduler;
0140 
0141 typedef enum {
0142   CReqClockNanosleep_Post_RMTp_Zero,
0143   CReqClockNanosleep_Post_RMTp_Nop,
0144   CReqClockNanosleep_Post_RMTp_NA
0145 } CReqClockNanosleep_Post_RMTp;
0146 
0147 typedef struct {
0148   uint32_t Skip : 1;
0149   uint32_t Pre_ClockId_NA : 1;
0150   uint32_t Pre_Abstime_NA : 1;
0151   uint32_t Pre_RQTp_NA : 1;
0152   uint32_t Pre_RQTpNSec_NA : 1;
0153   uint32_t Pre_RQTpSec_NA : 1;
0154   uint32_t Pre_RMTp_NA : 1;
0155   uint32_t Post_Status : 2;
0156   uint32_t Post_Timer : 2;
0157   uint32_t Post_Expire : 2;
0158   uint32_t Post_Scheduler : 2;
0159   uint32_t Post_RMTp : 2;
0160 } CReqClockNanosleep_Entry;
0161 
0162 /**
0163  * @brief Test context for spec:/c/req/clock-nanosleep test case.
0164  */
0165 typedef struct {
0166   /**
0167    * @brief This member provides the scheduler operation records.
0168    */
0169   T_scheduler_log_4 scheduler_log;
0170 
0171   /**
0172    * @brief This member contains the CLOCK_REALTIME value before the
0173    *   clock_nanosleep() call.
0174    */
0175   struct timespec now_realtime;
0176 
0177   /**
0178    * @brief This member contains the CLOCK_MONOTONIC value before the
0179    *   clock_nanosleep() call.
0180    */
0181   struct timespec now_monotonic;
0182 
0183   /**
0184    * @brief This member contains the worker task identifier.
0185    */
0186   rtems_id worker_id;
0187 
0188   /**
0189    * @brief This member contains the timer information of the worker task.
0190    */
0191   TaskTimerInfo timer_info;
0192 
0193   /**
0194    * @brief This member provides the object referenced by the ``rqtp``
0195    *   parameter.
0196    */
0197   struct timespec rqtp_obj;
0198 
0199   /**
0200    * @brief This member provides the object referenced by the ``rmtp``
0201    *   parameter.
0202    */
0203   struct timespec rmtp_obj;
0204 
0205   /**
0206    * @brief This member contains the return value of the clock_nanosleep()
0207    *   call.
0208    */
0209   int status;
0210 
0211   /**
0212    * @brief This member specifies the ``clock_id`` parameter value.
0213    */
0214   clockid_t clock_id;
0215 
0216   /**
0217    * @brief This member specifies the ``flags`` parameter value.
0218    */
0219   int flags;
0220 
0221   /**
0222    * @brief This member specifies the ``rqtp`` parameter value.
0223    */
0224   const struct timespec *rqtp;
0225 
0226   /**
0227    * @brief This member specifies the ``rmtp`` parameter value.
0228    */
0229   struct timespec *rmtp;
0230 
0231   struct {
0232     /**
0233      * @brief This member defines the pre-condition indices for the next
0234      *   action.
0235      */
0236     size_t pci[ 6 ];
0237 
0238     /**
0239      * @brief This member defines the pre-condition states for the next action.
0240      */
0241     size_t pcs[ 6 ];
0242 
0243     /**
0244      * @brief If this member is true, then the test action loop is executed.
0245      */
0246     bool in_action_loop;
0247 
0248     /**
0249      * @brief This member contains the next transition map index.
0250      */
0251     size_t index;
0252 
0253     /**
0254      * @brief This member contains the current transition map entry.
0255      */
0256     CReqClockNanosleep_Entry entry;
0257 
0258     /**
0259      * @brief If this member is true, then the current transition variant
0260      *   should be skipped.
0261      */
0262     bool skip;
0263   } Map;
0264 } CReqClockNanosleep_Context;
0265 
0266 static CReqClockNanosleep_Context
0267   CReqClockNanosleep_Instance;
0268 
0269 static const char * const CReqClockNanosleep_PreDesc_ClockId[] = {
0270   "Monotonic",
0271   "Realtime",
0272   "Invalid",
0273   "NA"
0274 };
0275 
0276 static const char * const CReqClockNanosleep_PreDesc_Abstime[] = {
0277   "Yes",
0278   "No",
0279   "NA"
0280 };
0281 
0282 static const char * const CReqClockNanosleep_PreDesc_RQTp[] = {
0283   "Valid",
0284   "Null",
0285   "NA"
0286 };
0287 
0288 static const char * const CReqClockNanosleep_PreDesc_RQTpNSec[] = {
0289   "Valid",
0290   "Invalid",
0291   "NA"
0292 };
0293 
0294 static const char * const CReqClockNanosleep_PreDesc_RQTpSec[] = {
0295   "Negative",
0296   "FarFuture",
0297   "Future",
0298   "PastOrNow",
0299   "NA"
0300 };
0301 
0302 static const char * const CReqClockNanosleep_PreDesc_RMTp[] = {
0303   "Valid",
0304   "Null",
0305   "NA"
0306 };
0307 
0308 static const char * const * const CReqClockNanosleep_PreDesc[] = {
0309   CReqClockNanosleep_PreDesc_ClockId,
0310   CReqClockNanosleep_PreDesc_Abstime,
0311   CReqClockNanosleep_PreDesc_RQTp,
0312   CReqClockNanosleep_PreDesc_RQTpNSec,
0313   CReqClockNanosleep_PreDesc_RQTpSec,
0314   CReqClockNanosleep_PreDesc_RMTp,
0315   NULL
0316 };
0317 
0318 typedef CReqClockNanosleep_Context Context;
0319 
0320 static void Worker( rtems_task_argument arg )
0321 {
0322   Context *ctx;
0323 
0324   ctx = (Context *) arg;
0325 
0326   while ( true ) {
0327     T_scheduler_log *log;
0328     uint32_t         counter;
0329 
0330     SuspendSelf();
0331 
0332     log = T_scheduler_record_4( &ctx->scheduler_log );
0333     T_null( log );
0334 
0335     counter = GetTimecountCounter();
0336     _Timecounter_Nanotime( &ctx->now_realtime );
0337     SetTimecountCounter( counter );
0338 
0339     counter = GetTimecountCounter();
0340     _Timecounter_Nanouptime( &ctx->now_monotonic );
0341     SetTimecountCounter( counter );
0342 
0343     ctx->status = clock_nanosleep(
0344       ctx->clock_id,
0345       ctx->flags,
0346       ctx->rqtp,
0347       ctx->rmtp
0348     );
0349 
0350     (void) T_scheduler_record( NULL );
0351   }
0352 }
0353 
0354 static void CReqClockNanosleep_Pre_ClockId_Prepare(
0355   CReqClockNanosleep_Context    *ctx,
0356   CReqClockNanosleep_Pre_ClockId state
0357 )
0358 {
0359   switch ( state ) {
0360     case CReqClockNanosleep_Pre_ClockId_Monotonic: {
0361       /*
0362        * While the ``clock_id`` parameter is equal to CLOCK_MONOTONIC.
0363        */
0364       ctx->clock_id = CLOCK_MONOTONIC;
0365       break;
0366     }
0367 
0368     case CReqClockNanosleep_Pre_ClockId_Realtime: {
0369       /*
0370        * While the ``clock_id`` parameter is equal to CLOCK_REALTIME.
0371        */
0372       ctx->clock_id = CLOCK_REALTIME;
0373       break;
0374     }
0375 
0376     case CReqClockNanosleep_Pre_ClockId_Invalid: {
0377       /*
0378        * While the ``clock_id`` parameter is an invalid clock identifier.
0379        */
0380       ctx->clock_id = INT_MAX;
0381       break;
0382     }
0383 
0384     case CReqClockNanosleep_Pre_ClockId_NA:
0385       break;
0386   }
0387 }
0388 
0389 static void CReqClockNanosleep_Pre_Abstime_Prepare(
0390   CReqClockNanosleep_Context    *ctx,
0391   CReqClockNanosleep_Pre_Abstime state
0392 )
0393 {
0394   switch ( state ) {
0395     case CReqClockNanosleep_Pre_Abstime_Yes: {
0396       /*
0397        * While the ``flags`` parameter indicates an absolute time.
0398        */
0399       ctx->flags |= TIMER_ABSTIME;
0400       break;
0401     }
0402 
0403     case CReqClockNanosleep_Pre_Abstime_No: {
0404       /*
0405        * While the ``flags`` parameter does not indicate an absolute time.
0406        */
0407       /* This is the default */
0408       break;
0409     }
0410 
0411     case CReqClockNanosleep_Pre_Abstime_NA:
0412       break;
0413   }
0414 }
0415 
0416 static void CReqClockNanosleep_Pre_RQTp_Prepare(
0417   CReqClockNanosleep_Context *ctx,
0418   CReqClockNanosleep_Pre_RQTp state
0419 )
0420 {
0421   switch ( state ) {
0422     case CReqClockNanosleep_Pre_RQTp_Valid: {
0423       /*
0424        * While the ``rqtp`` parameter references an object of type struct
0425        * timespec.
0426        */
0427       ctx->rqtp = &ctx->rqtp_obj;
0428       break;
0429     }
0430 
0431     case CReqClockNanosleep_Pre_RQTp_Null: {
0432       /*
0433        * While the ``rqtp`` parameter is equal to NULL.
0434        */
0435       ctx->rqtp = NULL;
0436       break;
0437     }
0438 
0439     case CReqClockNanosleep_Pre_RQTp_NA:
0440       break;
0441   }
0442 }
0443 
0444 static void CReqClockNanosleep_Pre_RQTpNSec_Prepare(
0445   CReqClockNanosleep_Context     *ctx,
0446   CReqClockNanosleep_Pre_RQTpNSec state
0447 )
0448 {
0449   switch ( state ) {
0450     case CReqClockNanosleep_Pre_RQTpNSec_Valid: {
0451       /*
0452        * While the ``tv_nsec`` member of the object referenced by the ``rqtp``
0453        * parameter is a valid nanoseconds value.
0454        */
0455       ctx->rqtp_obj.tv_nsec = 999999999;
0456       break;
0457     }
0458 
0459     case CReqClockNanosleep_Pre_RQTpNSec_Invalid: {
0460       /*
0461        * While the ``tv_nsec`` member of the object referenced by the ``rqtp``
0462        * parameter is an invalid nanoseconds value.
0463        */
0464       ctx->rqtp_obj.tv_nsec = -1;
0465       break;
0466     }
0467 
0468     case CReqClockNanosleep_Pre_RQTpNSec_NA:
0469       break;
0470   }
0471 }
0472 
0473 static void CReqClockNanosleep_Pre_RQTpSec_Prepare(
0474   CReqClockNanosleep_Context    *ctx,
0475   CReqClockNanosleep_Pre_RQTpSec state
0476 )
0477 {
0478   switch ( state ) {
0479     case CReqClockNanosleep_Pre_RQTpSec_Negative: {
0480       /*
0481        * While the ``tv_sec`` member of the object referenced by the ``rqtp``
0482        * parameter is negative.
0483        */
0484       ctx->rqtp_obj.tv_sec = -238479;
0485       break;
0486     }
0487 
0488     case CReqClockNanosleep_Pre_RQTpSec_FarFuture: {
0489       /*
0490        * While the ``tv_sec`` member of the object referenced by the ``rqtp``
0491        * parameter specifies a time point which is past the implementation
0492        * limit.
0493        */
0494       ctx->rqtp_obj.tv_sec = INT64_MAX;
0495       break;
0496     }
0497 
0498     case CReqClockNanosleep_Pre_RQTpSec_Future: {
0499       /*
0500        * While the ``tv_sec`` member of the object referenced by the ``rqtp``
0501        * parameter specifies a time point which is after the current time of
0502        * the clock specified by the ``clock_id`` parameter and is within the
0503        * implementation limits.
0504        */
0505       ctx->rqtp_obj.tv_sec = 1621322302;
0506       break;
0507     }
0508 
0509     case CReqClockNanosleep_Pre_RQTpSec_PastOrNow: {
0510       /*
0511        * While the ``tv_sec`` member of the object referenced by the ``rqtp``
0512        * parameter is non-negative and specifies a time point which is before
0513        * or at the current time of the clock specified by the ``clock_id``
0514        * parameter.
0515        */
0516       ctx->rqtp_obj.tv_sec = 0;
0517 
0518       if ( ctx->rqtp_obj.tv_nsec == 999999999 ) {
0519         ctx->rqtp_obj.tv_nsec = 0;
0520       }
0521       break;
0522     }
0523 
0524     case CReqClockNanosleep_Pre_RQTpSec_NA:
0525       break;
0526   }
0527 }
0528 
0529 static void CReqClockNanosleep_Pre_RMTp_Prepare(
0530   CReqClockNanosleep_Context *ctx,
0531   CReqClockNanosleep_Pre_RMTp state
0532 )
0533 {
0534   switch ( state ) {
0535     case CReqClockNanosleep_Pre_RMTp_Valid: {
0536       /*
0537        * While the ``rmtp`` parameter references an object of type struct
0538        * timespec.
0539        */
0540       ctx->rmtp = &ctx->rmtp_obj;
0541       break;
0542     }
0543 
0544     case CReqClockNanosleep_Pre_RMTp_Null: {
0545       /*
0546        * While the ``rmtp`` parameter is equal to NULL.
0547        */
0548       ctx->rmtp = NULL;
0549       break;
0550     }
0551 
0552     case CReqClockNanosleep_Pre_RMTp_NA:
0553       break;
0554   }
0555 }
0556 
0557 static void CReqClockNanosleep_Post_Status_Check(
0558   CReqClockNanosleep_Context    *ctx,
0559   CReqClockNanosleep_Post_Status state
0560 )
0561 {
0562   switch ( state ) {
0563     case CReqClockNanosleep_Post_Status_Zero: {
0564       /*
0565        * The return value of clock_nanosleep() shall be equal to zero.
0566        */
0567       T_eq_int( ctx->status, 0 );
0568       break;
0569     }
0570 
0571     case CReqClockNanosleep_Post_Status_ENOTSUP: {
0572       /*
0573        * The return value of clock_nanosleep() shall be equal to ENOTSUP.
0574        */
0575       T_eq_int( ctx->status, ENOTSUP );
0576       break;
0577     }
0578 
0579     case CReqClockNanosleep_Post_Status_EINVAL: {
0580       /*
0581        * The return value of clock_nanosleep() shall be equal to EINVAL.
0582        */
0583       T_eq_int( ctx->status, EINVAL );
0584       break;
0585     }
0586 
0587     case CReqClockNanosleep_Post_Status_NA:
0588       break;
0589   }
0590 }
0591 
0592 static void CReqClockNanosleep_Post_Timer_Check(
0593   CReqClockNanosleep_Context   *ctx,
0594   CReqClockNanosleep_Post_Timer state
0595 )
0596 {
0597   switch ( state ) {
0598     case CReqClockNanosleep_Post_Timer_Inactive: {
0599       /*
0600        * The timer of the calling task shall be inactive.
0601        */
0602       T_eq_int( ctx->timer_info.state, TASK_TIMER_INACTIVE );
0603       break;
0604     }
0605 
0606     case CReqClockNanosleep_Post_Timer_Monotonic: {
0607       /*
0608        * The timer of the calling task shall be active using the
0609        * CLOCK_MONOTONIC.
0610        */
0611       T_eq_int( ctx->timer_info.state, TASK_TIMER_MONOTONIC );
0612       break;
0613     }
0614 
0615     case CReqClockNanosleep_Post_Timer_Realtime: {
0616       /*
0617        * The timer of the calling task shall be active using the
0618        * CLOCK_REALTIME.
0619        */
0620       T_eq_int( ctx->timer_info.state, TASK_TIMER_REALTIME );
0621       break;
0622     }
0623 
0624     case CReqClockNanosleep_Post_Timer_NA:
0625       break;
0626   }
0627 }
0628 
0629 static void CReqClockNanosleep_Post_Expire_Check(
0630   CReqClockNanosleep_Context    *ctx,
0631   CReqClockNanosleep_Post_Expire state
0632 )
0633 {
0634   struct timespec expire;
0635 
0636   switch ( state ) {
0637     case CReqClockNanosleep_Post_Expire_Last: {
0638       /*
0639        * The timer of the calling task shall expire at the last valid time
0640        * point of the clock specified by the ``clock_id`` parameter.
0641        */
0642       T_eq_u64( ctx->timer_info.expire_ticks, 0xffffffffffffffff );
0643       break;
0644     }
0645 
0646     case CReqClockNanosleep_Post_Expire_Absolute: {
0647       /*
0648        * The timer of the calling task shall expire at the time point specified
0649        * by the ``rqtp`` parameter.
0650        */
0651       T_eq_i64( ctx->timer_info.expire_timespec.tv_sec, ctx->rqtp_obj.tv_sec );
0652       T_eq_long(
0653         ctx->timer_info.expire_timespec.tv_nsec,
0654         ctx->rqtp_obj.tv_nsec
0655       );
0656       break;
0657     }
0658 
0659     case CReqClockNanosleep_Post_Expire_Relative: {
0660       /*
0661        * The timer of the calling task shall expire at the time point specified
0662        * by the sum of the current time of the clock specified by
0663        * CLOCK_MONOTONIC and the interval specified by the ``rqtp`` parameter.
0664        */
0665       expire = ctx->now_monotonic;
0666       expire.tv_sec += ctx->rqtp_obj.tv_sec;
0667       expire.tv_nsec += ctx->rqtp_obj.tv_nsec;
0668 
0669       if ( expire.tv_nsec >= 1000000000 ) {
0670         ++expire.tv_sec;
0671         expire.tv_nsec -= 1000000000;
0672       }
0673 
0674       T_eq_i64( ctx->timer_info.expire_timespec.tv_sec, expire.tv_sec );
0675       T_eq_long( ctx->timer_info.expire_timespec.tv_nsec, expire.tv_nsec );
0676       break;
0677     }
0678 
0679     case CReqClockNanosleep_Post_Expire_NA:
0680       break;
0681   }
0682 }
0683 
0684 static void CReqClockNanosleep_Post_Scheduler_Check(
0685   CReqClockNanosleep_Context       *ctx,
0686   CReqClockNanosleep_Post_Scheduler state
0687 )
0688 {
0689   switch ( state ) {
0690     case CReqClockNanosleep_Post_Scheduler_Block: {
0691       /*
0692        * The calling task shall be blocked by the scheduler exactly once by the
0693        * clock_nanosleep() call.
0694        */
0695       T_eq_sz( ctx->scheduler_log.header.recorded, 1 );
0696       T_eq_int(
0697         ctx->scheduler_log.events[ 0 ].operation,
0698         T_SCHEDULER_BLOCK
0699       );
0700       break;
0701     }
0702 
0703     case CReqClockNanosleep_Post_Scheduler_BlockUnblock: {
0704       /*
0705        * The calling task shall be blocked exactly once by the scheduler and
0706        * then unblocked in the same thread dispatch critical section by the
0707        * clock_nanosleep() call.
0708        */
0709       T_eq_sz( ctx->scheduler_log.header.recorded, 2 );
0710       T_eq_int(
0711         ctx->scheduler_log.events[ 0 ].operation,
0712         T_SCHEDULER_BLOCK
0713       );
0714       T_eq_int(
0715         ctx->scheduler_log.events[ 1 ].operation,
0716         T_SCHEDULER_UNBLOCK
0717       );
0718       break;
0719     }
0720 
0721     case CReqClockNanosleep_Post_Scheduler_Nop: {
0722       /*
0723        * The calling task shall not be altered by the scheduler by the
0724        * clock_nanosleep() call.
0725        */
0726       T_eq_sz( ctx->scheduler_log.header.recorded, 0 );
0727       break;
0728     }
0729 
0730     case CReqClockNanosleep_Post_Scheduler_NA:
0731       break;
0732   }
0733 }
0734 
0735 static void CReqClockNanosleep_Post_RMTp_Check(
0736   CReqClockNanosleep_Context  *ctx,
0737   CReqClockNanosleep_Post_RMTp state
0738 )
0739 {
0740   switch ( state ) {
0741     case CReqClockNanosleep_Post_RMTp_Zero: {
0742       /*
0743        * The object referenced by the ``rmtp`` parameter shall be cleared to
0744        * zero after the return of the clock_nanosleep() call.
0745        */
0746       T_eq_i64( ctx->rmtp_obj.tv_sec, 0 );
0747       T_eq_long( ctx->rmtp_obj.tv_nsec, 0 );
0748       break;
0749     }
0750 
0751     case CReqClockNanosleep_Post_RMTp_Nop: {
0752       /*
0753        * Objects referenced by the ``rmtp`` parameter in past calls to
0754        * clock_nanosleep() shall not be accessed by the clock_nanosleep() call.
0755        */
0756       T_eq_i64( ctx->rmtp_obj.tv_sec, -1 );
0757       T_eq_long( ctx->rmtp_obj.tv_nsec, -1 );
0758       break;
0759     }
0760 
0761     case CReqClockNanosleep_Post_RMTp_NA:
0762       break;
0763   }
0764 }
0765 
0766 static void CReqClockNanosleep_Setup( CReqClockNanosleep_Context *ctx )
0767 {
0768   rtems_time_of_day now = { 1988, 1, 1, 0, 0, 0, 0 };
0769   T_rsc_success( rtems_clock_set( &now ) );
0770   SetSelfPriority( PRIO_NORMAL );
0771   ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0772   StartTask( ctx->worker_id, Worker, ctx );
0773 }
0774 
0775 static void CReqClockNanosleep_Setup_Wrap( void *arg )
0776 {
0777   CReqClockNanosleep_Context *ctx;
0778 
0779   ctx = arg;
0780   ctx->Map.in_action_loop = false;
0781   CReqClockNanosleep_Setup( ctx );
0782 }
0783 
0784 static void CReqClockNanosleep_Teardown( CReqClockNanosleep_Context *ctx )
0785 {
0786   DeleteTask( ctx->worker_id );
0787   RestoreRunnerPriority();
0788 }
0789 
0790 static void CReqClockNanosleep_Teardown_Wrap( void *arg )
0791 {
0792   CReqClockNanosleep_Context *ctx;
0793 
0794   ctx = arg;
0795   ctx->Map.in_action_loop = false;
0796   CReqClockNanosleep_Teardown( ctx );
0797 }
0798 
0799 static void CReqClockNanosleep_Prepare( CReqClockNanosleep_Context *ctx )
0800 {
0801   ctx->status = -1;
0802   ctx->flags = 0;
0803   ctx->rmtp_obj.tv_sec = -1;
0804   ctx->rmtp_obj.tv_nsec = -1;
0805 }
0806 
0807 static void CReqClockNanosleep_Action( CReqClockNanosleep_Context *ctx )
0808 {
0809   ResumeTask( ctx->worker_id );
0810   (void) T_scheduler_record( NULL );
0811   GetTaskTimerInfo( ctx->worker_id, &ctx->timer_info );
0812   ClockTick();
0813   FinalClockTick();
0814 }
0815 
0816 static const CReqClockNanosleep_Entry
0817 CReqClockNanosleep_Entries[] = {
0818   { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_EINVAL,
0819     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0820     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0821     CReqClockNanosleep_Post_RMTp_Nop },
0822   { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_ENOTSUP,
0823     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0824     CReqClockNanosleep_Post_Scheduler_Nop, CReqClockNanosleep_Post_RMTp_Nop },
0825   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_EINVAL,
0826     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0827     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0828     CReqClockNanosleep_Post_RMTp_Nop },
0829   { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_EINVAL,
0830     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0831     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0832     CReqClockNanosleep_Post_RMTp_Zero },
0833   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_ENOTSUP,
0834     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0835     CReqClockNanosleep_Post_Scheduler_Nop, CReqClockNanosleep_Post_RMTp_Nop },
0836   { 1, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_NA,
0837     CReqClockNanosleep_Post_Timer_NA, CReqClockNanosleep_Post_Expire_NA,
0838     CReqClockNanosleep_Post_Scheduler_NA, CReqClockNanosleep_Post_RMTp_NA },
0839   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0840     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0841     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0842     CReqClockNanosleep_Post_RMTp_Nop },
0843   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_EINVAL,
0844     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0845     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0846     CReqClockNanosleep_Post_RMTp_Zero },
0847   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0848     CReqClockNanosleep_Post_Timer_Monotonic,
0849     CReqClockNanosleep_Post_Expire_Last,
0850     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
0851   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0852     CReqClockNanosleep_Post_Timer_Monotonic,
0853     CReqClockNanosleep_Post_Expire_Absolute,
0854     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
0855   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0856     CReqClockNanosleep_Post_Timer_Monotonic,
0857     CReqClockNanosleep_Post_Expire_Last,
0858     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
0859   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0860     CReqClockNanosleep_Post_Timer_Monotonic,
0861     CReqClockNanosleep_Post_Expire_Relative,
0862     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
0863   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0864     CReqClockNanosleep_Post_Timer_Monotonic,
0865     CReqClockNanosleep_Post_Expire_Relative,
0866     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
0867   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0868     CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
0869     CReqClockNanosleep_Post_Scheduler_BlockUnblock,
0870     CReqClockNanosleep_Post_RMTp_Zero },
0871   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0872     CReqClockNanosleep_Post_Timer_Realtime,
0873     CReqClockNanosleep_Post_Expire_Last,
0874     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
0875   { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
0876     CReqClockNanosleep_Post_Timer_Realtime,
0877     CReqClockNanosleep_Post_Expire_Absolute,
0878     CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop }
0879 };
0880 
0881 static const uint8_t
0882 CReqClockNanosleep_Map[] = {
0883   6, 6, 8, 8, 9, 9, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0884   0, 0, 0, 0, 0, 0, 7, 2, 10, 8, 11, 12, 13, 6, 7, 2, 7, 2, 7, 2, 7, 2, 3, 0,
0885   3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 6, 6, 14, 14, 15, 15, 6, 6, 2, 2,
0886   2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 10,
0887   8, 11, 12, 13, 6, 7, 2, 7, 2, 7, 2, 7, 2, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
0888   3, 0, 3, 0, 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1,
0889   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5,
0890   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
0891 };
0892 
0893 static size_t CReqClockNanosleep_Scope( void *arg, char *buf, size_t n )
0894 {
0895   CReqClockNanosleep_Context *ctx;
0896 
0897   ctx = arg;
0898 
0899   if ( ctx->Map.in_action_loop ) {
0900     return T_get_scope( CReqClockNanosleep_PreDesc, buf, n, ctx->Map.pcs );
0901   }
0902 
0903   return 0;
0904 }
0905 
0906 static T_fixture CReqClockNanosleep_Fixture = {
0907   .setup = CReqClockNanosleep_Setup_Wrap,
0908   .stop = NULL,
0909   .teardown = CReqClockNanosleep_Teardown_Wrap,
0910   .scope = CReqClockNanosleep_Scope,
0911   .initial_context = &CReqClockNanosleep_Instance
0912 };
0913 
0914 static inline CReqClockNanosleep_Entry CReqClockNanosleep_PopEntry(
0915   CReqClockNanosleep_Context *ctx
0916 )
0917 {
0918   size_t index;
0919 
0920   index = ctx->Map.index;
0921   ctx->Map.index = index + 1;
0922   return CReqClockNanosleep_Entries[
0923     CReqClockNanosleep_Map[ index ]
0924   ];
0925 }
0926 
0927 static void CReqClockNanosleep_SetPreConditionStates(
0928   CReqClockNanosleep_Context *ctx
0929 )
0930 {
0931   ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0932   ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0933   ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
0934 
0935   if ( ctx->Map.entry.Pre_RQTpNSec_NA ) {
0936     ctx->Map.pcs[ 3 ] = CReqClockNanosleep_Pre_RQTpNSec_NA;
0937   } else {
0938     ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
0939   }
0940 
0941   if ( ctx->Map.entry.Pre_RQTpSec_NA ) {
0942     ctx->Map.pcs[ 4 ] = CReqClockNanosleep_Pre_RQTpSec_NA;
0943   } else {
0944     ctx->Map.pcs[ 4 ] = ctx->Map.pci[ 4 ];
0945   }
0946 
0947   ctx->Map.pcs[ 5 ] = ctx->Map.pci[ 5 ];
0948 }
0949 
0950 static void CReqClockNanosleep_TestVariant( CReqClockNanosleep_Context *ctx )
0951 {
0952   CReqClockNanosleep_Pre_ClockId_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0953   CReqClockNanosleep_Pre_Abstime_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0954   CReqClockNanosleep_Pre_RQTp_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0955   CReqClockNanosleep_Pre_RQTpNSec_Prepare( ctx, ctx->Map.pcs[ 3 ] );
0956   CReqClockNanosleep_Pre_RQTpSec_Prepare( ctx, ctx->Map.pcs[ 4 ] );
0957   CReqClockNanosleep_Pre_RMTp_Prepare( ctx, ctx->Map.pcs[ 5 ] );
0958   CReqClockNanosleep_Action( ctx );
0959   CReqClockNanosleep_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0960   CReqClockNanosleep_Post_Timer_Check( ctx, ctx->Map.entry.Post_Timer );
0961   CReqClockNanosleep_Post_Expire_Check( ctx, ctx->Map.entry.Post_Expire );
0962   CReqClockNanosleep_Post_Scheduler_Check(
0963     ctx,
0964     ctx->Map.entry.Post_Scheduler
0965   );
0966   CReqClockNanosleep_Post_RMTp_Check( ctx, ctx->Map.entry.Post_RMTp );
0967 }
0968 
0969 /**
0970  * @fn void T_case_body_CReqClockNanosleep( void )
0971  */
0972 T_TEST_CASE_FIXTURE( CReqClockNanosleep, &CReqClockNanosleep_Fixture )
0973 {
0974   CReqClockNanosleep_Context *ctx;
0975 
0976   ctx = T_fixture_context();
0977   ctx->Map.in_action_loop = true;
0978   ctx->Map.index = 0;
0979 
0980   for (
0981     ctx->Map.pci[ 0 ] = CReqClockNanosleep_Pre_ClockId_Monotonic;
0982     ctx->Map.pci[ 0 ] < CReqClockNanosleep_Pre_ClockId_NA;
0983     ++ctx->Map.pci[ 0 ]
0984   ) {
0985     for (
0986       ctx->Map.pci[ 1 ] = CReqClockNanosleep_Pre_Abstime_Yes;
0987       ctx->Map.pci[ 1 ] < CReqClockNanosleep_Pre_Abstime_NA;
0988       ++ctx->Map.pci[ 1 ]
0989     ) {
0990       for (
0991         ctx->Map.pci[ 2 ] = CReqClockNanosleep_Pre_RQTp_Valid;
0992         ctx->Map.pci[ 2 ] < CReqClockNanosleep_Pre_RQTp_NA;
0993         ++ctx->Map.pci[ 2 ]
0994       ) {
0995         for (
0996           ctx->Map.pci[ 3 ] = CReqClockNanosleep_Pre_RQTpNSec_Valid;
0997           ctx->Map.pci[ 3 ] < CReqClockNanosleep_Pre_RQTpNSec_NA;
0998           ++ctx->Map.pci[ 3 ]
0999         ) {
1000           for (
1001             ctx->Map.pci[ 4 ] = CReqClockNanosleep_Pre_RQTpSec_Negative;
1002             ctx->Map.pci[ 4 ] < CReqClockNanosleep_Pre_RQTpSec_NA;
1003             ++ctx->Map.pci[ 4 ]
1004           ) {
1005             for (
1006               ctx->Map.pci[ 5 ] = CReqClockNanosleep_Pre_RMTp_Valid;
1007               ctx->Map.pci[ 5 ] < CReqClockNanosleep_Pre_RMTp_NA;
1008               ++ctx->Map.pci[ 5 ]
1009             ) {
1010               ctx->Map.entry = CReqClockNanosleep_PopEntry( ctx );
1011 
1012               if ( ctx->Map.entry.Skip ) {
1013                 continue;
1014               }
1015 
1016               CReqClockNanosleep_SetPreConditionStates( ctx );
1017               CReqClockNanosleep_Prepare( ctx );
1018               CReqClockNanosleep_TestVariant( ctx );
1019             }
1020           }
1021         }
1022       }
1023     }
1024   }
1025 }
1026 
1027 /** @} */