[rtems commit] score: Port large time delta support to RTEMS

Sebastian Huber sebh at rtems.org
Mon Nov 15 08:15:17 UTC 2021


Module:    rtems
Branch:    master
Commit:    52c53a5914f5fbe92e5b935df2b3c3fadb47d1d5
Changeset: http://git.rtems.org/rtems/commit/?id=52c53a5914f5fbe92e5b935df2b3c3fadb47d1d5

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Oct 11 10:45:27 2021 +0200

score: Port large time delta support to RTEMS

---

 cpukit/score/src/kern_tc.c                | 25 ++++++++++++++++++++++---
 testsuites/sptests/sptimecounter01/init.c |  4 ++--
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index e43e322..5544b9e 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -175,7 +175,7 @@ struct timehands {
 	struct timecounter	*th_counter;
 	int64_t			th_adjustment;
 	uint64_t		th_scale;
-	u_int			th_large_delta;
+	uint32_t		th_large_delta;
 	uint32_t	 	th_offset_count;
 	struct bintime		th_offset;
 	struct bintime		th_bintime;
@@ -235,6 +235,7 @@ static struct timehands th0 = {
 	.th_counter = &dummy_timecounter,
 	.th_scale = (uint64_t)-1 / 1000000,
 	.th_offset = { .sec = 1 },
+	.th_large_delta = 1000000,
 	.th_generation = UINT_MAX,
 #ifdef __rtems__
 	.th_bintime = { .sec = TOD_SECONDS_1970_THROUGH_1988 },
@@ -390,7 +391,12 @@ bintime_off(struct bintime *bt, u_int off)
 	struct timehands *th;
 	struct bintime *btp;
 	uint64_t scale, x;
+#ifndef __rtems__
 	u_int delta, gen, large_delta;
+#else /* __rtems__ */
+	uint32_t delta, large_delta;
+	u_int gen;
+#endif /* __rtems__ */
 
 	do {
 		th = timehands;
@@ -553,17 +559,30 @@ sbintime_t
 _Timecounter_Sbinuptime(void)
 {
 	struct timehands *th;
-	uint32_t gen;
 	sbintime_t sbt;
+	uint64_t scale;
+	uint32_t delta;
+	uint32_t large_delta;
+	u_int gen;
 
 	do {
 		th = timehands;
 		gen = atomic_load_acq_int(&th->th_generation);
 		sbt = bttosbt(th->th_offset);
-		sbt += (th->th_scale * tc_delta(th)) >> 32;
+		scale = th->th_scale;
+		delta = tc_delta(th);
+		large_delta = th->th_large_delta;
 		atomic_thread_fence_acq();
 	} while (gen == 0 || gen != th->th_generation);
 
+	if (__predict_false(delta >= large_delta)) {
+		/* Avoid overflow for scale * delta. */
+		sbt += (scale >> 32) * delta;
+		sbt += ((scale & 0xffffffff) * delta) >> 32;
+	} else {
+		sbt += (scale * delta) >> 32;
+	}
+
 	return (sbt);
 }
 #endif /* __rtems__ */
diff --git a/testsuites/sptests/sptimecounter01/init.c b/testsuites/sptests/sptimecounter01/init.c
index 23671e3..bfeb216 100644
--- a/testsuites/sptests/sptimecounter01/init.c
+++ b/testsuites/sptests/sptimecounter01/init.c
@@ -204,11 +204,11 @@ void boot_card(const char *cmdline)
   assert(bt.sec == 1);
   assert(bt.frac == 18446744073708);
 
-  /* Ensure that the fraction overflows and the second remains constant */
+  /* Check that a large delta yields a correct time */
   ctx->counter = (0xf0000000 | 1) + TEST_FREQ;
   rtems_bsd_binuptime(&bt);
   assert(ctx->counter == (0xf0000000 | 2) + TEST_FREQ);
-  assert(bt.sec == 1);
+  assert(bt.sec == 2);
   assert(bt.frac == 18446742522092);
 
   test_install(ctx);



More information about the vc mailing list