]>
Commit | Line | Data |
---|---|---|
5b262bb6 DO |
1 | /* |
2 | * QTest testcase for the ptimer | |
3 | * | |
673c7e89 | 4 | * Copyright (c) 2016 Dmitry Osipenko <[email protected]> |
5b262bb6 DO |
5 | * |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
7 | * See the COPYING file in the top-level directory. | |
8 | * | |
9 | */ | |
10 | ||
11 | #include <glib/gprintf.h> | |
12 | ||
13 | #include "qemu/osdep.h" | |
14 | #include "qemu/main-loop.h" | |
15 | #include "hw/ptimer.h" | |
16 | ||
17 | #include "libqtest.h" | |
18 | #include "ptimer-test.h" | |
19 | ||
20 | static bool triggered; | |
21 | ||
22 | static void ptimer_trigger(void *opaque) | |
23 | { | |
24 | triggered = true; | |
25 | } | |
26 | ||
27 | static void ptimer_test_expire_qemu_timers(int64_t expire_time, | |
28 | QEMUClockType type) | |
29 | { | |
30 | QEMUTimerList *timer_list = main_loop_tlg.tl[type]; | |
31 | QEMUTimer *t = timer_list->active_timers.next; | |
32 | ||
33 | while (t != NULL) { | |
34 | if (t->expire_time == expire_time) { | |
35 | timer_del(t); | |
36 | ||
37 | if (t->cb != NULL) { | |
38 | t->cb(t->opaque); | |
39 | } | |
40 | } | |
41 | ||
42 | t = t->next; | |
43 | } | |
44 | } | |
45 | ||
46 | static void ptimer_test_set_qemu_time_ns(int64_t ns) | |
47 | { | |
48 | ptimer_test_time_ns = ns; | |
49 | } | |
50 | ||
51 | static void qemu_clock_step(uint64_t ns) | |
52 | { | |
53 | int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); | |
54 | int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns; | |
55 | ||
56 | while (deadline != -1 && deadline <= advanced_time) { | |
57 | ptimer_test_set_qemu_time_ns(deadline); | |
58 | ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL); | |
59 | deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); | |
60 | } | |
61 | ||
62 | ptimer_test_set_qemu_time_ns(advanced_time); | |
63 | } | |
64 | ||
65 | static void check_set_count(gconstpointer arg) | |
66 | { | |
67 | const uint8_t *policy = arg; | |
68 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
69 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
70 | ||
71 | triggered = false; | |
72 | ||
73 | ptimer_set_count(ptimer, 1000); | |
74 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000); | |
75 | g_assert_false(triggered); | |
76 | } | |
77 | ||
78 | static void check_set_limit(gconstpointer arg) | |
79 | { | |
80 | const uint8_t *policy = arg; | |
81 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
82 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
83 | ||
84 | triggered = false; | |
85 | ||
86 | ptimer_set_limit(ptimer, 1000, 0); | |
87 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
88 | g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000); | |
89 | g_assert_false(triggered); | |
90 | ||
91 | ptimer_set_limit(ptimer, 2000, 1); | |
92 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000); | |
93 | g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000); | |
94 | g_assert_false(triggered); | |
95 | } | |
96 | ||
97 | static void check_oneshot(gconstpointer arg) | |
98 | { | |
99 | const uint8_t *policy = arg; | |
100 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
101 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
057516fe | 102 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
103 | |
104 | triggered = false; | |
105 | ||
106 | ptimer_set_period(ptimer, 2000000); | |
107 | ptimer_set_count(ptimer, 10); | |
108 | ptimer_run(ptimer, 1); | |
109 | ||
33d44cdf | 110 | qemu_clock_step(2000000 * 2 + 1); |
5b262bb6 | 111 | |
057516fe | 112 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); |
5b262bb6 DO |
113 | g_assert_false(triggered); |
114 | ||
115 | ptimer_stop(ptimer); | |
116 | ||
057516fe | 117 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); |
5b262bb6 DO |
118 | g_assert_false(triggered); |
119 | ||
120 | qemu_clock_step(2000000 * 11); | |
121 | ||
057516fe | 122 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); |
5b262bb6 DO |
123 | g_assert_false(triggered); |
124 | ||
125 | ptimer_run(ptimer, 1); | |
126 | ||
33d44cdf | 127 | qemu_clock_step(2000000 * 7 + 1); |
5b262bb6 | 128 | |
057516fe | 129 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); |
5b262bb6 | 130 | |
057516fe DO |
131 | if (no_round_down) { |
132 | g_assert_false(triggered); | |
133 | } else { | |
134 | g_assert_true(triggered); | |
135 | ||
136 | triggered = false; | |
137 | } | |
5b262bb6 DO |
138 | |
139 | qemu_clock_step(2000000); | |
140 | ||
141 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
057516fe DO |
142 | |
143 | if (no_round_down) { | |
144 | g_assert_true(triggered); | |
145 | ||
146 | triggered = false; | |
147 | } else { | |
148 | g_assert_false(triggered); | |
149 | } | |
5b262bb6 DO |
150 | |
151 | qemu_clock_step(4000000); | |
152 | ||
153 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
154 | g_assert_false(triggered); | |
155 | ||
156 | ptimer_set_count(ptimer, 10); | |
157 | ||
33d44cdf | 158 | qemu_clock_step(20000000 + 1); |
5b262bb6 DO |
159 | |
160 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10); | |
161 | g_assert_false(triggered); | |
162 | ||
163 | ptimer_set_limit(ptimer, 9, 1); | |
164 | ||
33d44cdf | 165 | qemu_clock_step(20000000 + 1); |
5b262bb6 DO |
166 | |
167 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9); | |
168 | g_assert_false(triggered); | |
169 | ||
170 | ptimer_run(ptimer, 1); | |
171 | ||
33d44cdf | 172 | qemu_clock_step(2000000 + 1); |
5b262bb6 | 173 | |
057516fe | 174 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); |
5b262bb6 DO |
175 | g_assert_false(triggered); |
176 | ||
177 | ptimer_set_count(ptimer, 20); | |
178 | ||
33d44cdf | 179 | qemu_clock_step(2000000 * 19 + 1); |
5b262bb6 | 180 | |
057516fe | 181 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); |
5b262bb6 DO |
182 | g_assert_false(triggered); |
183 | ||
184 | qemu_clock_step(2000000); | |
185 | ||
186 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
187 | g_assert_true(triggered); | |
188 | ||
189 | ptimer_stop(ptimer); | |
190 | ||
191 | triggered = false; | |
192 | ||
33d44cdf | 193 | qemu_clock_step(2000000 * 12 + 1); |
5b262bb6 DO |
194 | |
195 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
196 | g_assert_false(triggered); | |
197 | } | |
198 | ||
199 | static void check_periodic(gconstpointer arg) | |
200 | { | |
201 | const uint8_t *policy = arg; | |
202 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
203 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
293130aa | 204 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); |
516deb42 | 205 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); |
56700e1a | 206 | bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD); |
057516fe | 207 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
208 | |
209 | triggered = false; | |
210 | ||
211 | ptimer_set_period(ptimer, 2000000); | |
212 | ptimer_set_limit(ptimer, 10, 1); | |
213 | ptimer_run(ptimer, 0); | |
214 | ||
293130aa DO |
215 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10); |
216 | g_assert_false(triggered); | |
217 | ||
33d44cdf | 218 | qemu_clock_step(1); |
5b262bb6 | 219 | |
057516fe | 220 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9); |
293130aa DO |
221 | g_assert_false(triggered); |
222 | ||
33d44cdf | 223 | qemu_clock_step(2000000 * 10 - 1); |
293130aa DO |
224 | |
225 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, wrap_policy ? 0 : 10); | |
226 | g_assert_true(triggered); | |
227 | ||
33d44cdf | 228 | qemu_clock_step(1); |
293130aa | 229 | |
057516fe DO |
230 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
231 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
5b262bb6 DO |
232 | g_assert_true(triggered); |
233 | ||
234 | triggered = false; | |
235 | ||
236 | qemu_clock_step(2000000); | |
237 | ||
057516fe DO |
238 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
239 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
240 | g_assert_false(triggered); |
241 | ||
242 | ptimer_set_count(ptimer, 20); | |
243 | ||
293130aa DO |
244 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 20); |
245 | g_assert_false(triggered); | |
246 | ||
33d44cdf | 247 | qemu_clock_step(1); |
293130aa | 248 | |
057516fe | 249 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 20 : 19); |
293130aa DO |
250 | g_assert_false(triggered); |
251 | ||
33d44cdf | 252 | qemu_clock_step(2000000 * 11 + 1); |
5b262bb6 | 253 | |
057516fe | 254 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 9 : 8); |
5b262bb6 DO |
255 | g_assert_false(triggered); |
256 | ||
257 | qemu_clock_step(2000000 * 10); | |
258 | ||
057516fe DO |
259 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
260 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
293130aa DO |
261 | g_assert_true(triggered); |
262 | ||
263 | triggered = false; | |
264 | ||
265 | ptimer_set_count(ptimer, 3); | |
266 | ||
267 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3); | |
268 | g_assert_false(triggered); | |
269 | ||
33d44cdf | 270 | qemu_clock_step(1); |
293130aa | 271 | |
057516fe | 272 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 3 : 2); |
293130aa DO |
273 | g_assert_false(triggered); |
274 | ||
275 | qemu_clock_step(2000000 * 4); | |
276 | ||
057516fe DO |
277 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
278 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
279 | g_assert_true(triggered); |
280 | ||
281 | ptimer_stop(ptimer); | |
282 | triggered = false; | |
283 | ||
284 | qemu_clock_step(2000000); | |
285 | ||
057516fe DO |
286 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
287 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
288 | g_assert_false(triggered); |
289 | ||
290 | ptimer_set_count(ptimer, 3); | |
291 | ptimer_run(ptimer, 0); | |
292 | ||
33d44cdf | 293 | qemu_clock_step(2000000 * 3 + 1); |
5b262bb6 | 294 | |
057516fe DO |
295 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
296 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
5b262bb6 DO |
297 | g_assert_true(triggered); |
298 | ||
299 | triggered = false; | |
300 | ||
301 | qemu_clock_step(2000000); | |
302 | ||
057516fe DO |
303 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
304 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
305 | g_assert_false(triggered); |
306 | ||
307 | ptimer_set_count(ptimer, 0); | |
56700e1a DO |
308 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
309 | no_immediate_reload ? 0 : 10); | |
516deb42 DO |
310 | |
311 | if (no_immediate_trigger) { | |
312 | g_assert_false(triggered); | |
313 | } else { | |
314 | g_assert_true(triggered); | |
315 | } | |
5b262bb6 DO |
316 | |
317 | triggered = false; | |
318 | ||
33d44cdf | 319 | qemu_clock_step(1); |
5b262bb6 | 320 | |
56700e1a DO |
321 | if (no_immediate_reload) { |
322 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
323 | g_assert_false(triggered); | |
324 | ||
325 | qemu_clock_step(2000000); | |
326 | ||
327 | if (no_immediate_trigger) { | |
328 | g_assert_true(triggered); | |
329 | } else { | |
330 | g_assert_false(triggered); | |
331 | } | |
332 | ||
333 | triggered = false; | |
334 | } | |
335 | ||
057516fe | 336 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9); |
293130aa DO |
337 | g_assert_false(triggered); |
338 | ||
339 | qemu_clock_step(2000000 * 12); | |
340 | ||
057516fe DO |
341 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
342 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
343 | g_assert_true(triggered); |
344 | ||
345 | ptimer_stop(ptimer); | |
346 | ||
347 | triggered = false; | |
348 | ||
293130aa | 349 | qemu_clock_step(2000000 * 10); |
5b262bb6 | 350 | |
057516fe DO |
351 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
352 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
353 | g_assert_false(triggered); |
354 | ||
355 | ptimer_run(ptimer, 0); | |
356 | ptimer_set_period(ptimer, 0); | |
357 | ||
33d44cdf | 358 | qemu_clock_step(2000000 + 1); |
5b262bb6 | 359 | |
057516fe DO |
360 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
361 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
362 | g_assert_false(triggered); |
363 | } | |
364 | ||
365 | static void check_on_the_fly_mode_change(gconstpointer arg) | |
366 | { | |
367 | const uint8_t *policy = arg; | |
368 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
369 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
293130aa | 370 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); |
057516fe | 371 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
372 | |
373 | triggered = false; | |
374 | ||
375 | ptimer_set_period(ptimer, 2000000); | |
376 | ptimer_set_limit(ptimer, 10, 1); | |
377 | ptimer_run(ptimer, 1); | |
378 | ||
33d44cdf | 379 | qemu_clock_step(2000000 * 9 + 1); |
5b262bb6 | 380 | |
057516fe | 381 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); |
293130aa DO |
382 | g_assert_false(triggered); |
383 | ||
5b262bb6 DO |
384 | ptimer_run(ptimer, 0); |
385 | ||
057516fe | 386 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); |
5b262bb6 DO |
387 | g_assert_false(triggered); |
388 | ||
389 | qemu_clock_step(2000000); | |
390 | ||
057516fe DO |
391 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
392 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
5b262bb6 DO |
393 | g_assert_true(triggered); |
394 | ||
395 | triggered = false; | |
396 | ||
397 | qemu_clock_step(2000000 * 9); | |
398 | ||
399 | ptimer_run(ptimer, 1); | |
400 | ||
057516fe DO |
401 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
402 | (no_round_down ? 1 : 0) + (wrap_policy ? 1 : 0)); | |
5b262bb6 DO |
403 | g_assert_false(triggered); |
404 | ||
405 | qemu_clock_step(2000000 * 3); | |
406 | ||
407 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
408 | g_assert_true(triggered); | |
409 | } | |
410 | ||
411 | static void check_on_the_fly_period_change(gconstpointer arg) | |
412 | { | |
413 | const uint8_t *policy = arg; | |
414 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
415 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
057516fe | 416 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
417 | |
418 | triggered = false; | |
419 | ||
420 | ptimer_set_period(ptimer, 2000000); | |
421 | ptimer_set_limit(ptimer, 8, 1); | |
422 | ptimer_run(ptimer, 1); | |
423 | ||
33d44cdf | 424 | qemu_clock_step(2000000 * 4 + 1); |
5b262bb6 | 425 | |
057516fe | 426 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); |
5b262bb6 DO |
427 | g_assert_false(triggered); |
428 | ||
429 | ptimer_set_period(ptimer, 4000000); | |
057516fe | 430 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); |
5b262bb6 | 431 | |
33d44cdf | 432 | qemu_clock_step(4000000 * 2 + 1); |
5b262bb6 | 433 | |
057516fe | 434 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0); |
5b262bb6 DO |
435 | g_assert_false(triggered); |
436 | ||
437 | qemu_clock_step(4000000 * 2); | |
438 | ||
439 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
440 | g_assert_true(triggered); | |
441 | } | |
442 | ||
443 | static void check_on_the_fly_freq_change(gconstpointer arg) | |
444 | { | |
445 | const uint8_t *policy = arg; | |
446 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
447 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
057516fe | 448 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
449 | |
450 | triggered = false; | |
451 | ||
452 | ptimer_set_freq(ptimer, 500); | |
453 | ptimer_set_limit(ptimer, 8, 1); | |
454 | ptimer_run(ptimer, 1); | |
455 | ||
33d44cdf | 456 | qemu_clock_step(2000000 * 4 + 1); |
5b262bb6 | 457 | |
057516fe | 458 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); |
5b262bb6 DO |
459 | g_assert_false(triggered); |
460 | ||
461 | ptimer_set_freq(ptimer, 250); | |
057516fe | 462 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); |
5b262bb6 | 463 | |
33d44cdf | 464 | qemu_clock_step(2000000 * 4 + 1); |
5b262bb6 | 465 | |
057516fe | 466 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0); |
5b262bb6 DO |
467 | g_assert_false(triggered); |
468 | ||
469 | qemu_clock_step(2000000 * 4); | |
470 | ||
471 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
472 | g_assert_true(triggered); | |
473 | } | |
474 | ||
475 | static void check_run_with_period_0(gconstpointer arg) | |
476 | { | |
477 | const uint8_t *policy = arg; | |
478 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
479 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
480 | ||
481 | triggered = false; | |
482 | ||
483 | ptimer_set_count(ptimer, 99); | |
484 | ptimer_run(ptimer, 1); | |
485 | ||
486 | qemu_clock_step(10 * NANOSECONDS_PER_SECOND); | |
487 | ||
488 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99); | |
489 | g_assert_false(triggered); | |
490 | } | |
491 | ||
492 | static void check_run_with_delta_0(gconstpointer arg) | |
493 | { | |
494 | const uint8_t *policy = arg; | |
495 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
496 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
293130aa | 497 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); |
516deb42 | 498 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); |
56700e1a | 499 | bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD); |
057516fe | 500 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); |
5b262bb6 DO |
501 | |
502 | triggered = false; | |
503 | ||
504 | ptimer_set_period(ptimer, 2000000); | |
505 | ptimer_set_limit(ptimer, 99, 0); | |
506 | ptimer_run(ptimer, 1); | |
56700e1a DO |
507 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
508 | no_immediate_reload ? 0 : 99); | |
516deb42 DO |
509 | |
510 | if (no_immediate_trigger) { | |
511 | g_assert_false(triggered); | |
512 | } else { | |
513 | g_assert_true(triggered); | |
514 | } | |
5b262bb6 DO |
515 | |
516 | triggered = false; | |
517 | ||
56700e1a | 518 | if (no_immediate_trigger || no_immediate_reload) { |
33d44cdf | 519 | qemu_clock_step(2000000 + 1); |
516deb42 | 520 | |
56700e1a | 521 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
057516fe | 522 | no_immediate_reload ? 0 : (no_round_down ? 98 : 97)); |
56700e1a DO |
523 | |
524 | if (no_immediate_trigger && no_immediate_reload) { | |
525 | g_assert_true(triggered); | |
526 | ||
527 | triggered = false; | |
528 | } else { | |
529 | g_assert_false(triggered); | |
530 | } | |
516deb42 DO |
531 | |
532 | ptimer_set_count(ptimer, 99); | |
533 | ptimer_run(ptimer, 1); | |
534 | } | |
535 | ||
33d44cdf | 536 | qemu_clock_step(2000000 + 1); |
5b262bb6 | 537 | |
057516fe | 538 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97); |
5b262bb6 DO |
539 | g_assert_false(triggered); |
540 | ||
541 | qemu_clock_step(2000000 * 97); | |
542 | ||
057516fe | 543 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); |
5b262bb6 DO |
544 | g_assert_false(triggered); |
545 | ||
546 | qemu_clock_step(2000000 * 2); | |
547 | ||
548 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
549 | g_assert_true(triggered); | |
550 | ||
551 | triggered = false; | |
552 | ||
553 | ptimer_set_count(ptimer, 0); | |
554 | ptimer_run(ptimer, 0); | |
56700e1a DO |
555 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
556 | no_immediate_reload ? 0 : 99); | |
516deb42 DO |
557 | |
558 | if (no_immediate_trigger) { | |
559 | g_assert_false(triggered); | |
560 | } else { | |
561 | g_assert_true(triggered); | |
562 | } | |
5b262bb6 DO |
563 | |
564 | triggered = false; | |
565 | ||
33d44cdf | 566 | qemu_clock_step(1); |
293130aa | 567 | |
56700e1a DO |
568 | if (no_immediate_reload) { |
569 | qemu_clock_step(2000000); | |
570 | } | |
571 | ||
057516fe | 572 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 99 : 98); |
56700e1a DO |
573 | |
574 | if (no_immediate_reload && no_immediate_trigger) { | |
575 | g_assert_true(triggered); | |
576 | } else { | |
577 | g_assert_false(triggered); | |
578 | } | |
293130aa DO |
579 | |
580 | triggered = false; | |
581 | ||
582 | qemu_clock_step(2000000); | |
5b262bb6 | 583 | |
057516fe | 584 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97); |
5b262bb6 DO |
585 | g_assert_false(triggered); |
586 | ||
587 | qemu_clock_step(2000000 * 98); | |
588 | ||
057516fe DO |
589 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, |
590 | wrap_policy ? 0 : (no_round_down ? 99 : 98)); | |
5b262bb6 DO |
591 | g_assert_true(triggered); |
592 | ||
593 | ptimer_stop(ptimer); | |
594 | } | |
595 | ||
596 | static void check_periodic_with_load_0(gconstpointer arg) | |
597 | { | |
598 | const uint8_t *policy = arg; | |
599 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
600 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
2e74583b | 601 | bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER); |
516deb42 | 602 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); |
5b262bb6 DO |
603 | |
604 | triggered = false; | |
605 | ||
606 | ptimer_set_period(ptimer, 2000000); | |
607 | ptimer_run(ptimer, 0); | |
608 | ||
609 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
516deb42 DO |
610 | |
611 | if (no_immediate_trigger) { | |
612 | g_assert_false(triggered); | |
613 | } else { | |
614 | g_assert_true(triggered); | |
615 | } | |
5b262bb6 DO |
616 | |
617 | triggered = false; | |
618 | ||
33d44cdf | 619 | qemu_clock_step(2000000 + 1); |
5b262bb6 DO |
620 | |
621 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
2e74583b | 622 | |
516deb42 | 623 | if (continuous_trigger || no_immediate_trigger) { |
2e74583b DO |
624 | g_assert_true(triggered); |
625 | } else { | |
626 | g_assert_false(triggered); | |
627 | } | |
5b262bb6 | 628 | |
293130aa DO |
629 | triggered = false; |
630 | ||
631 | ptimer_set_count(ptimer, 10); | |
632 | ptimer_run(ptimer, 0); | |
633 | ||
33d44cdf | 634 | qemu_clock_step(2000000 * 10 + 1); |
293130aa DO |
635 | |
636 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
637 | g_assert_true(triggered); | |
638 | ||
639 | triggered = false; | |
640 | ||
33d44cdf | 641 | qemu_clock_step(2000000 + 1); |
293130aa DO |
642 | |
643 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
2e74583b DO |
644 | |
645 | if (continuous_trigger) { | |
646 | g_assert_true(triggered); | |
647 | } else { | |
648 | g_assert_false(triggered); | |
649 | } | |
293130aa | 650 | |
5b262bb6 DO |
651 | ptimer_stop(ptimer); |
652 | } | |
653 | ||
654 | static void check_oneshot_with_load_0(gconstpointer arg) | |
655 | { | |
656 | const uint8_t *policy = arg; | |
657 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
658 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
516deb42 | 659 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); |
5b262bb6 DO |
660 | |
661 | triggered = false; | |
662 | ||
663 | ptimer_set_period(ptimer, 2000000); | |
664 | ptimer_run(ptimer, 1); | |
665 | ||
666 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
516deb42 DO |
667 | |
668 | if (no_immediate_trigger) { | |
669 | g_assert_false(triggered); | |
670 | } else { | |
671 | g_assert_true(triggered); | |
672 | } | |
5b262bb6 DO |
673 | |
674 | triggered = false; | |
675 | ||
33d44cdf | 676 | qemu_clock_step(2000000 + 1); |
5b262bb6 DO |
677 | |
678 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
516deb42 DO |
679 | |
680 | if (no_immediate_trigger) { | |
681 | g_assert_true(triggered); | |
682 | } else { | |
683 | g_assert_false(triggered); | |
684 | } | |
5b262bb6 DO |
685 | } |
686 | ||
687 | static void add_ptimer_tests(uint8_t policy) | |
688 | { | |
689 | uint8_t *ppolicy = g_malloc(1); | |
293130aa | 690 | char *policy_name = g_malloc0(256); |
5b262bb6 DO |
691 | |
692 | *ppolicy = policy; | |
693 | ||
694 | if (policy == PTIMER_POLICY_DEFAULT) { | |
695 | g_sprintf(policy_name, "default"); | |
696 | } | |
697 | ||
293130aa DO |
698 | if (policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) { |
699 | g_strlcat(policy_name, "wrap_after_one_period,", 256); | |
700 | } | |
701 | ||
2e74583b DO |
702 | if (policy & PTIMER_POLICY_CONTINUOUS_TRIGGER) { |
703 | g_strlcat(policy_name, "continuous_trigger,", 256); | |
704 | } | |
705 | ||
516deb42 DO |
706 | if (policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER) { |
707 | g_strlcat(policy_name, "no_immediate_trigger,", 256); | |
708 | } | |
709 | ||
56700e1a DO |
710 | if (policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD) { |
711 | g_strlcat(policy_name, "no_immediate_reload,", 256); | |
712 | } | |
713 | ||
057516fe DO |
714 | if (policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN) { |
715 | g_strlcat(policy_name, "no_counter_rounddown,", 256); | |
716 | } | |
717 | ||
24b94625 | 718 | g_test_add_data_func( |
5b262bb6 DO |
719 | g_strdup_printf("/ptimer/set_count policy=%s", policy_name), |
720 | ppolicy, check_set_count); | |
721 | ||
24b94625 | 722 | g_test_add_data_func( |
5b262bb6 DO |
723 | g_strdup_printf("/ptimer/set_limit policy=%s", policy_name), |
724 | ppolicy, check_set_limit); | |
725 | ||
24b94625 | 726 | g_test_add_data_func( |
5b262bb6 DO |
727 | g_strdup_printf("/ptimer/oneshot policy=%s", policy_name), |
728 | ppolicy, check_oneshot); | |
729 | ||
24b94625 | 730 | g_test_add_data_func( |
5b262bb6 DO |
731 | g_strdup_printf("/ptimer/periodic policy=%s", policy_name), |
732 | ppolicy, check_periodic); | |
733 | ||
24b94625 | 734 | g_test_add_data_func( |
5b262bb6 DO |
735 | g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name), |
736 | ppolicy, check_on_the_fly_mode_change); | |
737 | ||
24b94625 | 738 | g_test_add_data_func( |
5b262bb6 DO |
739 | g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name), |
740 | ppolicy, check_on_the_fly_period_change); | |
741 | ||
24b94625 | 742 | g_test_add_data_func( |
5b262bb6 DO |
743 | g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name), |
744 | ppolicy, check_on_the_fly_freq_change); | |
745 | ||
24b94625 | 746 | g_test_add_data_func( |
5b262bb6 DO |
747 | g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name), |
748 | ppolicy, check_run_with_period_0); | |
749 | ||
24b94625 | 750 | g_test_add_data_func( |
5b262bb6 DO |
751 | g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name), |
752 | ppolicy, check_run_with_delta_0); | |
753 | ||
24b94625 | 754 | g_test_add_data_func( |
5b262bb6 DO |
755 | g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name), |
756 | ppolicy, check_periodic_with_load_0); | |
757 | ||
24b94625 | 758 | g_test_add_data_func( |
5b262bb6 DO |
759 | g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name), |
760 | ppolicy, check_oneshot_with_load_0); | |
761 | } | |
762 | ||
293130aa DO |
763 | static void add_all_ptimer_policies_comb_tests(void) |
764 | { | |
057516fe | 765 | int last_policy = PTIMER_POLICY_NO_COUNTER_ROUND_DOWN; |
293130aa DO |
766 | int policy = PTIMER_POLICY_DEFAULT; |
767 | ||
768 | for (; policy < (last_policy << 1); policy++) { | |
769 | add_ptimer_tests(policy); | |
770 | } | |
771 | } | |
772 | ||
5b262bb6 DO |
773 | int main(int argc, char **argv) |
774 | { | |
775 | int i; | |
776 | ||
777 | g_test_init(&argc, &argv, NULL); | |
778 | ||
779 | for (i = 0; i < QEMU_CLOCK_MAX; i++) { | |
780 | main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1); | |
781 | } | |
782 | ||
293130aa | 783 | add_all_ptimer_policies_comb_tests(); |
5b262bb6 DO |
784 | |
785 | qtest_allowed = true; | |
786 | ||
787 | return g_test_run(); | |
788 | } |