Re: Large timecounter delta handling

From: Sebastian Huber <sebastian.huber_at_embedded-brains.de>
Date: Mon, 11 Oct 2021 09:31:29 UTC
On 11/10/2021 10:58, Konstantin Belousov wrote:
> On Mon, Oct 11, 2021 at 09:53:31AM +0200, Sebastian Huber wrote:
>> Hello,
>>
>> I synchronize currently the port of the FreeBSD timecounters to RTEMS. I
>> have to write test cases for all code we use in RTEMS. In 2020 some code was
>> added to fix integer overflow issues with large time deltas while getting
>> the time from a timehand.
>>
>> https://github.com/freebsd/freebsd-src/commit/6cf2362e2c7e9061611f93a48ec654a5b7451d6b#diff-8b8e2f8e41e6a847f14ab08c7d50454c20a4a135f2c2241d91687c0832c1d99e
>>
>> If a time delta obtained by tc_delta(th) is greater than or equal to
>> th->th_large_delta, then some extra calculation is carried out.
>>
>> The th->th_large_delta is computed like this
>>
>> 	scale = (uint64_t)1 << 63;
>> 	scale += (th->th_adjustment / 1024) * 2199;
>> 	scale /= th->th_counter->tc_frequency;
>> 	th->th_scale = scale * 2;
>> 	th->th_large_delta = MIN(((uint64_t)1 << 63) / scale, UINT_MAX);
>>
>> If we ignore the th->th_adjustment (== 0), then we have ideally
>>
>> scale = 2**64 / f
>> th->th_large_delta = MIN( f / 2, UINT_MAX )
>>
>> Does this mean that we only need the large delta processing if a timehand
>> was not updated for about 0.5s?
> 
> I do not understand your question.  We need large_delta to handle overflows
> in bintime_off().  tc_large_delta is computed in advance during windup to
> avoid this calculation in time reading code.

Yes, I also ask since we never got bug reports for RTEMS related to such 
a scenario. No updates for about 0.5s would mean that an RTEMS 
application is already in a completely undefined system state. Maybe it 
can happen in FreeBSD systems under transient overload conditions.

It could happen in RTEMS, if we have an extremely long boot time, since 
during boot interrupts are disabled.

> 
> Your question is more like "under which conditions we switch to use
> tc_large_delta path in bintime_off()?"  Then it is mostly right, that
> long intervals between tc_windup() calls would trigger it, and it seems
> that indeed it is around 0.5 sec.

Yes, this was the question.

I think the initialization value should be 50000:

diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 81d373b3b1d0..a4792e31abd4 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -87,7 +87,7 @@ static struct timehands ths[16] = {
      [0] =  {
         .th_counter = &dummy_timecounter,
         .th_scale = (uint64_t)-1 / 1000000,
-       .th_large_delta = 1000000,
+       .th_large_delta = 500000,
         .th_offset = { .sec = 1 },
         .th_generation = 1,
      },

> 
> If you have a controlled environment, just skip some tc_windup() calls
> to see.

Yes, I can also use a software timecounter for these tests.

-- 
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/