Skip to content
Permalink
Browse files

tests/kernel/sleep: Fix usleep test for fast ticks

The logic about minimal sleep sizes due to "tick" aliasing was
correct, but drivers also have similar behavior with "cycle" aliasing
too.  When cycles are 3-4 orders of magnitude faster than ticks, it's
undetectable noise.  But now on nRF they're exactly the same and we
need to correct for that, essentially doubling the number of ticks a
usleep() might wait for.

The logic here was simply too strict, basically.  Fast tick rates
can't guarantee what the test promised.

Note that this relaxes the test bounds on the other side of the
equation too: it's no longer an error to usleep() for only one tick
(i.e. an improved sleep/timeout implementation no longer gets detected
as a test failure).

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
  • Loading branch information...
andyross authored and nashif committed Jun 16, 2019
1 parent ed7d863 commit b1280108a219b44d284573cf85eb6b3a3f6f6900
Showing with 18 additions and 21 deletions.
  1. +18 −21 tests/kernel/sleep/src/usleep.c
@@ -16,17 +16,23 @@
#define RETRIES 10

/*
* Theory of operation: we can't use absolute units (e.g., "sleep for 10us")
* in testing k_usleep() because the granularity of sleeps is highly dependent
* on the hardware's capabilities and kernel configuration. Instead, we
* test that k_usleep() actually sleeps for the minimum possible duration.
* (That minimum duration is presently two ticks; see below.) So, we loop
* k_usleep()ing for as many iterations as should comprise a second, and
* check to see that a total of one second has elapsed.
* Theory of operation: we can't use absolute units (e.g., "sleep for
* 10us") in testing k_usleep() because the granularity of sleeps is
* highly dependent on the hardware's capabilities and kernel
* configuration. Instead, we test that k_usleep() actually sleeps for
* the minimum possible duration. So, we loop k_usleep()ing for as
* many iterations as should comprise a second, and check to see that
* a total of one second has elapsed.
*/

#define LOWER_BOUND_MS 900 /* +/- 10%, might be too lax */
#define UPPER_BOUND_MS 1100
#define LOOPS (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 2)

/* It should never iterate faster than the tick rate. It might be as
* much as 4x slower on drivers with fast tick rates (each of the app,
* sleep, timeout and cycle layers may need to align).
*/
#define LOWER_BOUND_MS ((1000 * LOOPS) / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
#define UPPER_BOUND_MS ((4 * 1000 * LOOPS) / CONFIG_SYS_CLOCK_TICKS_PER_SEC)

void test_usleep(void)
{
@@ -41,16 +47,7 @@ void test_usleep(void)
++retries;
start_ms = k_uptime_get();

for (i = 0; i < (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 2); ++i) {
/*
* this will always sleep for TWO ticks:
*
* the conversion from 1us to ticks is rounded
* up to the nearest tick boundary, and sleeps
* always have _TICK_ALIGN (currently 1) added
* to their durations.
*/

for (i = 0; i < LOOPS; ++i) {
k_usleep(1);
}

@@ -60,12 +57,12 @@ void test_usleep(void)
/* if at first you don't succeed, keep sucking. */

if ((elapsed_ms >= LOWER_BOUND_MS) &&
(elapsed_ms < UPPER_BOUND_MS)) {
(elapsed_ms <= UPPER_BOUND_MS)) {
break;
}
}

printk("elapsed_ms = %lld\n", elapsed_ms);
zassert_true(elapsed_ms >= LOWER_BOUND_MS, "short sleep");
zassert_true(elapsed_ms < UPPER_BOUND_MS, "overslept");
zassert_true(elapsed_ms <= UPPER_BOUND_MS, "overslept");
}

0 comments on commit b128010

Please sign in to comment.
You can’t perform that action at this time.