[PATCH weston 1/7] timespec: Add timespec_add_nsec helper

Pekka Paalanen ppaalanen at gmail.com
Tue Feb 14 15:02:02 UTC 2017


On Tue, 14 Feb 2017 14:21:17 +0000
Daniel Stone <daniel at fooishbar.org> wrote:

> Hi,
> 
> On 14 February 2017 at 14:09, Pekka Paalanen <ppaalanen at gmail.com> wrote:
> > On Tue, 14 Feb 2017 13:18:01 +0000
> > Daniel Stone <daniels at collabora.com> wrote:  
> >> Add a (timespec) = (timespec) + (nsec) helper, to save intermediate
> >> conversions to nanoseconds in its users.  

> >> +/* Add a nanosecond value to a timespec
> >> + *
> >> + * \param r[out] result: a + b
> >> + * \param a[in] base operand as timespec
> >> + * \param b[in] operand in nanoseconds
> >> + */
> >> +static inline void
> >> +timespec_add_nsec(struct timespec *r, const struct timespec *a, int64_t b)
> >> +{
> >> +     r->tv_sec = a->tv_sec + (b / NSEC_PER_SEC);
> >> +     r->tv_nsec = a->tv_nsec + (b % NSEC_PER_SEC);
> >> +
> >> +     if (r->tv_nsec >= NSEC_PER_SEC) {
> >> +             r->tv_sec++;
> >> +             r->tv_nsec -= NSEC_PER_SEC;
> >> +     } else if (r->tv_nsec <= -NSEC_PER_SEC) {  
> >
> > IIRC tv_nsec cannot be negative, so it should be:
> >         r->tv_nsec < 0  
> 
> This is working on r->tv_nsec, i.e. (a->tv_nsec + signed input value).
> I did this to deliberately allow timespec_add_nsec(&r, &a, -12345).

Indeed r->tv_nsec, and you need to guarantee to not return a timespec
with an invalid tv_nsec. It has no relation to allowing negative b
which is fine.

> > I recall writing asserts for tv_nsec, but maybe it wasn't weston where
> > I did that.
> >
> > I realize mandating 0 <= nsec < NSEC_PER_SEC to be somewhat arbitrary,
> > but timespec_sub() already assumes that and it is what
> > presentation-time protocol requires.
> >
> > In wesgr where I needed the notion of invalid timestamps, I abused the
> > value tv_nsec = -1 for it.  
> 
> That's all perfectly reasonable. I thought about adding some
> assertions that timespec was in fact normalised, but decided I'd
> already wandered far enough off topic tbh.

Yup, totally fine.

> >> +     a.tv_sec = 0;
> >> +     a.tv_nsec = 1;
> >> +     timespec_add_nsec(&r, &a, -2);
> >> +     ZUC_ASSERT_EQ(r.tv_sec, 0);
> >> +     ZUC_ASSERT_EQ(r.tv_nsec, -1);  
> >
> > Incorrect, tv_nsec cannot be negative.  
> 
> So this would have to be { .tv_sec = -1, .tv_nsec = NSEC_PER_SEC - 1
> }? I was somewhat confused as to the relationship of the two.

Yes, nsec is always [0, 999999999] in normalized form.

I was also confused about how to interpret a timespec when I started
using it, but in the end, it is just tv_sec + tv_nsec / 1e9. I think
comparison functions might become annoying if tv_nsec was allowed to be
negative. Sticking to the normalized form makes things easier, IMO. At
least it pays off to stick to just one normalized form (see
presentation-time). :-)

The real confusion comes if one tries to think of it as integer
concatenated with fractional part ("%d.%09d"). It works if tv_sec and
tv_nsec are both positive (and normalized), but fails immediately when
either becomes negative.


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20170214/1c7cec01/attachment.sig>


More information about the wayland-devel mailing list