On Wed, 2021-03-31 at 11:26 +0800, chensong wrote:
> add test case for clock_nanosleep64 in testsuite
> 
> Signed-off-by: chensong <[email protected]>
> ---
>  testsuite/smokey/y2038/syscall-tests.c | 65 
> ++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
> 
> diff --git a/testsuite/smokey/y2038/syscall-tests.c 
> b/testsuite/smokey/y2038/syscall-tests.c
> index 03a3198..affbb2d 100644
> --- a/testsuite/smokey/y2038/syscall-tests.c
> +++ b/testsuite/smokey/y2038/syscall-tests.c
> @@ -226,6 +226,67 @@ static int test_sc_cobalt_clock_settime64(void)
>       return 0;
>  }
>  
> 

> +static inline int64_t calcdiff(struct timespec t1, struct xn_timespec64 t2)
> 
> +{
> +     struct timespec r;
> +
> +     r.tv_sec = t1.tv_sec - t2.tv_sec;
> +     r.tv_nsec = t1.tv_nsec - t2.tv_nsec;

When looking at the function signature I would assume t2 is the bigger
or later one. But it's flipped. But maybe this function is getting
obsolete, see below.

> +     if (r.tv_nsec < 0) {
> +             r.tv_sec--;
> +             r.tv_nsec += NSEC_PER_SEC;
> +     }
> +
> +     return (r.tv_sec * NSEC_PER_SEC + r.tv_nsec) / 1000;
> +}
> +
> +static int test_sc_cobalt_clock_nanosleep64(void)
> +{
> +     long ret;
> +     int code = __xn_syscode(sc_cobalt_clock_nanosleep64);
> +     struct xn_timespec64 next;
> +     struct timespec now;
> +     int64_t diff;
> +     int64_t threshold = 500;
> +
> +     /* Make sure we don't crash because of NULL pointers */
> +     ret = syscall(code, NULL, NULL, NULL);
> +     if (ret == -1 && errno == ENOSYS) {
> +             smokey_note("clock_nanosleep64: skipped. (no kernel support)");
> +             return 0; // Not implemented, nothing to test, success
> +     }
> +     if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
> +             return errno;
> +
> +     /* Providing an invalid address has to deliver EFAULT */
> +     ret = syscall(code, CLOCK_MONOTONIC, (void *)0xdeadbeefUL,
> +                             (void *)0xdeadbeefUL);
> +     if (!smokey_assert(ret == -1) || !smokey_assert(errno == EFAULT))
> +             return errno;

To be complete we should cover all possibilities here. We already cover
that both pointers are invalid, but there might be one invalid and a
valid one in all combinations.

> +
> +     /* Provide an valid 64bit timespec*/

Minor: "a valid" instead of "an valid"

> +     ret = clock_gettime(CLOCK_REALTIME, &now);
> +     if (ret)
> +             return errno;

When leaving the function here we should add a warning that we failed
because clock_gettime did not work. Otherwise we might end up searching
for the root cause in the nanosleep stuff.

There is a second clock_gettime() error path below. Both should be
handled the same way.

> +
> +     next.tv_sec  = now.tv_sec + 1;
> +     next.tv_nsec = now.tv_nsec;
> +
> +     ret = syscall(code, CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
> +     if (!smokey_assert(!ret))
> +             return errno;
> +
> +     ret = clock_gettime(CLOCK_REALTIME, &now);
> +     if (ret)
> +             return errno;
> +
> +     diff = calcdiff(now, next);
> +     if (diff > threshold)
> +             smokey_warning("clock_nanosleep64, latency is %dus\n");
> +

I'm not a fan of magic numbers (threshold = 500). Those numbers might
be OK on some systems / architectures / chips but might be wrong for
others.

For the semaphore test I just made sure that we don't come back to
early. Maybe someone has a better idea?

As CLOCK_REALTIME could jump back and forward we should switch to
CLOCK_MONOTONIC for all such tests (as well as for the clock_gettime()
part)

> +     return 0;
> +}
> +
>  static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
>  {
>       int ret;
> @@ -242,5 +303,9 @@ static int run_y2038(struct smokey_test *t, int argc, 
> char *const argv[])
>       if (ret)
>               return ret;
> 
> +     ret = test_sc_cobalt_clock_nanosleep64();
> +     if (ret)
> +             return ret;
> +
>       return 0;
>  }

Reply via email to