Skip to content

Commit 34e70e7

Browse files
Fix-Pointxiaoxiang781216
authored andcommitted
testing/ostest: Fix timing assertions in wdog_test
This patch removed timing assertions in wdog_test. Signed-off-by: ouyangxiangzhen <[email protected]>
1 parent 3d6785b commit 34e70e7

File tree

1 file changed

+109
-39
lines changed

1 file changed

+109
-39
lines changed

testing/ostest/wdog.c

+109-39
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,23 @@
2626
#include <nuttx/arch.h>
2727
#include <nuttx/wdog.h>
2828

29+
#include <assert.h>
2930
#include <pthread.h>
3031
#include <stdio.h>
31-
#include <assert.h>
32+
#include <syslog.h>
3233
#include <unistd.h>
3334

3435
/****************************************************************************
3536
* Pre-processor Definitions
3637
****************************************************************************/
3738

3839
#define WDOGTEST_RAND_ITER 1024
39-
#define WDOGTEST_THREAD_NR 8
40-
#define WDOGTEST_TOLERENT_LATENCY_US 5000
40+
#define WDOGTEST_THREAD_NR (CONFIG_SMP_NCPUS * 4)
41+
#define WDOGTEST_TOLERENT_TICK 10
4142

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

44-
#define wdtest_printf(...) printf(__VA_ARGS__)
45+
#define wdtest_printf(...) syslog(LOG_WARNING, __VA_ARGS__)
4546

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

@@ -64,63 +65,131 @@ typedef struct wdtest_param_s
6465
#ifdef CONFIG_BUILD_FLAT
6566
static void wdtest_callback(wdparm_t param)
6667
{
67-
struct timespec tp;
6868
FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param;
6969

70-
clock_gettime(CLOCK_MONOTONIC, &tp);
70+
/* Increment the callback count */
7171

7272
wdtest_param->callback_cnt += 1;
73-
wdtest_param->triggered_tick = clock_time2ticks(&tp);
73+
74+
/* Record the system tick at which the callback was triggered */
75+
76+
wdtest_param->triggered_tick = clock_systime_ticks();
77+
}
78+
79+
static void wdtest_checkdelay(sclock_t diff, sclock_t delay_tick)
80+
{
81+
/* Ensure the watchdog trigger time is not earlier than expected. */
82+
83+
wdtest_assert(diff - delay_tick >= 0);
84+
85+
/* If the timer latency exceeds the tolerance, print a warning. */
86+
87+
if (diff - delay_tick > WDOGTEST_TOLERENT_TICK)
88+
{
89+
wdtest_printf("WARNING: wdog latency ticks %lld "
90+
"(> %u may indicate timing error)\n",
91+
(long long)diff - delay_tick,
92+
WDOGTEST_TOLERENT_TICK);
93+
}
7494
}
7595

