Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSTestFrameworkImpl
0007  *
0008  * @brief This source file contains the implementation of the time and ticks
0009  *   test support.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2018 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #undef __STRICT_ANSI__
0038 
0039 #include <rtems/test.h>
0040 
0041 #include <inttypes.h>
0042 #include <stdatomic.h>
0043 #include <stdio.h>
0044 #include <time.h>
0045 
0046 #ifdef __rtems__
0047 #include <rtems.h>
0048 #include <rtems/counter.h>
0049 #include <rtems/score/timecounter.h>
0050 #endif
0051 
0052 #ifdef __rtems__
0053 static T_time
0054 round_sbt(T_time time)
0055 {
0056     /*
0057      * One 1ns consists of 4.30 fractions of 1/2**32.  Round up close to
0058      * the middle.  This turns the conversion mapping of struct timespec to
0059      * sbintime_t and back into the identity function.
0060      */
0061     return time + 2;
0062 }
0063 #endif
0064 
0065 const char *
0066 T_time_to_string_ns(T_time time, T_time_string string)
0067 {
0068     uint32_t s;
0069     uint32_t f;
0070 
0071 #ifdef __rtems__
0072     time = round_sbt(time);
0073     s = (uint32_t)(time >> 32);
0074     f = (uint32_t)(((uint64_t)1000000000 * (uint32_t)time) >> 32);
0075 #else
0076     s = (uint32_t)(time / 1000000000);
0077     f = (uint32_t)(time % 1000000000);
0078 #endif
0079 
0080     (void)T_snprintf(string, sizeof(T_time_string),
0081         "%" PRIu32 ".%09" PRIu32, s, f);
0082     return string;
0083 }
0084 
0085 const char *
0086 T_time_to_string_us(T_time time, T_time_string string)
0087 {
0088     uint32_t s;
0089     uint32_t f;
0090 
0091 #ifdef __rtems__
0092     time = round_sbt(time);
0093     s = (uint32_t)(time >> 32);
0094     f = (uint32_t)(((uint64_t)1000000 * (uint32_t)time) >> 32);
0095 #else
0096     time /= 1000;
0097     s = (uint32_t)(time / 1000000);
0098     f = (uint32_t)(time % 1000000);
0099 #endif
0100 
0101     (void)T_snprintf(string, sizeof(T_time_string),
0102         "%" PRIu32 ".%06" PRIu32, s, f);
0103     return string;
0104 }
0105 
0106 const char *
0107 T_time_to_string_ms(T_time time, T_time_string string)
0108 {
0109     uint32_t s;
0110     uint32_t f;
0111 
0112 #ifdef __rtems__
0113     time = round_sbt(time);
0114     s = (uint32_t)(time >> 32);
0115     f = (uint32_t)(((uint64_t)1000 * (uint32_t)time) >> 32);
0116 #else
0117     time /= 1000000;
0118     s = (uint32_t)(time / 1000);
0119     f = (uint32_t)(time % 1000);
0120 #endif
0121 
0122     (void)T_snprintf(string, sizeof(T_time_string),
0123         "%" PRIu32 ".%03" PRIu32, s, f);
0124     return string;
0125 }
0126 
0127 const char *
0128 T_time_to_string_s(T_time time, T_time_string string)
0129 {
0130     uint32_t s;
0131 
0132 #ifdef __rtems__
0133     time = round_sbt(time);
0134     s = (uint32_t)(time >> 32);
0135 #else
0136     s = (uint32_t)(time / 1000000000);
0137 #endif
0138 
0139     (void)T_snprintf(string, sizeof(T_time_string), "%" PRIu32, s);
0140     return string;
0141 }
0142 
0143 const char *
0144 T_ticks_to_string_ns(T_ticks ticks, T_time_string string)
0145 {
0146     return T_time_to_string_ns(T_ticks_to_time(ticks), string);
0147 }
0148 
0149 const char *
0150 T_ticks_to_string_us(T_ticks ticks, T_time_string string)
0151 {
0152     return T_time_to_string_us(T_ticks_to_time(ticks), string);
0153 }
0154 
0155 const char *
0156 T_ticks_to_string_ms(T_ticks ticks, T_time_string string)
0157 {
0158     return T_time_to_string_ms(T_ticks_to_time(ticks), string);
0159 }
0160 
0161 const char *
0162 T_ticks_to_string_s(T_ticks ticks, T_time_string string)
0163 {
0164     return T_time_to_string_s(T_ticks_to_time(ticks), string);
0165 }
0166 
0167 uint64_t
0168 T_ticks_to_time(T_ticks ticks)
0169 {
0170 #ifdef __rtems__
0171     return (uint64_t)rtems_counter_ticks_to_sbintime(ticks);
0172 #else
0173     return ticks;
0174 #endif
0175 }
0176 
0177 T_ticks
0178 T_time_to_ticks(T_time time)
0179 {
0180 #ifdef __rtems__
0181     return rtems_counter_sbintime_to_ticks((sbintime_t)time);
0182 #else
0183     return time;
0184 #endif
0185 }
0186 
0187 T_time
0188 T_seconds_and_nanoseconds_to_time(uint32_t s, uint32_t ns)
0189 {
0190 #ifdef __rtems__
0191     struct timespec ts;
0192 
0193     ts.tv_sec = s;
0194     ts.tv_nsec = (long)ns;
0195     return (T_time)tstosbt(ts);
0196 #else
0197     return (T_time)s * (T_time)1000000000 + (T_time)ns;
0198 #endif
0199 }
0200 
0201 void
0202 T_time_to_seconds_and_nanoseconds(T_time time, uint32_t *s, uint32_t *ns)
0203 {
0204 #ifdef __rtems__
0205     time = round_sbt(time);
0206     *s = (uint32_t)(time >> 32);
0207     *ns = (uint32_t)(((uint64_t)1000000000 * (uint32_t)time) >> 32);
0208 #else
0209     *s = (uint32_t)(time / 1000000000);
0210     *ns = (uint32_t)(time % 1000000000);
0211 #endif
0212 }
0213 
0214 T_time
0215 T_now_clock(void)
0216 {
0217 #ifndef __rtems__
0218     struct timespec tp;
0219 
0220     (void)clock_gettime(CLOCK_MONOTONIC, &tp);
0221     return (T_time)tp.tv_sec * (T_time)1000000000 + (T_time)tp.tv_nsec;
0222 #else /* __rtems__ */
0223     return (T_time)_Timecounter_Sbinuptime();
0224 #endif /* __rtems__ */
0225 }
0226 
0227 #ifndef __rtems__
0228 T_ticks
0229 T_tick(void)
0230 {
0231     return T_now();
0232 }
0233 #endif
0234 
0235 static atomic_uint T_dummy_time;
0236 
0237 T_time
0238 T_now_dummy(void)
0239 {
0240     return atomic_fetch_add_explicit(&T_dummy_time, 1,
0241         memory_order_relaxed);
0242 }
0243 
0244 #ifndef __rtems__
0245 T_time
0246 T_now_tick(void)
0247 {
0248     return T_ticks_to_time(T_tick());
0249 }
0250 #else /* __rtems__ */
0251 #if defined(RTEMS_SMP)
0252 static rtems_interrupt_lock T_time_lock =
0253   RTEMS_INTERRUPT_LOCK_INITIALIZER("Test Time Lock");
0254 #endif
0255 
0256 static T_ticks T_tick_last;
0257 
0258 static T_time T_tick_time;
0259 
0260 static bool T_tick_initialized;
0261 
0262 T_time
0263 T_now_tick(void)
0264 {
0265     rtems_interrupt_lock_context lock_context;
0266     T_ticks ticks;
0267     T_time now;
0268 
0269     ticks = T_tick();
0270 
0271     rtems_interrupt_lock_acquire(&T_time_lock, &lock_context);
0272 
0273     if (T_tick_initialized) {
0274         T_ticks last;
0275 
0276         last = T_tick_last;
0277         T_tick_last = ticks;
0278 
0279         now = T_tick_time;
0280         now += T_ticks_to_time(ticks - last);
0281         T_tick_time = now;
0282     } else {
0283         T_tick_initialized = true;
0284         T_tick_last = ticks;
0285         now = 0;
0286     }
0287 
0288     rtems_interrupt_lock_release(&T_time_lock, &lock_context);
0289 
0290     return now;
0291 }
0292 #endif /* __rtems__ */