source: rtems/testsuites/validation/tc-clock-nanosleep.c @ cd50bea

Last change on this file since cd50bea was cd50bea, checked in by Sebastian Huber <sebastian.huber@…>, on 06/22/22 at 09:02:33

score: Use right clock for threadq timeouts

Use CLOCK_REALTIME and CLOCK_MONOTONIC for relative thread queue timeouts
instead of CLOCK_REALTIME_COARSE and CLOCK_MONOTONIC_COARSE. This fixes an
issue with clock_nanosleep() in combination with clock_gettime().

Close #4669.

  • Property mode set to 100644
File size: 29.3 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSTestCaseCReqClockNanosleep
7 */
8
9/*
10 * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * This file is part of the RTEMS quality process and was automatically
36 * generated.  If you find something that needs to be fixed or
37 * worded better please post a report or patch to an RTEMS mailing list
38 * or raise a bug report:
39 *
40 * https://www.rtems.org/bugs.html
41 *
42 * For information on updating and regenerating please refer to the How-To
43 * section in the Software Requirements Engineering chapter of the
44 * RTEMS Software Engineering manual.  The manual is provided as a part of
45 * a release.  For development sources please refer to the online
46 * documentation at:
47 *
48 * https://docs.rtems.org
49 */
50
51#ifdef HAVE_CONFIG_H
52#include "config.h"
53#endif
54
55#include <errno.h>
56#include <limits.h>
57#include <rtems.h>
58#include <time.h>
59#include <rtems/test-scheduler.h>
60#include <rtems/score/timecounter.h>
61
62#include "tx-support.h"
63
64#include <rtems/test.h>
65
66/**
67 * @defgroup RTEMSTestCaseCReqClockNanosleep spec:/c/req/clock-nanosleep
68 *
69 * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0
70 *
71 * @{
72 */
73
74typedef enum {
75  CReqClockNanosleep_Pre_ClockId_Monotonic,
76  CReqClockNanosleep_Pre_ClockId_Realtime,
77  CReqClockNanosleep_Pre_ClockId_Invalid,
78  CReqClockNanosleep_Pre_ClockId_NA
79} CReqClockNanosleep_Pre_ClockId;
80
81typedef enum {
82  CReqClockNanosleep_Pre_Abstime_Yes,
83  CReqClockNanosleep_Pre_Abstime_No,
84  CReqClockNanosleep_Pre_Abstime_NA
85} CReqClockNanosleep_Pre_Abstime;
86
87typedef enum {
88  CReqClockNanosleep_Pre_RQTp_Valid,
89  CReqClockNanosleep_Pre_RQTp_Null,
90  CReqClockNanosleep_Pre_RQTp_NA
91} CReqClockNanosleep_Pre_RQTp;
92
93typedef enum {
94  CReqClockNanosleep_Pre_RQTpNSec_Valid,
95  CReqClockNanosleep_Pre_RQTpNSec_Invalid,
96  CReqClockNanosleep_Pre_RQTpNSec_NA
97} CReqClockNanosleep_Pre_RQTpNSec;
98
99typedef enum {
100  CReqClockNanosleep_Pre_RQTpSec_Negative,
101  CReqClockNanosleep_Pre_RQTpSec_FarFuture,
102  CReqClockNanosleep_Pre_RQTpSec_Future,
103  CReqClockNanosleep_Pre_RQTpSec_PastOrNow,
104  CReqClockNanosleep_Pre_RQTpSec_NA
105} CReqClockNanosleep_Pre_RQTpSec;
106
107typedef enum {
108  CReqClockNanosleep_Pre_RMTp_Valid,
109  CReqClockNanosleep_Pre_RMTp_Null,
110  CReqClockNanosleep_Pre_RMTp_NA
111} CReqClockNanosleep_Pre_RMTp;
112
113typedef enum {
114  CReqClockNanosleep_Post_Status_Zero,
115  CReqClockNanosleep_Post_Status_ENOTSUP,
116  CReqClockNanosleep_Post_Status_EINVAL,
117  CReqClockNanosleep_Post_Status_NA
118} CReqClockNanosleep_Post_Status;
119
120typedef enum {
121  CReqClockNanosleep_Post_Timer_Inactive,
122  CReqClockNanosleep_Post_Timer_Monotonic,
123  CReqClockNanosleep_Post_Timer_Realtime,
124  CReqClockNanosleep_Post_Timer_NA
125} CReqClockNanosleep_Post_Timer;
126
127typedef enum {
128  CReqClockNanosleep_Post_Expire_Last,
129  CReqClockNanosleep_Post_Expire_Absolute,
130  CReqClockNanosleep_Post_Expire_Relative,
131  CReqClockNanosleep_Post_Expire_NA
132} CReqClockNanosleep_Post_Expire;
133
134typedef enum {
135  CReqClockNanosleep_Post_Scheduler_Block,
136  CReqClockNanosleep_Post_Scheduler_BlockUnblock,
137  CReqClockNanosleep_Post_Scheduler_Nop,
138  CReqClockNanosleep_Post_Scheduler_NA
139} CReqClockNanosleep_Post_Scheduler;
140
141typedef enum {
142  CReqClockNanosleep_Post_RMTp_Zero,
143  CReqClockNanosleep_Post_RMTp_Nop,
144  CReqClockNanosleep_Post_RMTp_NA
145} CReqClockNanosleep_Post_RMTp;
146
147typedef struct {
148  uint32_t Skip : 1;
149  uint32_t Pre_ClockId_NA : 1;
150  uint32_t Pre_Abstime_NA : 1;
151  uint32_t Pre_RQTp_NA : 1;
152  uint32_t Pre_RQTpNSec_NA : 1;
153  uint32_t Pre_RQTpSec_NA : 1;
154  uint32_t Pre_RMTp_NA : 1;
155  uint32_t Post_Status : 2;
156  uint32_t Post_Timer : 2;
157  uint32_t Post_Expire : 2;
158  uint32_t Post_Scheduler : 2;
159  uint32_t Post_RMTp : 2;
160} CReqClockNanosleep_Entry;
161
162/**
163 * @brief Test context for spec:/c/req/clock-nanosleep test case.
164 */
165typedef struct {
166  /**
167   * @brief This member provides the scheduler operation records.
168   */
169  T_scheduler_log_4 scheduler_log;;
170
171  /**
172   * @brief This member contains the CLOCK_REALTIME value before the
173   *   clock_nanosleep() call.
174   */
175  struct timespec now_realtime;;
176
177  /**
178   * @brief This member contains the CLOCK_MONOTONIC value before the
179   *   clock_nanosleep() call.
180   */
181  struct timespec now_monotonic;;
182
183  /**
184   * @brief This member contains the worker task identifier.
185   */
186  rtems_id worker_id;;
187
188  /**
189   * @brief This member contains the timer information of the worker task.
190   */
191  TaskTimerInfo timer_info;;
192
193  /**
194   * @brief This member provides the object referenced by the ``rqtp``
195   *   parameter.
196   */
197  struct timespec rqtp_obj;
198
199  /**
200   * @brief This member provides the object referenced by the ``rmtp``
201   *   parameter.
202   */
203  struct timespec rmtp_obj;
204
205  /**
206   * @brief This member contains the return value of the clock_nanosleep()
207   *   call.
208   */
209  int status;
210
211  /**
212   * @brief This member specifies the ``clock_id`` parameter value.
213   */
214  clockid_t clock_id;
215
216  /**
217   * @brief This member specifies the ``flags`` parameter value.
218   */
219  int flags;
220
221  /**
222   * @brief This member specifies the ``rqtp`` parameter value.
223   */
224  const struct timespec *rqtp;
225
226  /**
227   * @brief This member specifies the ``rmtp`` parameter value.
228   */
229  struct timespec *rmtp;
230
231  struct {
232    /**
233     * @brief This member defines the pre-condition indices for the next
234     *   action.
235     */
236    size_t pci[ 6 ];
237
238    /**
239     * @brief This member defines the pre-condition states for the next action.
240     */
241    size_t pcs[ 6 ];
242
243    /**
244     * @brief If this member is true, then the test action loop is executed.
245     */
246    bool in_action_loop;
247
248    /**
249     * @brief This member contains the next transition map index.
250     */
251    size_t index;
252
253    /**
254     * @brief This member contains the current transition map entry.
255     */
256    CReqClockNanosleep_Entry entry;
257
258    /**
259     * @brief If this member is true, then the current transition variant
260     *   should be skipped.
261     */
262    bool skip;
263  } Map;
264} CReqClockNanosleep_Context;
265
266static CReqClockNanosleep_Context
267  CReqClockNanosleep_Instance;
268
269static const char * const CReqClockNanosleep_PreDesc_ClockId[] = {
270  "Monotonic",
271  "Realtime",
272  "Invalid",
273  "NA"
274};
275
276static const char * const CReqClockNanosleep_PreDesc_Abstime[] = {
277  "Yes",
278  "No",
279  "NA"
280};
281
282static const char * const CReqClockNanosleep_PreDesc_RQTp[] = {
283  "Valid",
284  "Null",
285  "NA"
286};
287
288static const char * const CReqClockNanosleep_PreDesc_RQTpNSec[] = {
289  "Valid",
290  "Invalid",
291  "NA"
292};
293
294static const char * const CReqClockNanosleep_PreDesc_RQTpSec[] = {
295  "Negative",
296  "FarFuture",
297  "Future",
298  "PastOrNow",
299  "NA"
300};
301
302static const char * const CReqClockNanosleep_PreDesc_RMTp[] = {
303  "Valid",
304  "Null",
305  "NA"
306};
307
308static const char * const * const CReqClockNanosleep_PreDesc[] = {
309  CReqClockNanosleep_PreDesc_ClockId,
310  CReqClockNanosleep_PreDesc_Abstime,
311  CReqClockNanosleep_PreDesc_RQTp,
312  CReqClockNanosleep_PreDesc_RQTpNSec,
313  CReqClockNanosleep_PreDesc_RQTpSec,
314  CReqClockNanosleep_PreDesc_RMTp,
315  NULL
316};
317
318typedef CReqClockNanosleep_Context Context;
319
320static void Worker( rtems_task_argument arg )
321{
322  Context *ctx;
323
324  ctx = (Context *) arg;
325
326  while ( true ) {
327    T_scheduler_log *log;
328    uint32_t         counter;
329
330    SuspendSelf();
331
332    log = T_scheduler_record_4( &ctx->scheduler_log );
333    T_null( log );
334
335    counter = GetTimecountCounter();
336    _Timecounter_Nanotime( &ctx->now_realtime );
337    SetTimecountCounter( counter );
338
339    counter = GetTimecountCounter();
340    _Timecounter_Nanouptime( &ctx->now_monotonic );
341    SetTimecountCounter( counter );
342
343    ctx->status = clock_nanosleep(
344      ctx->clock_id,
345      ctx->flags,
346      ctx->rqtp,
347      ctx->rmtp
348    );
349
350    (void) T_scheduler_record( NULL );
351  }
352}
353
354static void CReqClockNanosleep_Pre_ClockId_Prepare(
355  CReqClockNanosleep_Context    *ctx,
356  CReqClockNanosleep_Pre_ClockId state
357)
358{
359  switch ( state ) {
360    case CReqClockNanosleep_Pre_ClockId_Monotonic: {
361      /*
362       * While the ``clock_id`` parameter is equal to CLOCK_MONOTONIC.
363       */
364      ctx->clock_id = CLOCK_MONOTONIC;
365      break;
366    }
367
368    case CReqClockNanosleep_Pre_ClockId_Realtime: {
369      /*
370       * While the ``clock_id`` parameter is equal to CLOCK_REALTIME.
371       */
372      ctx->clock_id = CLOCK_REALTIME;
373      break;
374    }
375
376    case CReqClockNanosleep_Pre_ClockId_Invalid: {
377      /*
378       * While the ``clock_id`` parameter is an invalid clock identifier.
379       */
380      ctx->clock_id = INT_MAX;
381      break;
382    }
383
384    case CReqClockNanosleep_Pre_ClockId_NA:
385      break;
386  }
387}
388
389static void CReqClockNanosleep_Pre_Abstime_Prepare(
390  CReqClockNanosleep_Context    *ctx,
391  CReqClockNanosleep_Pre_Abstime state
392)
393{
394  switch ( state ) {
395    case CReqClockNanosleep_Pre_Abstime_Yes: {
396      /*
397       * While the ``flags`` parameter indicates an absolute time.
398       */
399      ctx->flags |= TIMER_ABSTIME;
400      break;
401    }
402
403    case CReqClockNanosleep_Pre_Abstime_No: {
404      /*
405       * While the ``flags`` parameter does not indicate an absolute time.
406       */
407      /* This is the default */
408      break;
409    }
410
411    case CReqClockNanosleep_Pre_Abstime_NA:
412      break;
413  }
414}
415
416static void CReqClockNanosleep_Pre_RQTp_Prepare(
417  CReqClockNanosleep_Context *ctx,
418  CReqClockNanosleep_Pre_RQTp state
419)
420{
421  switch ( state ) {
422    case CReqClockNanosleep_Pre_RQTp_Valid: {
423      /*
424       * While the ``rqtp`` parameter references an object of type struct
425       * timespec.
426       */
427      ctx->rqtp = &ctx->rqtp_obj;
428      break;
429    }
430
431    case CReqClockNanosleep_Pre_RQTp_Null: {
432      /*
433       * While the ``rqtp parameter is equal to NULL.
434       */
435      ctx->rqtp = NULL;
436      break;
437    }
438
439    case CReqClockNanosleep_Pre_RQTp_NA:
440      break;
441  }
442}
443
444static void CReqClockNanosleep_Pre_RQTpNSec_Prepare(
445  CReqClockNanosleep_Context     *ctx,
446  CReqClockNanosleep_Pre_RQTpNSec state
447)
448{
449  switch ( state ) {
450    case CReqClockNanosleep_Pre_RQTpNSec_Valid: {
451      /*
452       * While the ``tv_nsec`` member of the object referenced by the ``rqtp``
453       * parameter is a valid nanoseconds value.
454       */
455      ctx->rqtp_obj.tv_nsec = 999999999;
456      break;
457    }
458
459    case CReqClockNanosleep_Pre_RQTpNSec_Invalid: {
460      /*
461       * While the ``tv_nsec`` member of the object referenced by the ``rqtp``
462       * parameter is an invalid nanoseconds value.
463       */
464      ctx->rqtp_obj.tv_nsec = -1;
465      break;
466    }
467
468    case CReqClockNanosleep_Pre_RQTpNSec_NA:
469      break;
470  }
471}
472
473static void CReqClockNanosleep_Pre_RQTpSec_Prepare(
474  CReqClockNanosleep_Context    *ctx,
475  CReqClockNanosleep_Pre_RQTpSec state
476)
477{
478  switch ( state ) {
479    case CReqClockNanosleep_Pre_RQTpSec_Negative: {
480      /*
481       * While the ``tv_sec`` member of the object referenced by the ``rqtp``
482       * parameter is negative.
483       */
484      ctx->rqtp_obj.tv_sec = -238479;
485      break;
486    }
487
488    case CReqClockNanosleep_Pre_RQTpSec_FarFuture: {
489      /*
490       * While the ``tv_sec`` member of the object referenced by the ``rqtp``
491       * parameter specifies a time point which is past the implementation
492       * limit.
493       */
494      ctx->rqtp_obj.tv_sec = INT64_MAX;
495      break;
496    }
497
498    case CReqClockNanosleep_Pre_RQTpSec_Future: {
499      /*
500       * While the ``tv_sec`` member of the object referenced by the ``rqtp``
501       * parameter specifies a time point which is after the current time of
502       * the clock specified by the ``clock_id`` parameter and is within the
503       * implementation limits.
504       */
505      ctx->rqtp_obj.tv_sec = 1621322302;
506      break;
507    }
508
509    case CReqClockNanosleep_Pre_RQTpSec_PastOrNow: {
510      /*
511       * While the ``tv_sec`` member of the object referenced by the ``rqtp``
512       * parameter is non-negative and specifies a time point which is before
513       * or at the current time of the clock specified by the ``clock_id``
514       * parameter.
515       */
516      ctx->rqtp_obj.tv_sec = 0;
517
518      if ( ctx->rqtp_obj.tv_nsec == 999999999 ) {
519        ctx->rqtp_obj.tv_nsec = 0;
520      }
521      break;
522    }
523
524    case CReqClockNanosleep_Pre_RQTpSec_NA:
525      break;
526  }
527}
528
529static void CReqClockNanosleep_Pre_RMTp_Prepare(
530  CReqClockNanosleep_Context *ctx,
531  CReqClockNanosleep_Pre_RMTp state
532)
533{
534  switch ( state ) {
535    case CReqClockNanosleep_Pre_RMTp_Valid: {
536      /*
537       * While the ``rmtp`` parameter references an object of type struct
538       * timespec.
539       */
540      ctx->rmtp = &ctx->rmtp_obj;
541      break;
542    }
543
544    case CReqClockNanosleep_Pre_RMTp_Null: {
545      /*
546       * While the ``rmtp parameter is equal to NULL.
547       */
548      ctx->rmtp = NULL;
549      break;
550    }
551
552    case CReqClockNanosleep_Pre_RMTp_NA:
553      break;
554  }
555}
556
557static void CReqClockNanosleep_Post_Status_Check(
558  CReqClockNanosleep_Context    *ctx,
559  CReqClockNanosleep_Post_Status state
560)
561{
562  switch ( state ) {
563    case CReqClockNanosleep_Post_Status_Zero: {
564      /*
565       * The return value of clock_nanosleep() shall be equal to zero.
566       */
567      T_eq_int( ctx->status, 0 );
568      break;
569    }
570
571    case CReqClockNanosleep_Post_Status_ENOTSUP: {
572      /*
573       * The return value of clock_nanosleep() shall be equal to ENOTSUP.
574       */
575      T_eq_int( ctx->status, ENOTSUP );
576      break;
577    }
578
579    case CReqClockNanosleep_Post_Status_EINVAL: {
580      /*
581       * The return value of clock_nanosleep() shall be equal to EINVAL.
582       */
583      T_eq_int( ctx->status, EINVAL );
584      break;
585    }
586
587    case CReqClockNanosleep_Post_Status_NA:
588      break;
589  }
590}
591
592static void CReqClockNanosleep_Post_Timer_Check(
593  CReqClockNanosleep_Context   *ctx,
594  CReqClockNanosleep_Post_Timer state
595)
596{
597  switch ( state ) {
598    case CReqClockNanosleep_Post_Timer_Inactive: {
599      /*
600       * The timer of the calling task shall be inactive.
601       */
602      T_eq_int( ctx->timer_info.state, TASK_TIMER_INACTIVE );
603      break;
604    }
605
606    case CReqClockNanosleep_Post_Timer_Monotonic: {
607      /*
608       * The timer of the calling task shall be active using the
609       * CLOCK_MONOTONIC.
610       */
611      T_eq_int( ctx->timer_info.state, TASK_TIMER_MONOTONIC );
612      break;
613    }
614
615    case CReqClockNanosleep_Post_Timer_Realtime: {
616      /*
617       * The timer of the calling task shall be active using the
618       * CLOCK_REALTIME.
619       */
620      T_eq_int( ctx->timer_info.state, TASK_TIMER_REALTIME );
621      break;
622    }
623
624    case CReqClockNanosleep_Post_Timer_NA:
625      break;
626  }
627}
628
629static void CReqClockNanosleep_Post_Expire_Check(
630  CReqClockNanosleep_Context    *ctx,
631  CReqClockNanosleep_Post_Expire state
632)
633{
634  struct timespec expire;
635
636  switch ( state ) {
637    case CReqClockNanosleep_Post_Expire_Last: {
638      /*
639       * The timer of the calling task shall expire at the last valid time
640       * point of the clock specified by the ``clock_id`` parameter.
641       */
642      T_eq_u64( ctx->timer_info.expire_ticks, 0xffffffffffffffff );
643      break;
644    }
645
646    case CReqClockNanosleep_Post_Expire_Absolute: {
647      /*
648       * The timer of the calling task shall expire at the time point specified
649       * by the ``rqtp`` parameter.
650       */
651      T_eq_i64( ctx->timer_info.expire_timespec.tv_sec, ctx->rqtp_obj.tv_sec );
652      T_eq_long(
653        ctx->timer_info.expire_timespec.tv_nsec,
654        ctx->rqtp_obj.tv_nsec
655      );
656      break;
657    }
658
659    case CReqClockNanosleep_Post_Expire_Relative: {
660      /*
661       * The timer of the calling task shall expire at the time point specified
662       * by the sum of the current time of the clock specified by the
663       * ``clock_id`` parameter and the interval specified by the ``rqtp``
664       * parameter.
665       */
666      if ( ctx->clock_id == CLOCK_REALTIME ) {
667        expire = ctx->now_realtime;
668      } else {
669        expire = ctx->now_monotonic;
670      }
671
672      expire.tv_sec += ctx->rqtp_obj.tv_sec;
673      expire.tv_nsec += ctx->rqtp_obj.tv_nsec;
674
675      if ( expire.tv_nsec >= 1000000000 ) {
676        ++expire.tv_sec;
677        expire.tv_nsec -= 1000000000;
678      }
679
680      T_eq_i64( ctx->timer_info.expire_timespec.tv_sec, expire.tv_sec );
681      T_eq_long( ctx->timer_info.expire_timespec.tv_nsec, expire.tv_nsec );
682      break;
683    }
684
685    case CReqClockNanosleep_Post_Expire_NA:
686      break;
687  }
688}
689
690static void CReqClockNanosleep_Post_Scheduler_Check(
691  CReqClockNanosleep_Context       *ctx,
692  CReqClockNanosleep_Post_Scheduler state
693)
694{
695  switch ( state ) {
696    case CReqClockNanosleep_Post_Scheduler_Block: {
697      /*
698       * The calling task shall be blocked by the scheduler exactly once by the
699       * clock_nanosleep() call.
700       */
701      T_eq_sz( ctx->scheduler_log.header.recorded, 1 );
702      T_eq_int(
703        ctx->scheduler_log.events[ 0 ].operation,
704        T_SCHEDULER_BLOCK
705      );
706      break;
707    }
708
709    case CReqClockNanosleep_Post_Scheduler_BlockUnblock: {
710      /*
711       * The calling task shall be blocked exactly once by the scheduler and
712       * then unblocked in the same thread dispatch critical section by the
713       * clock_nanosleep() call.
714       */
715      T_eq_sz( ctx->scheduler_log.header.recorded, 2 );
716      T_eq_int(
717        ctx->scheduler_log.events[ 0 ].operation,
718        T_SCHEDULER_BLOCK
719      );
720      T_eq_int(
721        ctx->scheduler_log.events[ 1 ].operation,
722        T_SCHEDULER_UNBLOCK
723      );
724      break;
725    }
726
727    case CReqClockNanosleep_Post_Scheduler_Nop: {
728      /*
729       * The calling task shall not be altered by the scheduler by the
730       * clock_nanosleep() call.
731       */
732      T_eq_sz( ctx->scheduler_log.header.recorded, 0 );
733      break;
734    }
735
736    case CReqClockNanosleep_Post_Scheduler_NA:
737      break;
738  }
739}
740
741static void CReqClockNanosleep_Post_RMTp_Check(
742  CReqClockNanosleep_Context  *ctx,
743  CReqClockNanosleep_Post_RMTp state
744)
745{
746  switch ( state ) {
747    case CReqClockNanosleep_Post_RMTp_Zero: {
748      /*
749       * The object referenced by the ``rmtp`` parameter shall be cleared to
750       * zero after the return of the clock_nanosleep() call.
751       */
752      T_eq_i64( ctx->rmtp_obj.tv_sec, 0 );
753      T_eq_long( ctx->rmtp_obj.tv_nsec, 0 );
754      break;
755    }
756
757    case CReqClockNanosleep_Post_RMTp_Nop: {
758      /*
759       * Objects referenced by the ``rmtp`` parameter in past calls to
760       * clock_nanosleep() shall not be accessed by the clock_nanosleep() call.
761       */
762      T_eq_i64( ctx->rmtp_obj.tv_sec, -1 );
763      T_eq_long( ctx->rmtp_obj.tv_nsec, -1 );
764      break;
765    }
766
767    case CReqClockNanosleep_Post_RMTp_NA:
768      break;
769  }
770}
771
772static void CReqClockNanosleep_Setup( CReqClockNanosleep_Context *ctx )
773{
774  rtems_time_of_day now = { 1988, 1, 1, 0, 0, 0, 0 };
775  T_rsc_success( rtems_clock_set( &now ) );
776  SetSelfPriority( PRIO_NORMAL );
777  ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
778  StartTask( ctx->worker_id, Worker, ctx );
779}
780
781static void CReqClockNanosleep_Setup_Wrap( void *arg )
782{
783  CReqClockNanosleep_Context *ctx;
784
785  ctx = arg;
786  ctx->Map.in_action_loop = false;
787  CReqClockNanosleep_Setup( ctx );
788}
789
790static void CReqClockNanosleep_Teardown( CReqClockNanosleep_Context *ctx )
791{
792  DeleteTask( ctx->worker_id );
793  RestoreRunnerPriority();
794}
795
796static void CReqClockNanosleep_Teardown_Wrap( void *arg )
797{
798  CReqClockNanosleep_Context *ctx;
799
800  ctx = arg;
801  ctx->Map.in_action_loop = false;
802  CReqClockNanosleep_Teardown( ctx );
803}
804
805static void CReqClockNanosleep_Prepare( CReqClockNanosleep_Context *ctx )
806{
807  ctx->status = -1;
808  ctx->flags = 0;
809  ctx->rmtp_obj.tv_sec = -1;
810  ctx->rmtp_obj.tv_nsec = -1;
811}
812
813static void CReqClockNanosleep_Action( CReqClockNanosleep_Context *ctx )
814{
815  ResumeTask( ctx->worker_id );
816  (void) T_scheduler_record( NULL );
817  GetTaskTimerInfo( ctx->worker_id, &ctx->timer_info );
818  ClockTick();
819  FinalClockTick();
820}
821
822static const CReqClockNanosleep_Entry
823CReqClockNanosleep_Entries[] = {
824  { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_EINVAL,
825    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
826    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
827    CReqClockNanosleep_Post_RMTp_Nop },
828  { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_ENOTSUP,
829    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
830    CReqClockNanosleep_Post_Scheduler_Nop, CReqClockNanosleep_Post_RMTp_Nop },
831  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_EINVAL,
832    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
833    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
834    CReqClockNanosleep_Post_RMTp_Nop },
835  { 0, 0, 0, 0, 1, 1, 0, CReqClockNanosleep_Post_Status_EINVAL,
836    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
837    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
838    CReqClockNanosleep_Post_RMTp_Zero },
839  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_ENOTSUP,
840    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
841    CReqClockNanosleep_Post_Scheduler_Nop, CReqClockNanosleep_Post_RMTp_Nop },
842  { 1, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_NA,
843    CReqClockNanosleep_Post_Timer_NA, CReqClockNanosleep_Post_Expire_NA,
844    CReqClockNanosleep_Post_Scheduler_NA, CReqClockNanosleep_Post_RMTp_NA },
845  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
846    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
847    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
848    CReqClockNanosleep_Post_RMTp_Nop },
849  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_EINVAL,
850    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
851    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
852    CReqClockNanosleep_Post_RMTp_Zero },
853  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
854    CReqClockNanosleep_Post_Timer_Monotonic,
855    CReqClockNanosleep_Post_Expire_Last,
856    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
857  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
858    CReqClockNanosleep_Post_Timer_Realtime,
859    CReqClockNanosleep_Post_Expire_Last,
860    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
861  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
862    CReqClockNanosleep_Post_Timer_Monotonic,
863    CReqClockNanosleep_Post_Expire_Absolute,
864    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
865  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
866    CReqClockNanosleep_Post_Timer_Inactive, CReqClockNanosleep_Post_Expire_NA,
867    CReqClockNanosleep_Post_Scheduler_BlockUnblock,
868    CReqClockNanosleep_Post_RMTp_Zero },
869  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
870    CReqClockNanosleep_Post_Timer_Realtime,
871    CReqClockNanosleep_Post_Expire_Absolute,
872    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
873  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
874    CReqClockNanosleep_Post_Timer_Monotonic,
875    CReqClockNanosleep_Post_Expire_Last,
876    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
877  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
878    CReqClockNanosleep_Post_Timer_Monotonic,
879    CReqClockNanosleep_Post_Expire_Relative,
880    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
881  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
882    CReqClockNanosleep_Post_Timer_Monotonic,
883    CReqClockNanosleep_Post_Expire_Relative,
884    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop },
885  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
886    CReqClockNanosleep_Post_Timer_Realtime,
887    CReqClockNanosleep_Post_Expire_Last,
888    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
889  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
890    CReqClockNanosleep_Post_Timer_Realtime,
891    CReqClockNanosleep_Post_Expire_Relative,
892    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Zero },
893  { 0, 0, 0, 0, 0, 0, 0, CReqClockNanosleep_Post_Status_Zero,
894    CReqClockNanosleep_Post_Timer_Realtime,
895    CReqClockNanosleep_Post_Expire_Relative,
896    CReqClockNanosleep_Post_Scheduler_Block, CReqClockNanosleep_Post_RMTp_Nop }
897};
898
899static const uint8_t
900CReqClockNanosleep_Map[] = {
901  6, 6, 8, 8, 10, 10, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
902  0, 0, 0, 0, 0, 0, 0, 7, 2, 13, 8, 14, 15, 11, 6, 7, 2, 7, 2, 7, 2, 7, 2, 3,
903  0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 6, 6, 9, 9, 12, 12, 6, 6, 2, 2,
904  2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 16,
905  9, 17, 18, 11, 6, 7, 2, 7, 2, 7, 2, 7, 2, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
906  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,
907  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,
908  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
909};
910
911static size_t CReqClockNanosleep_Scope( void *arg, char *buf, size_t n )
912{
913  CReqClockNanosleep_Context *ctx;
914
915  ctx = arg;
916
917  if ( ctx->Map.in_action_loop ) {
918    return T_get_scope( CReqClockNanosleep_PreDesc, buf, n, ctx->Map.pcs );
919  }
920
921  return 0;
922}
923
924static T_fixture CReqClockNanosleep_Fixture = {
925  .setup = CReqClockNanosleep_Setup_Wrap,
926  .stop = NULL,
927  .teardown = CReqClockNanosleep_Teardown_Wrap,
928  .scope = CReqClockNanosleep_Scope,
929  .initial_context = &CReqClockNanosleep_Instance
930};
931
932static inline CReqClockNanosleep_Entry CReqClockNanosleep_PopEntry(
933  CReqClockNanosleep_Context *ctx
934)
935{
936  size_t index;
937
938  index = ctx->Map.index;
939  ctx->Map.index = index + 1;
940  return CReqClockNanosleep_Entries[
941    CReqClockNanosleep_Map[ index ]
942  ];
943}
944
945static void CReqClockNanosleep_SetPreConditionStates(
946  CReqClockNanosleep_Context *ctx
947)
948{
949  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
950  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
951  ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
952
953  if ( ctx->Map.entry.Pre_RQTpNSec_NA ) {
954    ctx->Map.pcs[ 3 ] = CReqClockNanosleep_Pre_RQTpNSec_NA;
955  } else {
956    ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
957  }
958
959  if ( ctx->Map.entry.Pre_RQTpSec_NA ) {
960    ctx->Map.pcs[ 4 ] = CReqClockNanosleep_Pre_RQTpSec_NA;
961  } else {
962    ctx->Map.pcs[ 4 ] = ctx->Map.pci[ 4 ];
963  }
964
965  ctx->Map.pcs[ 5 ] = ctx->Map.pci[ 5 ];
966}
967
968static void CReqClockNanosleep_TestVariant( CReqClockNanosleep_Context *ctx )
969{
970  CReqClockNanosleep_Pre_ClockId_Prepare( ctx, ctx->Map.pcs[ 0 ] );
971  CReqClockNanosleep_Pre_Abstime_Prepare( ctx, ctx->Map.pcs[ 1 ] );
972  CReqClockNanosleep_Pre_RQTp_Prepare( ctx, ctx->Map.pcs[ 2 ] );
973  CReqClockNanosleep_Pre_RQTpNSec_Prepare( ctx, ctx->Map.pcs[ 3 ] );
974  CReqClockNanosleep_Pre_RQTpSec_Prepare( ctx, ctx->Map.pcs[ 4 ] );
975  CReqClockNanosleep_Pre_RMTp_Prepare( ctx, ctx->Map.pcs[ 5 ] );
976  CReqClockNanosleep_Action( ctx );
977  CReqClockNanosleep_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
978  CReqClockNanosleep_Post_Timer_Check( ctx, ctx->Map.entry.Post_Timer );
979  CReqClockNanosleep_Post_Expire_Check( ctx, ctx->Map.entry.Post_Expire );
980  CReqClockNanosleep_Post_Scheduler_Check(
981    ctx,
982    ctx->Map.entry.Post_Scheduler
983  );
984  CReqClockNanosleep_Post_RMTp_Check( ctx, ctx->Map.entry.Post_RMTp );
985}
986
987/**
988 * @fn void T_case_body_CReqClockNanosleep( void )
989 */
990T_TEST_CASE_FIXTURE( CReqClockNanosleep, &CReqClockNanosleep_Fixture )
991{
992  CReqClockNanosleep_Context *ctx;
993
994  ctx = T_fixture_context();
995  ctx->Map.in_action_loop = true;
996  ctx->Map.index = 0;
997
998  for (
999    ctx->Map.pci[ 0 ] = CReqClockNanosleep_Pre_ClockId_Monotonic;
1000    ctx->Map.pci[ 0 ] < CReqClockNanosleep_Pre_ClockId_NA;
1001    ++ctx->Map.pci[ 0 ]
1002  ) {
1003    for (
1004      ctx->Map.pci[ 1 ] = CReqClockNanosleep_Pre_Abstime_Yes;
1005      ctx->Map.pci[ 1 ] < CReqClockNanosleep_Pre_Abstime_NA;
1006      ++ctx->Map.pci[ 1 ]
1007    ) {
1008      for (
1009        ctx->Map.pci[ 2 ] = CReqClockNanosleep_Pre_RQTp_Valid;
1010        ctx->Map.pci[ 2 ] < CReqClockNanosleep_Pre_RQTp_NA;
1011        ++ctx->Map.pci[ 2 ]
1012      ) {
1013        for (
1014          ctx->Map.pci[ 3 ] = CReqClockNanosleep_Pre_RQTpNSec_Valid;
1015          ctx->Map.pci[ 3 ] < CReqClockNanosleep_Pre_RQTpNSec_NA;
1016          ++ctx->Map.pci[ 3 ]
1017        ) {
1018          for (
1019            ctx->Map.pci[ 4 ] = CReqClockNanosleep_Pre_RQTpSec_Negative;
1020            ctx->Map.pci[ 4 ] < CReqClockNanosleep_Pre_RQTpSec_NA;
1021            ++ctx->Map.pci[ 4 ]
1022          ) {
1023            for (
1024              ctx->Map.pci[ 5 ] = CReqClockNanosleep_Pre_RMTp_Valid;
1025              ctx->Map.pci[ 5 ] < CReqClockNanosleep_Pre_RMTp_NA;
1026              ++ctx->Map.pci[ 5 ]
1027            ) {
1028              ctx->Map.entry = CReqClockNanosleep_PopEntry( ctx );
1029
1030              if ( ctx->Map.entry.Skip ) {
1031                continue;
1032              }
1033
1034              CReqClockNanosleep_SetPreConditionStates( ctx );
1035              CReqClockNanosleep_Prepare( ctx );
1036              CReqClockNanosleep_TestVariant( ctx );
1037            }
1038          }
1039        }
1040      }
1041    }
1042  }
1043}
1044
1045/** @} */
Note: See TracBrowser for help on using the repository browser.