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