[PATCH 2/2] rtems: Add more clock tick functions

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Aug 25 06:50:24 UTC 2014


On 24/08/14 11:42, Pavel Pisa wrote:
> Hello Sebastian,
>
> On Sunday 24 of August 2014 10:54:15 Sebastian Huber wrote:
>> On 08/22/2014 10:14 PM, Pavel Pisa wrote:
>>>>> +RTEMS_INLINE_ROUTINE bool rtems_clock_ticks_before(
>>>>>
>>>>>>> +  rtems_interval ticks
>>>>>>> +)
>>>>>>> +{
>>>>>>> +  return ( (int32_t) ticks - (int32_t) _Watchdog_Ticks_since_boot )
>>>>>>>> 0;
>>>>>
>>>>> Why not just return _Watchdog_Ticks_since_boot < ticks;
>>
>> Yes, this doesn't work if the counter overflows.
>>
>>> For sure not, to have correctly working overflow arithmetics
>>> it is required to use subtraction of unsigned types and then
>>> to limit result to signed type of same size.
>>>
>>> Overflow of subtraction of signed types is undefined according
>>> to the C standard. The implementation causing exception is correct
>>> but seldom used (can be enabled for MIPS on GCC). But comparison
>>> is often optimized. So for example next code
>>
>> Conversion of too large unsigned integers to singed integers is also
>> undefined.  I assume two's complement arithmetic here.
>
> I do not remember such uncertainty from C99 standard reading.
> Should be checked.

I used the wrong term, it is not undefined, it is implementation-defined.  See 
6.3.1.3 Signed and unsigned integers, paragraph 3.

> What I am sure about is, that C standard
> defines behavior equivalent to 2'complement arithmetics
> for shifts and overflows for unsigned types and conversion
> from/to signed has take that into account somehow even if
> signed representation is not 2'complement. And we know that
> on all RTEMS target signed is 2'complement. So standard
> declares signed as unsigned as safe.

Yes.

>
>>> int fnc(int32_t x)
>>> {
>>>     if ((x + 0x7fffffff) < -0x10000000) {
>>>       return 1;
>>>     } else {
>>>       return 0;
>>>     }
>>> }
>>>
>>> can be legally optimized to
>>>
>>> int fnc(int32_t x)
>>> {
>>>     return 0;
>>> }
>>>
>>> because for any valid x number <-0x80000000;0x7fffffff>
>>> arithmetic value of the sum cannot be smaller than -1.
>>> And this kind of optimization is seen in reality.
>>>
>>> So even Sebastian's above code which tries to prevent
>>> overflow case can be misoptimized and broken.
>>>
>>> Correct is
>>>
>>>     return ( (int32_t) ( (uint32_t) ticks - (uint32_t)
>>> _Watchdog_Ticks_since_boot ) ) > 0;
>>
>> This version works also with two's complement arithmetic.  I don't think
>> the compiler can optimize my version in the same way as your example,
>> since _Watchdog_Ticks_since_boot is a global volatile variable.  Linux
>> uses the same approach for time_before().
>
> But your code subtact int32_t values and it is not safe even if it
> is volatile. I.e. if volatile value is read to register then it is
> processed as regular value for given occurrence in the expression.
> I.e. for comparison with constant (not so probable for time) it can behave
> exactly as I have described. Even worse if compared to non constant
> ((in32_t)start_time + 1000) because then compiler expect that this
> subexpression never overflows and it does not compare final substraction
> for carry but for signed less and equal.

The difference is that we have > 0 and not < -0x10000000, so this range 
deduction by the compiler doesn't work.  Anyway, I will use your version now 
since you have the better arguments:

RTEMS_INLINE_ROUTINE bool rtems_clock_tick_before(
   rtems_interval ticks
)
{
   return (int32_t) ( ticks - _Watchdog_Ticks_since_boot ) > 0;
}

[...]


-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber at embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.


More information about the devel mailing list