Re: [ANNOUNCE] ktimers subsystem

Roman Zippel
2005-09-24T23:45:31Z

Hi,

On Sat, 24 Sep 2005, Thomas Gleixner wrote:

> #define timespec_gt(a,b) \
> (((a).tv_sec > (b).tv_sec) ? 1 : \
> (((a).tv_sec < (b).tv_sec) ? 0 : \
> ((a).tv_nsec > (b).tv_nsec)))
>
> #define timespec_addptr(a,b) \
> (a)->tv_sec = ((a)->tv_sec + (b)->tv_sec); \
> (a)->tv_nsec = ((a)->tv_nsec + (b)->tv_nsec); \
> if ((a)->tv_nsec >= NSEC_PER_SEC){ \
> (a)->tv_nsec -= NSEC_PER_SEC; \
> (a)->tv_sec++; \
> }
>
> #define timespec_addppp(c,a,b) \
> (c)->tv_sec = ((a)->tv_sec + (b)->tv_sec); \
> (c)->tv_nsec = ((a)->tv_nsec + (b)->tv_nsec); \
> if ((c)->tv_nsec >= NSEC_PER_SEC){ \
> (c)->tv_nsec -= NSEC_PER_SEC; \
> (c)->tv_sec++; \
> }

Alternative for ktimespec:

#define timespec_gt(a,b) ((a).tv64 > (b).tv64)

#if BITS_PER_LONG == 64
#define timespec_addptr(a,b) \
(a).tv64 += (b).tv64; \
if ((a).tv.nsec >= NSEC_PER_SEC) { \
(a).tv64 += (u32)-NSEC_PER_SEC; \
}

#define timespec_addppp(c,a,b) \
(c).tv64 = (a).tv64 + (b).tv64; \
if ((c).tv.nsec >= NSEC_PER_SEC) { \
(c).tv64 += (u32)-NSEC_PER_SEC; \
}
#else
#define timespec_addptr(a,b) \
(a).tv.sec = ((a).tv.sec + (b).tv.sec); \
(a).tv.nsec = ((a).tv.nsec + (b).tv.nsec); \
if ((a).tv.nsec >= NSEC_PER_SEC) { \
(a).tv.nsec -= NSEC_PER_SEC; \
(a).tv.sec++; \
}

#define timespec_addppp(c,a,b) \
(c).tv.sec = ((a).tv.sec + (b).tv.sec); \
(c).tv.nsec = ((a).tv.nsec + (b).tv.nsec); \
if ((c).tv.nsec >= NSEC_PER_SEC) { \
(c).tv.nsec -= NSEC_PER_SEC; \
(c).tv.sec++; \
}
#endif

Adding the necessary conversion to the makes the difference even smaller.

> The only point, where (k)timespec has an advantage is that the userspace
> value must not be converted to nsec_t, but deducing therefor this is the
> better overall solution is a fallacy.

That's your opinion...

> nsec_t ktimespec
>
> syscall:
> 32x32 mul
> 64bit add 2 x 32bit move
>
> arm timer:
> 64 bit add 2 x 32 bit add
> 32 bit compare
> 32 bit sub
> 32 bit add
>
> The 3 operation compensate for the 32x32
> multiplication.

The multiply is not necessarly cheap, if the arch has no 32x32->64
instruction, gcc will generate a call to __muldi3().
Overall for the common case both variations don't differ much in speed
and size (for a single code path). For a few timers it likely doesn't
matter and for a lot of timers the tree insert likely dominates.

> The backward conversion from nsec_t to timespec is almost a non issue.
> The vast majority of callers dont provide the second argument to
> nanosleep(), setitimer(), set_timer() which makes the conversion
> necessary and I think we optimize for the common use case.

You know very well, that the conversion back to timespec is the killer in
your calculation. You graciously decide that the "vast majority" doesn't
want to read the timer, how did you get to that conclusion?

> Besides that the representation of time in nsec_t values is much
> clearer.

Well, that depends on the bigger picture, mainly how the timesource
manages the time. We want to optimize them for a fast get(ns)timeofday, so
we have already timespec based interfaces. Tick based sources will keep a
cached xtime timespec, so they either have to convert that to ns or
maintain another cached value just for your ktimers.
As long as you can't get rid of timespec completely (which is impossible),
there is a value in keeping it as much as possible as timespec.

bye, Roman