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