Skip to content

Commit

Permalink
testing/ostest: Fix timing assertions in wdog_test
Browse files Browse the repository at this point in the history
This patch removed timing assertions in wdog_test.

Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
  • Loading branch information
Fix-Point authored and xiaoxiang781216 committed Oct 1, 2024
1 parent 3d6785b commit 34e70e7
Showing 1 changed file with 109 additions and 39 deletions.
148 changes: 109 additions & 39 deletions testing/ostest/wdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@
#include <nuttx/arch.h>
#include <nuttx/wdog.h>

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <assert.h>
#include <syslog.h>
#include <unistd.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define WDOGTEST_RAND_ITER 1024
#define WDOGTEST_THREAD_NR 8
#define WDOGTEST_TOLERENT_LATENCY_US 5000
#define WDOGTEST_THREAD_NR (CONFIG_SMP_NCPUS * 4)
#define WDOGTEST_TOLERENT_TICK 10

#define wdtest_assert(x) _ASSERT(x, __FILE__, __LINE__)

#define wdtest_printf(...) printf(__VA_ARGS__)
#define wdtest_printf(...) syslog(LOG_WARNING, __VA_ARGS__)

#define wdtest_delay(delay_ns) usleep(delay_ns / 1000 + 1)

Expand All @@ -64,63 +65,131 @@ typedef struct wdtest_param_s
#ifdef CONFIG_BUILD_FLAT
static void wdtest_callback(wdparm_t param)
{
struct timespec tp;
FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param;

clock_gettime(CLOCK_MONOTONIC, &tp);
/* Increment the callback count */

wdtest_param->callback_cnt += 1;
wdtest_param->triggered_tick = clock_time2ticks(&tp);

/* Record the system tick at which the callback was triggered */

wdtest_param->triggered_tick = clock_systime_ticks();
}

static void wdtest_checkdelay(sclock_t diff, sclock_t delay_tick)
{
/* Ensure the watchdog trigger time is not earlier than expected. */

wdtest_assert(diff - delay_tick >= 0);

/* If the timer latency exceeds the tolerance, print a warning. */

if (diff - delay_tick > WDOGTEST_TOLERENT_TICK)
{
wdtest_printf("WARNING: wdog latency ticks %lld "
"(> %u may indicate timing error)\n",
(long long)diff - delay_tick,
WDOGTEST_TOLERENT_TICK);
}
}

