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