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