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