us_delay() improvement
Jonathan Larmour
jifl@eCosCentric.com
Mon Jun 23 23:23:00 GMT 2003
Nick Garnett wrote:
> + if( usecs > usec_per_period/2 )
> + slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
> + else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
> + slice = usecs * ticks_per_usec;
> + else
> + {
> + slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
> + slice /= usec_per_period;
> + }
I've been thinking about this.... we get overflow if
usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD overflows, which means that since
usecs should be at most usec_per_period/2, we have to "play safe" if
plugging usecs == usec_per_period/2 in to the multiplication would
overflow, because that's the worst case.
So we get the expression to test as:
(usec_per_period/2)*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF
which we reorganise to prevent overflow of this expression to become:
CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period
which should be sufficient. The code as written will unnecessarily catch
certain configurations I'd think.
> + // Adjust by elapsed, not slice, since an interrupt may
> + // have been stalling us for some time.
> +
> + if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
> + elapsed_usec = elapsed / ticks_per_usec;
> + else
> + {
> + elapsed_usec = elapsed * usec_per_period;
> + elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
> + }
FAOD the above wouldn't have the same issue because of the additional
complication that elapsed may be greater than slice, so the risk of
overflow is even higher, but by an indeterminate amount to make things
more fun ;-). A factor of two fudge seems as good/bad as any other amount
then.
Jifl
--
eCosCentric http://www.eCosCentric.com/ The eCos and RedBoot experts
--[ "You can complain because roses have thorns, or you ]--
--[ can rejoice because thorns have roses." -Lincoln ]-- Opinions==mine
More information about the Ecos-patches
mailing list