7696
static void wdtest_once(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,
7797
sclock_t delay_ns)
7898
{
79-
uint64_t cnt;
80-
long long diff;
81-
clock_t wdset_tick;
82-
struct timespec tp;
83-
clock_t delay_ticks = (clock_t)NSEC2TICK((clock_t)delay_ns);
99+
uint64_t cnt;
100+
sclock_t diff;
101+
clock_t wdset_tick;
102+
irqstate_t flags;
103+
sclock_t delay_tick = (sclock_t)NSEC2TICK((clock_t)delay_ns);
84104

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

87-
clock_gettime(CLOCK_MONOTONIC, &tp);
107+
/* Save the current callback count. */
88108

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

92-
wdtest_assert(wd_start(wdog, delay_ticks, wdtest_callback,
111+
/* Enter a critical section to prevent interruptions. */
112+
113+
flags = enter_critical_section();
114+
115+
/* Record the current system tick before setting the watchdog. */
116+
117+
wdset_tick = clock_systime_ticks();
118+
119+
wdtest_assert(wd_start(wdog, delay_tick, wdtest_callback,
93120
(wdparm_t)param) == OK);
94121

95-
wdtest_delay(delay_ns);
122+
leave_critical_section(flags);
96123

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

99-
wdtest_assert(cnt + 1 == param->callback_cnt);
126+
while (cnt + 1 != param->callback_cnt)
127+
{
128+
wdtest_delay(delay_ns);
129+
}
130+
131+
/* Check if the delay is within the acceptable tolerance. */
100132

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

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

107138
static void wdtest_rand(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,
108139
sclock_t rand_ns)
109140
{
110-
int idx;
111-
sclock_t delay_ns;
141+
uint64_t cnt;
142+
int idx;
143+
sclock_t delay_ns;
144+
clock_t wdset_tick;
145+
sclock_t delay_tick;
146+
sclock_t diff;
147+
irqstate_t flags;
148+
149+
/* Perform multiple iterations with random delays. */
112150

113151
for (idx = 0; idx < WDOGTEST_RAND_ITER; idx++)
114152
{
153+
cnt = param->callback_cnt;
154+
155+
/* Generate a random delay within the specified range. */
156+
115157
delay_ns = rand() % rand_ns;
116-
wdtest_assert(wd_start(wdog, NSEC2TICK(delay_ns), wdtest_callback,
158+
delay_tick = NSEC2TICK(delay_ns);
159+
160+
/* Enter critical section if the callback count is odd. */
161+
162+
if (cnt % 2)
163+
{
164+
flags = enter_critical_section();
165+
}
166+
167+
wdset_tick = clock_systime_ticks();
168+
wdtest_assert(wd_start(wdog, delay_tick, wdtest_callback,
117169
(wdparm_t)param) == 0);
170+
if (cnt % 2)
171+
{
172+
leave_critical_section(flags);
173+
}
118174

119-
/* Wait or Cancel 50/50 */
175+
/* Decide to wait for the callback or cancel the watchdog. */
120176

121177
if (delay_ns % 2)
122178
{
123-
wdtest_delay(delay_ns);
179+
/* Wait for the callback. */
180+
181+
while (cnt + 1 != param->callback_cnt)
182+
{
183+
wdtest_delay(delay_ns);
184+
}
185+
186+
/* Check the delay if the callback count is odd. */
187+
188+
if (cnt % 2)
189+
{
190+
diff = (sclock_t)(param->triggered_tick - wdset_tick);
191+
wdtest_checkdelay(diff, delay_tick);
192+
}
124193
}
125194
else
126195
{
@@ -131,14 +200,11 @@ static void wdtest_rand(FAR struct wdog_s *wdog, FAR wdtest_param_t *param,
131200

132201
static void wdtest_callback_recursive(wdparm_t param)
133202
{
134-
struct timespec tp;
135203
FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param;
136204
sclock_t interval = wdtest_param->interval;
137205

138-
clock_gettime(CLOCK_MONOTONIC, &tp);
139-
140206
wdtest_param->callback_cnt += 1;
141-
wdtest_param->triggered_tick = clock_time2ticks(&tp);
207+
wdtest_param->triggered_tick = clock_systime_ticks();
142208

143209
wd_start(wdtest_param->wdog, interval,
144210
wdtest_callback_recursive, param);
@@ -149,24 +215,29 @@ static void wdtest_recursive(FAR struct wdog_s *wdog,
149215
sclock_t delay_ns,
150216
unsigned int times)
151217
{
152-
uint64_t cnt;
153-
struct timespec tp;
154-
clock_t wdset_tick;
218+
uint64_t cnt;
219+
clock_t wdset_tick;
220+
irqstate_t flags;
155221

156222
wdtest_printf("wdtest_recursive %lldus\n", (long long)delay_ns);
223+
157224
cnt = param->callback_cnt;
225+
158226
param->wdog = wdog;
159227
param->interval = (sclock_t)NSEC2TICK((clock_t)delay_ns);
160228

161229
wdtest_assert(param->interval >= 0);
162230

163-
clock_gettime(CLOCK_MONOTONIC, &tp);
164-
wdset_tick = clock_time2ticks(&tp);
231+
flags = enter_critical_section();
232+
233+
wdset_tick = clock_systime_ticks();
165234

166235
wdtest_assert(wd_start(param->wdog, param->interval,
167236
wdtest_callback_recursive,
168237
(wdparm_t)param) == OK);
169238

239+
leave_critical_section(flags);
240+
170241
wdtest_delay(times * delay_ns);
171242

172243
wdtest_assert(wd_cancel(param->wdog) == 0);
@@ -208,7 +279,6 @@ static void wdog_test_run(FAR wdtest_param_t *param)
208279
wdtest_once(&test_wdog, param, 100);
209280
wdtest_once(&test_wdog, param, 1000);
210281
wdtest_once(&test_wdog, param, 10000);
211-
wdtest_delay(10);
212282

213283
/* Delay > 0, middle 100us */
214284

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

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

245-
wdtest_printf("wd_start with maximum delay, cancel %lld\n",
246-
(long long)rest);
247-
248315
wdtest_assert(wd_cancel(&test_wdog) == 0);
249316

317+
wdtest_printf("wd_start with maximum delay, cancel OK, rest %lld\n",
318+
(long long)rest);
319+
250320
/* Delay wraparound (delay < 0) */
251321

252322
delay = (sclock_t)((clock_t)delay + 1);

0 commit comments

Comments
 (0)