diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-11 10:45:27 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-12 13:54:23 +0200 |
commit | 9c21cfc1dc6f5c2980a692fdfc87f4e7cb3e8222 (patch) | |
tree | 0214efea120b49bca6d276f70719f5f602e20093 | |
parent | 07a8c91dff15c78dff4cb6eddc0fe52181b9e0ee (diff) |
score: Port large time delta support to RTEMS
-rw-r--r-- | cpukit/score/src/kern_tc.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index 096de85880..c013c16f87 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -170,7 +170,7 @@ struct timehands { int64_t th_adjustment; #endif /* __rtems__ */ 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; @@ -226,6 +226,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 }, @@ -381,7 +382,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; @@ -544,17 +550,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__ */ @@ -1649,12 +1668,24 @@ _Timecounter_Windup(struct bintime *new_boottimebin, #ifndef __rtems__ tc_min_ticktock_freq = max(1, timecounter->tc_frequency / (((uint64_t)timecounter->tc_counter_mask + 1) / 3)); +#else /* __rtems__ */ + /* + * For RTEMS, we can do the scale and large delta calculation + * here, since we do not support th_adjustment. It is + * condsidered to be zero. + */ + scale = (uint64_t)1 << 63; + scale /= th->th_counter->tc_frequency; + th->th_scale = scale * 2; + th->th_large_delta = MIN(((uint64_t)1 << 63) / scale, + UINT_MAX); #endif /* __rtems__ */ #ifdef FFCLOCK ffclock_change_tc(th); #endif } +#ifndef __rtems__ /*- * Recalculate the scaling factor. We want the number of 1/2^64 * fractions of a second per period of the hardware counter, taking @@ -1679,12 +1710,13 @@ _Timecounter_Windup(struct bintime *new_boottimebin, * */ scale = (uint64_t)1 << 63; -#ifndef __rtems__ scale += (th->th_adjustment / 1024) * 2199; -#endif /* __rtems__ */ scale /= th->th_counter->tc_frequency; th->th_scale = scale * 2; th->th_large_delta = MIN(((uint64_t)1 << 63) / scale, UINT_MAX); +#else + /* See above "Now is a good time to change timecounters." */ +#endif /* __rtems__ */ /* * Now that the struct timehands is again consistent, set the new |