static void wdtest_once(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,
sclock_t delay_ns)
{
uint64_t cnt;
long long diff;
clock_t wdset_tick;
struct timespec tp;
clock_t delay_ticks = (clock_t)NSEC2TICK((clock_t)delay_ns);
uint64_t cnt;
sclock_t diff;
clock_t wdset_tick;
irqstate_t flags;
sclock_t delay_tick = (sclock_t)NSEC2TICK((clock_t)delay_ns);

wdtest_printf("wdtest_once %lld ns\n", (long long)delay_ns);

clock_gettime(CLOCK_MONOTONIC, &tp);
/* Save the current callback count. */

wdset_tick = clock_time2ticks(&tp);
cnt = param->callback_cnt;

wdtest_assert(wd_start(wdog, delay_ticks, wdtest_callback,
/* Enter a critical section to prevent interruptions. */

flags = enter_critical_section();

/* Record the current system tick before setting the watchdog. */

wdset_tick = clock_systime_ticks();

wdtest_assert(wd_start(wdog, delay_tick, wdtest_callback,
(wdparm_t)param) == OK);

wdtest_delay(delay_ns);
leave_critical_section(flags);

diff = (long long)(param->triggered_tick - wdset_tick);
/* Wait until the callback is triggered exactly once. */

wdtest_assert(cnt + 1 == param->callback_cnt);
while (cnt + 1 != param->callback_cnt)
{
wdtest_delay(delay_ns);
}

/* Check if the delay is within the acceptable tolerance. */

/* Ensure diff - delay_ticks >= 0. */
diff = (sclock_t)(param->triggered_tick - wdset_tick);

wdtest_assert(diff - (long long)delay_ticks >= 0);
wdtest_printf("wdtest_once latency ticks %lld\n", diff - delay_ticks);
wdtest_checkdelay(diff, delay_tick);
}

static void wdtest_rand(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,
sclock_t rand_ns)
{
int idx;
sclock_t delay_ns;
uint64_t cnt;
int idx;
sclock_t delay_ns;
clock_t wdset_tick;
sclock_t delay_tick;
sclock_t diff;
irqstate_t flags;

/* Perform multiple iterations with random delays. */

for (idx = 0; idx < WDOGTEST_RAND_ITER; idx++)
{
cnt = param->callback_cnt;

/* Generate a random delay within the specified range. */

delay_ns = rand() % rand_ns;
wdtest_assert(wd_start(wdog, NSEC2TICK(delay_ns), wdtest_callback,
delay_tick = NSEC2TICK(delay_ns);

/* Enter critical section if the callback count is odd. */

if (cnt % 2)
{
flags = enter_critical_section();
}

wdset_tick = clock_systime_ticks();
wdtest_assert(wd_start(wdog, delay_tick, wdtest_callback,
(wdparm_t)param) == 0);
if (cnt % 2)
{
leave_critical_section(flags);
}

/* Wait or Cancel 50/50 */
/* Decide to wait for the callback or cancel the watchdog. */

if (delay_ns % 2)
{
wdtest_delay(delay_ns);
/* Wait for the callback. */

while (cnt + 1 != param->callback_cnt)
{
wdtest_delay(delay_ns);
}

/* Check the delay if the callback count is odd. */

if (cnt % 2)
{
diff = (sclock_t)(param->triggered_tick - wdset_tick);
wdtest_checkdelay(diff, delay_tick);
}
}
else
{
Expand All @@ -131,14 +200,11 @@ static void wdtest_rand(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,

static void wdtest_callback_recursive(wdparm_t param)
{
struct timespec tp;
FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param;
sclock_t interval = wdtest_param->interval;

clock_gettime(CLOCK_MONOTONIC, &tp);

wdtest_param->callback_cnt += 1;
wdtest_param->triggered_tick = clock_time2ticks(&tp);
wdtest_param->triggered_tick = clock_systime_ticks();

wd_start(wdtest_param->wdog, interval,
wdtest_callback_recursive, param);
Expand All @@ -149,24 +215,29 @@ static void wdtest_recursive(FAR struct wdog_s *wdog,
sclock_t delay_ns,
unsigned int times)
{
uint64_t cnt;
struct timespec tp;
clock_t wdset_tick;
uint64_t cnt;
clock_t wdset_tick;
irqstate_t flags;

wdtest_printf("wdtest_recursive %lldus\n", (long long)delay_ns);

cnt = param->callback_cnt;

param->wdog = wdog;
param->interval = (sclock_t)NSEC2TICK((clock_t)delay_ns);

wdtest_assert(param->interval >= 0);

clock_gettime(CLOCK_MONOTONIC, &tp);
wdset_tick = clock_time2ticks(&tp);
flags = enter_critical_section();

wdset_tick = clock_systime_ticks();

wdtest_assert(wd_start(param->wdog, param->interval,
wdtest_callback_recursive,
(wdparm_t)param) == OK);

leave_critical_section(flags);

wdtest_delay(times * delay_ns);

wdtest_assert(wd_cancel(param->wdog) == 0);
Expand Down Expand Up @@ -208,7 +279,6 @@ static void wdog_test_run(FAR wdtest_param_t *param)
wdtest_once(&test_wdog, param, 100);
wdtest_once(&test_wdog, param, 1000);
wdtest_once(&test_wdog, param, 10000);
wdtest_delay(10);

/* Delay > 0, middle 100us */

Expand Down Expand Up @@ -242,11 +312,11 @@ static void wdog_test_run(FAR wdtest_param_t *param)

wdtest_assert(rest < delay && rest > (delay >> 1));

wdtest_printf("wd_start with maximum delay, cancel %lld\n",
(long long)rest);

wdtest_assert(wd_cancel(&test_wdog) == 0);

wdtest_printf("wd_start with maximum delay, cancel OK, rest %lld\n",
(long long)rest);

/* Delay wraparound (delay < 0) */

delay = (sclock_t)((clock_t)delay + 1);
Expand Down

0 comments on commit 34e70e7

Please sign in to comment.