* [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll
@ 2013-08-06 23:48 Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
` (22 more replies)
0 siblings, 23 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
This patch series adds support for timers attached to an AioContext clock
which get called within aio_poll.
In doing so it removes alarm timers and moves to use ppoll where possible.
This patch set 'sort of' passes make check (see below for caveat)
including a new test harness for the aio timers, but has not been
tested much beyond that. In particular, the win32 changes have not
even been compile tested. Equally, alterations to use_icount
are untested.
Caveat: I have had to alter tests/test-aio.c so the following error
no longer occurs.
ERROR:tests/test-aio.c:346:test_wait_event_notifier_noflush: assertion failed: (aio_poll(ctx, false))
As gar as I can tell, this check was incorrect, in that it checking
aio_poll makes progress when in fact it should not make progress. I
fixed an issue where aio_poll was (as far as I can tell) wrongly
returning true on a timeout, and that generated this error.
Note also the comment on patch 18 in relation to a possible bug
in cpus.c.
Changes since v6:
* Fix build failure in vnc-auth-sasl.c
* Split first patch into 3
* Add assert on timerlist_free
* Fix ==/= error on qemu_clock_use_for_deadline
* Remove unnecessary cast in aio_timerlist_notify
* Fix bad deadline comparison in aio_ctx_check
* Add assert to timerlist_new_from_clock to check init_clocks
* Use timer_list not tl
* Change default_timerlistgroup to main_loop_timerlistgroup
* Add comment on commit for qemu_clock_use_for_deadline
* Fixed various include file issues
* Convert *_has_timers and *_has_expired to return bool
* Make loop variable consistent when looping through clock types
* Add documentation to existing qemu_timer calls
* Remove qemu_clock_deadline and move to qemu_clock_deadline_ns
Changes since v5:
* Rebase onto master (b9ac5d9)
* Fix spacing in typedef QEMUTimerList
* Rename 'QEMUClocks' extern to 'qemu_clocks'
Changes since v4:
* Rename qemu_timerlist_ functions to timer_list (per Paolo Bonzini)
* Rename qemu_timer_.*timerlist.* to timer_ (per Paolo Bonzini)
* Use enum for QEMUClockType
* Put clocks into an array; remove global variables
* Introduce QEMUTimerListGroup - a timeliest of each type
* Add a QEMUTimerListGroup to AioContext
* Use a callback on timer modification, rather than binding in
AioContext into the timeliest
* Make cpus.c iterate over all timerlists when it does a notify
* Make cpus.c icount timeout use soonest timeout
across all timerlists
Changes since v3:
* Split up QEMUClock and QEMUClock list
* Improve commenting
* Fix comment in vl.c
* Change test/test-aio.c to reflect correct behaviour in aio_poll.
Changes since v2:
* Reordered to remove alarm timers last
* Added prctl(PR_SET_TIMERSLACK, 1, ...)
* Renamed qemu_g_poll_ns to qemu_poll_ns
* Moved declaration of above & drop glib types
* Do not use a global list of qemu clocks
* Add AioContext * to QEMUClock
* Split up conversion to use ppoll and timers
* Indentation fix
* Fix aio_win32.c aio_poll to return progress
* aio_notify / qemu_notify when timers are modified
* change comment in deprecation of clock options
Alex Bligh (22):
aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock
types
aio / timers: add qemu-timer.c utility functions
aio / timers: Consistent treatment of disabled clocks for deadlines
aio / timers: add ppoll support with qemu_poll_ns
aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer
slack
aio / timers: Make qemu_run_timers and qemu_run_all_timers return
progress
aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList
aio / timers: Untangle include files
aio / timers: Add QEMUTimerListGroup and helper functions
aio / timers: Add QEMUTimerListGroup to AioContext
aio / timers: Add a notify callback to QEMUTimerList
aio / timers: aio_ctx_prepare sets timeout from AioContext timers
aio / timers: Add aio_timer_new wrapper
aio / timers: Convert aio_poll to use AioContext timers' deadline
aio / timers: Convert mainloop to use timeout
aio / timers: On timer modification, qemu_notify or aio_notify
aio / timers: Introduce new API qemu_timer_new and friends
aio / timers: Use all timerlists in icount warp calculations
aio / timers: Add documentation and new format calls
aio / timers: Remove alarm timers
aio / timers: Add test harness for AioContext timers
aio / timers: Remove legacy qemu_clock_deadline &
qemu_timerlist_deadline
aio-posix.c | 20 +-
aio-win32.c | 22 +-
async.c | 20 +-
configure | 37 ++
cpus.c | 46 ++-
dma-helpers.c | 1 +
hw/dma/xilinx_axidma.c | 1 +
hw/timer/arm_timer.c | 1 +
hw/timer/exynos4210_mct.c | 1 +
hw/timer/exynos4210_pwm.c | 1 +
hw/timer/grlib_gptimer.c | 2 +
hw/timer/imx_epit.c | 1 +
hw/timer/imx_gpt.c | 1 +
hw/timer/lm32_timer.c | 1 +
hw/timer/puv3_ost.c | 1 +
hw/timer/sh_timer.c | 1 +
hw/timer/slavio_timer.c | 1 +
hw/timer/xilinx_timer.c | 1 +
hw/tpm/tpm_tis.c | 1 +
hw/usb/hcd-uhci.c | 1 +
include/block/aio.h | 23 ++
include/block/block_int.h | 1 +
include/block/coroutine.h | 2 +
include/qemu/timer.h | 857 +++++++++++++++++++++++++++++++++++++++++++--
main-loop.c | 49 ++-
migration-exec.c | 1 +
migration-fd.c | 1 +
migration-tcp.c | 1 +
migration-unix.c | 1 +
migration.c | 1 +
nbd.c | 1 +
net/net.c | 1 +
net/socket.c | 1 +
qemu-coroutine-io.c | 1 +
qemu-io-cmds.c | 1 +
qemu-nbd.c | 1 +
qemu-timer.c | 803 +++++++++++++++---------------------------
qtest.c | 2 +-
slirp/misc.c | 1 +
tests/test-aio.c | 144 +++++++-
tests/test-thread-pool.c | 3 +
thread-pool.c | 1 +
ui/vnc-auth-sasl.h | 1 +
ui/vnc-auth-vencrypt.c | 2 +-
ui/vnc-ws.c | 1 +
vl.c | 4 +-
46 files changed, 1480 insertions(+), 586 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
@ 2013-08-06 23:48 ` Alex Bligh
2013-08-07 11:31 ` Stefan Hajnoczi
` (2 more replies)
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 02/22] aio / timers: add qemu-timer.c utility functions Alex Bligh
` (21 subsequent siblings)
22 siblings, 3 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add qemu_clock_free and expose qemu_new_clock as qemu_clock_new.
Expose clock types.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 22 ++++++++++++++++++++++
qemu-timer.c | 11 ++++++-----
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 9dd206c..3dd20bf 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -11,6 +11,10 @@
#define SCALE_US 1000
#define SCALE_NS 1
+#define QEMU_CLOCK_REALTIME 0
+#define QEMU_CLOCK_VIRTUAL 1
+#define QEMU_CLOCK_HOST 2
+
typedef struct QEMUClock QEMUClock;
typedef void QEMUTimerCB(void *opaque);
@@ -32,6 +36,24 @@ extern QEMUClock *vm_clock;
the virtual clock. */
extern QEMUClock *host_clock;
+/**
+ * qemu_clock_new:
+ * @type: the type of clock to be created
+ *
+ * Create a new clock of type @type
+ *
+ * Returns: A pointer to the clock object
+ */
+QEMUClock *qemu_clock_new(int type);
+
+/**
+ * qemu_clock_free:
+ * @clock: the clock to free
+ *
+ * Free clock object @clock
+ */
+void qemu_clock_free(QEMUClock *clock);
+
int64_t qemu_get_clock_ns(QEMUClock *clock);
int64_t qemu_clock_has_timers(QEMUClock *clock);
int64_t qemu_clock_expired(QEMUClock *clock);
diff --git a/qemu-timer.c b/qemu-timer.c
index b2d95e2..531aa05 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -40,10 +40,6 @@
/***********************************************************/
/* timers */
-#define QEMU_CLOCK_REALTIME 0
-#define QEMU_CLOCK_VIRTUAL 1
-#define QEMU_CLOCK_HOST 2
-
struct QEMUClock {
QEMUTimer *active_timers;
@@ -231,7 +227,7 @@ QEMUClock *rt_clock;
QEMUClock *vm_clock;
QEMUClock *host_clock;
-static QEMUClock *qemu_new_clock(int type)
+QEMUClock *qemu_clock_new(int type)
{
QEMUClock *clock;
@@ -243,6 +239,11 @@ static QEMUClock *qemu_new_clock(int type)
return clock;
}
+void qemu_clock_free(QEMUClock *clock)
+{
+ g_free(clock);
+}
+
void qemu_clock_enable(QEMUClock *clock, bool enabled)
{
bool old = clock->enabled;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 02/22] aio / timers: add qemu-timer.c utility functions
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
@ 2013-08-06 23:48 ` Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 03/22] aio / timers: Consistent treatment of disabled clocks for deadlines Alex Bligh
` (20 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add utility functions to qemu-timer.c for nanosecond timing.
Add qemu_clock_deadline_ns to calculate deadlines to
nanosecond accuracy.
Add utility function qemu_soonest_timeout to calculate soonest deadline.
Add qemu_timeout_ns_to_ms to convert a timeout in nanoseconds back to
milliseconds for when ppoll is not used.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 42 ++++++++++++++++++++++++++++++++++++++++++
qemu-timer.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 3dd20bf..c96fe2b 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -58,6 +58,29 @@ int64_t qemu_get_clock_ns(QEMUClock *clock);
int64_t qemu_clock_has_timers(QEMUClock *clock);
int64_t qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);
+
+/**
+ * qemu_clock_deadline_ns:
+ * @clock: the clock to operate on
+ *
+ * Calculate the timeout of the earliest expiring timer
+ * in nanoseconds, or -1 if no timer is set to expire.
+ *
+ * Returns: time until expiry in nanoseconds or -1
+ */
+int64_t qemu_clock_deadline_ns(QEMUClock *clock);
+
+/**
+ * qemu_timeout_ns_to_ms:
+ * @ns: nanosecond timeout value
+ *
+ * Convert a nanosecond timeout value (or -1) to
+ * a millisecond value (or -1), always rounding up.
+ *
+ * Returns: millisecond timeout value
+ */
+int qemu_timeout_ns_to_ms(int64_t ns);
+
void qemu_clock_enable(QEMUClock *clock, bool enabled);
void qemu_clock_warp(QEMUClock *clock);
@@ -85,6 +108,25 @@ int64_t cpu_get_ticks(void);
void cpu_enable_ticks(void);
void cpu_disable_ticks(void);
+/**
+ * qemu_soonest_timeout:
+ * @timeout1: first timeout in nanoseconds (or -1 for infinite)
+ * @timeout2: second timeout in nanoseconds (or -1 for infinite)
+ *
+ * Calculates the soonest of two timeout values. -1 means infinite, which
+ * is later than any other value.
+ *
+ * Returns: soonest timeout value in nanoseconds (or -1 for infinite)
+ */
+static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
+{
+ /* we can abuse the fact that -1 (which means infinite) is a maximal
+ * value when cast to unsigned. As this is disgusting, it's kept in
+ * one inline function.
+ */
+ return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
+}
+
static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
void *opaque)
{
diff --git a/qemu-timer.c b/qemu-timer.c
index 531aa05..2a862bc 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -278,6 +278,56 @@ int64_t qemu_clock_deadline(QEMUClock *clock)
return delta;
}
+/*
+ * As above, but return -1 for no deadline, and do not cap to 2^32
+ * as we know the result is always positive.
+ */
+
+int64_t qemu_clock_deadline_ns(QEMUClock *clock)
+{
+ int64_t delta;
+
+ if (!clock->enabled || !clock->active_timers) {
+ return -1;
+ }
+
+ delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+
+ if (delta <= 0) {
+ return 0;
+ }
+
+ return delta;
+}
+
+/* Transition function to convert a nanosecond timeout to ms
+ * This is used where a system does not support ppoll
+ */
+int qemu_timeout_ns_to_ms(int64_t ns)
+{
+ int64_t ms;
+ if (ns < 0) {
+ return -1;
+ }
+
+ if (!ns) {
+ return 0;
+ }
+
+ /* Always round up, because it's better to wait too long than to wait too
+ * little and effectively busy-wait
+ */
+ ms = (ns + SCALE_MS - 1) / SCALE_MS;
+
+ /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
+ if (ms > (int64_t) INT32_MAX) {
+ ms = INT32_MAX;
+ }
+
+ return (int) ms;
+}
+
+
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 03/22] aio / timers: Consistent treatment of disabled clocks for deadlines
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 02/22] aio / timers: add qemu-timer.c utility functions Alex Bligh
@ 2013-08-06 23:48 ` Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 04/22] aio / timers: add ppoll support with qemu_poll_ns Alex Bligh
` (19 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Make treatment of disabled clocks consistent in deadline calculation
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
qemu-timer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qemu-timer.c b/qemu-timer.c
index 2a862bc..0617e3e 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -269,7 +269,7 @@ int64_t qemu_clock_deadline(QEMUClock *clock)
/* To avoid problems with overflow limit this to 2^32. */
int64_t delta = INT32_MAX;
- if (clock->active_timers) {
+ if (clock->enabled && clock->active_timers) {
delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
}
if (delta < 0) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 04/22] aio / timers: add ppoll support with qemu_poll_ns
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (2 preceding siblings ...)
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 03/22] aio / timers: Consistent treatment of disabled clocks for deadlines Alex Bligh
@ 2013-08-06 23:48 ` Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 05/22] aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer slack Alex Bligh
` (18 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add qemu_poll_ns which works like g_poll but takes a nanosecond
timeout.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
configure | 19 +++++++++++++++++++
include/qemu/timer.h | 12 ++++++++++++
qemu-timer.c | 24 ++++++++++++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/configure b/configure
index f0761ea..4e54d1b 100755
--- a/configure
+++ b/configure
@@ -2818,6 +2818,22 @@ if compile_prog "" "" ; then
dup3=yes
fi
+# check for ppoll support
+ppoll=no
+cat > $TMPC << EOF
+#include <poll.h>
+
+int main(void)
+{
+ struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
+ ppoll(&pfd, 1, 0, 0);
+ return 0;
+}
+EOF
+if compile_prog "" "" ; then
+ ppoll=yes
+fi
+
# check for epoll support
epoll=no
cat > $TMPC << EOF
@@ -3809,6 +3825,9 @@ fi
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi
+if test "$ppoll" = "yes" ; then
+ echo "CONFIG_PPOLL=y" >> $config_host_mak
+fi
if test "$epoll" = "yes" ; then
echo "CONFIG_EPOLL=y" >> $config_host_mak
fi
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index c96fe2b..7cf6ed0 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -81,6 +81,18 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock);
*/
int qemu_timeout_ns_to_ms(int64_t ns);
+/**
+ * qemu_poll_ns:
+ * @fds: Array of file descriptors
+ * @nfds: number of file descriptors
+ * @timeout: timeout in nanoseconds
+ *
+ * Perform a poll like g_poll but with a timeout in nanoseconds.
+ * See g_poll documentation for further details.
+ *
+ * Returns: number of fds ready
+ */
+int qemu_poll_ns(GPollFD *fds, uint nfds, int64_t timeout);
void qemu_clock_enable(QEMUClock *clock, bool enabled);
void qemu_clock_warp(QEMUClock *clock);
diff --git a/qemu-timer.c b/qemu-timer.c
index 0617e3e..3109bd8 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -37,6 +37,10 @@
#include <mmsystem.h>
#endif
+#ifdef CONFIG_PPOLL
+#include <poll.h>
+#endif
+
/***********************************************************/
/* timers */
@@ -328,6 +332,26 @@ int qemu_timeout_ns_to_ms(int64_t ns)
}
+/* qemu implementation of g_poll which uses a nanosecond timeout but is
+ * otherwise identical to g_poll
+ */
+int qemu_poll_ns(GPollFD *fds, uint nfds, int64_t timeout)
+{
+#ifdef CONFIG_PPOLL
+ if (timeout < 0) {
+ return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
+ } else {
+ struct timespec ts;
+ ts.tv_sec = timeout / 1000000000LL;
+ ts.tv_nsec = timeout % 1000000000LL;
+ return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
+ }
+#else
+ return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
+#endif
+}
+
+
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 05/22] aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer slack
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (3 preceding siblings ...)
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 04/22] aio / timers: add ppoll support with qemu_poll_ns Alex Bligh
@ 2013-08-06 23:48 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 06/22] aio / timers: Make qemu_run_timers and qemu_run_all_timers return progress Alex Bligh
` (17 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:48 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Where supported, called prctl(PR_SET_TIMERSLACK, 1, ...) to
set one nanosecond timer slack to increase precision of timer
calls.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
qemu-timer.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/qemu-timer.c b/qemu-timer.c
index 3109bd8..7ad05fb 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -41,6 +41,10 @@
#include <poll.h>
#endif
+#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
+#include <sys/prctl.h>
+#endif
+
/***********************************************************/
/* timers */
@@ -508,10 +512,13 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
void init_clocks(void)
{
if (!rt_clock) {
- rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
- vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
- host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+ rt_clock = qemu_clock_new(QEMU_CLOCK_REALTIME);
+ vm_clock = qemu_clock_new(QEMU_CLOCK_VIRTUAL);
+ host_clock = qemu_clock_new(QEMU_CLOCK_HOST);
}
+#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
+ prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
+#endif
}
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 06/22] aio / timers: Make qemu_run_timers and qemu_run_all_timers return progress
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (4 preceding siblings ...)
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 05/22] aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer slack Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList Alex Bligh
` (16 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Make qemu_run_timers and qemu_run_all_timers return progress
so that aio_poll etc. can determine whether a timer has been
run.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 21 +++++++++++++++++++--
qemu-timer.c | 18 ++++++++++++------
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 7cf6ed0..0d368cc 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -110,8 +110,25 @@ bool qemu_timer_pending(QEMUTimer *ts);
bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
-void qemu_run_timers(QEMUClock *clock);
-void qemu_run_all_timers(void);
+/**
+ * qemu_run_timers:
+ * @clock: clock on which to operate
+ *
+ * Run all the timers associated with a clock.
+ *
+ * Returns: true if any timer ran.
+ */
+bool qemu_run_timers(QEMUClock *clock);
+
+/**
+ * qemu_run_all_timers:
+ *
+ * Run all the timers associated with every clock.
+ *
+ * Returns: true if any timer ran.
+ */
+bool qemu_run_all_timers(void);
+
void configure_alarms(char const *opt);
void init_clocks(void);
int init_timer_alarm(void);
diff --git a/qemu-timer.c b/qemu-timer.c
index 7ad05fb..388b98c 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -451,13 +451,14 @@ bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
}
-void qemu_run_timers(QEMUClock *clock)
+bool qemu_run_timers(QEMUClock *clock)
{
QEMUTimer *ts;
int64_t current_time;
+ bool progress = false;
if (!clock->enabled)
- return;
+ return progress;
current_time = qemu_get_clock_ns(clock);
for(;;) {
@@ -471,7 +472,9 @@ void qemu_run_timers(QEMUClock *clock)
/* run the callback (the timer list can be modified) */
ts->cb(ts->opaque);
+ progress = true;
}
+ return progress;
}
int64_t qemu_get_clock_ns(QEMUClock *clock)
@@ -526,20 +529,23 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
return qemu_timer_pending(ts) ? ts->expire_time : -1;
}
-void qemu_run_all_timers(void)
+bool qemu_run_all_timers(void)
{
+ bool progress = false;
alarm_timer->pending = false;
/* vm time timers */
- qemu_run_timers(vm_clock);
- qemu_run_timers(rt_clock);
- qemu_run_timers(host_clock);
+ progress |= qemu_run_timers(vm_clock);
+ progress |= qemu_run_timers(rt_clock);
+ progress |= qemu_run_timers(host_clock);
/* rearm timer, if not periodic */
if (alarm_timer->expired) {
alarm_timer->expired = false;
qemu_rearm_alarm_timer(alarm_timer);
}
+
+ return progress;
}
#ifdef _WIN32
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (5 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 06/22] aio / timers: Make qemu_run_timers and qemu_run_all_timers return progress Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-08 6:12 ` liu ping fan
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 08/22] aio / timers: Untangle include files Alex Bligh
` (15 subsequent siblings)
22 siblings, 1 reply; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Split QEMUClock into QEMUClock and QEMUTimerList so that we can
have more than one QEMUTimerList associated with the same clock.
Introduce a default_timerlist concept and make existing
qemu_clock_* calls that actually should operate on a QEMUTimerList
call the relevant QEMUTimerList implementations, using the clock's
default timerlist. This vastly reduces the invasiveness of this
change and means the API stays constant for existing users.
Introduce a list of QEMUTimerLists associated with each clock
so that reenabling the clock can cause all the notifiers
to be called. Note the code to do the notifications is added
in a later patch.
Switch QEMUClockType to an enum. Remove global variables vm_clock,
host_clock and rt_clock and add compatibility defines. Do not
fix qemu_next_alarm_deadline as it's going to be deleted.
Add qemu_clock_use_for_deadline to indicate whether a particular
clock should be used for deadline calculations. When use_icount
is true, vm_clock should not be used for deadline calculations
as it does not contain a nanosecond count. Instead, icount
timeouts come from the execution thread doing aio_notify or
qemu_notify as appropriate. This function is used in the next
patch.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 408 +++++++++++++++++++++++++++++++++++++++++++++++---
qemu-timer.c | 201 +++++++++++++++++++------
2 files changed, 538 insertions(+), 71 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 0d368cc..eb2b99e 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -11,30 +11,71 @@
#define SCALE_US 1000
#define SCALE_NS 1
-#define QEMU_CLOCK_REALTIME 0
-#define QEMU_CLOCK_VIRTUAL 1
-#define QEMU_CLOCK_HOST 2
+/**
+ * QEMUClockType:
+ *
+ * The following clock types are available:
+ *
+ * @QEMU_CLOCK_REALTIME: Real time clock
+ *
+ * The real time clock should be used only for stuff which does not
+ * change the virtual machine state, as it is run even if the virtual
+ * machine is stopped. The real time clock has a frequency of 1000
+ * Hz.
+ *
+ * Formerly rt_clock
+ *
+ * @QEMU_CLOCK_VIRTUAL: virtual clock
+ *
+ * The virtual clock is only run during the emulation. It is stopped
+ * when the virtual machine is stopped. Virtual timers use a high
+ * precision clock, usually cpu cycles (use ticks_per_sec).
+ *
+ * Formerly vm_clock
+ *
+ * @QEMU_CLOCK_HOST: host clock
+ *
+ * The host clock should be use for device models that emulate accurate
+ * real time sources. It will continue to run when the virtual machine
+ * is suspended, and it will reflect system time changes the host may
+ * undergo (e.g. due to NTP). The host clock has the same precision as
+ * the virtual clock.
+ *
+ * Formerly host_clock
+ */
+
+typedef enum {
+ QEMU_CLOCK_REALTIME = 0,
+ QEMU_CLOCK_VIRTUAL = 1,
+ QEMU_CLOCK_HOST = 2,
+ QEMU_CLOCK_MAX
+} QEMUClockType;
typedef struct QEMUClock QEMUClock;
+typedef struct QEMUTimerList QEMUTimerList;
typedef void QEMUTimerCB(void *opaque);
-/* The real time clock should be used only for stuff which does not
- change the virtual machine state, as it is run even if the virtual
- machine is stopped. The real time clock has a frequency of 1000
- Hz. */
-extern QEMUClock *rt_clock;
+extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
-/* The virtual clock is only run during the emulation. It is stopped
- when the virtual machine is stopped. Virtual timers use a high
- precision clock, usually cpu cycles (use ticks_per_sec). */
-extern QEMUClock *vm_clock;
+/**
+ * qemu_get_clock:
+ * @type: type of clock
+ *
+ * Translate a clock type into a pointer to QEMUClock object.
+ *
+ * Returns: a pointer to the QEMUClock object
+ */
+static inline QEMUClock *qemu_get_clock(QEMUClockType type)
+{
+ return qemu_clocks[type];
+}
-/* The host clock should be use for device models that emulate accurate
- real time sources. It will continue to run when the virtual machine
- is suspended, and it will reflect system time changes the host may
- undergo (e.g. due to NTP). The host clock has the same precision as
- the virtual clock. */
-extern QEMUClock *host_clock;
+/* These three clocks are maintained here with separate variable
+ * names for compatibility only.
+ */
+#define rt_clock (qemu_get_clock(QEMU_CLOCK_REALTIME))
+#define vm_clock (qemu_get_clock(QEMU_CLOCK_VIRTUAL))
+#define host_clock (qemu_get_clock(QEMU_CLOCK_HOST))
/**
* qemu_clock_new:
@@ -44,7 +85,7 @@ extern QEMUClock *host_clock;
*
* Returns: A pointer to the clock object
*/
-QEMUClock *qemu_clock_new(int type);
+QEMUClock *qemu_clock_new(QEMUClockType type);
/**
* qemu_clock_free:
@@ -55,8 +96,8 @@ QEMUClock *qemu_clock_new(int type);
void qemu_clock_free(QEMUClock *clock);
int64_t qemu_get_clock_ns(QEMUClock *clock);
-int64_t qemu_clock_has_timers(QEMUClock *clock);
-int64_t qemu_clock_expired(QEMUClock *clock);
+bool qemu_clock_has_timers(QEMUClock *clock);
+bool qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);
/**
@@ -71,6 +112,124 @@ int64_t qemu_clock_deadline(QEMUClock *clock);
int64_t qemu_clock_deadline_ns(QEMUClock *clock);
/**
+ * qemu_clock_use_for_deadline:
+ * @clock: the clock to operate on
+ *
+ * Determine whether a clock should be used for deadline
+ * calculations. Some clocks, for instance vm_clock with
+ * use_icount set, do not count in nanoseconds. Such clocks
+ * are not used for deadline calculations, and are presumed
+ * to interrupt any poll using qemu_notify/aio_notify
+ * etc.
+ *
+ * Returns: true if the clock runs in nanoseconds and
+ * should be used for a deadline.
+ */
+bool qemu_clock_use_for_deadline(QEMUClock *clock);
+
+/**
+ * qemu_clock_get_default_timerlist:
+ * @clock: the clock to operate on
+ *
+ * Return the default timer list assocatiated with a clock.
+ *
+ * Returns: the default timer list
+ */
+QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock);
+
+/**
+ * timerlist_new:
+ * @type: the clock type to associate with the timerlist
+ *
+ * Create a new timerlist associated with the clock of
+ * type @type.
+ *
+ * Returns: a pointer to the QEMUTimerList created
+ */
+QEMUTimerList *timerlist_new(QEMUClockType type);
+
+/**
+ * timerlist_free:
+ * @timer_list: the timer list to free
+ *
+ * Frees a timer_list. It must have no active timers.
+ */
+void timerlist_free(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_has_timers:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine whether a timer list has active timers
+ *
+ * Returns: true if the timer list has timers.
+ */
+bool timerlist_has_timers(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_expired:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine whether a timer list has any timers which
+ * are expired.
+ *
+ * Returns: true if the timer list has timers which
+ * have expired.
+ */
+bool timerlist_expired(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_deadline:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine the deadline for a timer_list. This is
+ * a legacy function which returns INT32_MAX if the
+ * timer list has no timers or if the earliest timer
+ * expires later than INT32_MAX nanoseconds away.
+ *
+ * Returns: the number of nanoseconds until the earliest
+ * timer expires or INT32_MAX in the situations listed
+ * above
+ */
+int64_t timerlist_deadline(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_deadline_ns:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine the deadline for a timer_list, i.e.
+ * the number of nanoseconds until the first timer
+ * expires. Return -1 if there are no timers.
+ *
+ * Returns: the number of nanoseconds until the earliest
+ * timer expires -1 if none
+ */
+int64_t timerlist_deadline_ns(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_getclock:
+ * @timer_list: the timer list to operate on
+ *
+ * Read the clock value associated with a timer list.
+ * The clock value is normally in nanoseconds, but may
+ * not be in some instances (e.g. vm_clock with use_icount).
+ *
+ * Returns: the value of the clock associated with the
+ * timer list.
+ */
+QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_run_timers:
+ * @timer_list: the timer list to use
+ *
+ * Call all expired timers associated with the timer list.
+ *
+ * Returns: true if any timer expired
+ */
+bool timerlist_run_timers(QEMUTimerList *timer_list);
+
+/**
* qemu_timeout_ns_to_ms:
* @ns: nanosecond timeout value
*
@@ -102,6 +261,21 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque);
+
+/**
+ * timer_new:
+ * @timer_list: the timer list to attach the timer to
+ * @scale: the scale value for the tiemr
+ * @cb: the callback to be called when the timer expires
+ * @opaque: the opaque pointer to be passed to the callback
+ *
+ * Creeate a new timer and associate it with @timer_list.
+ *
+ * Returns: a pointer to the timer
+ */
+QEMUTimer *timer_new(QEMUTimerList *timer_list, int scale,
+ QEMUTimerCB *cb, void *opaque);
+
void qemu_free_timer(QEMUTimer *ts);
void qemu_del_timer(QEMUTimer *ts);
void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
@@ -110,11 +284,101 @@ bool qemu_timer_pending(QEMUTimer *ts);
bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
+/* New format calling conventions for timers */
+
+/**
+ * timer_free:
+ * @ts: the timer
+ *
+ * Free a timer (it must not be on the active list)
+ */
+static inline void timer_free(QEMUTimer *ts)
+{
+ qemu_free_timer(ts);
+}
+
+/**
+ * timer_del:
+ * @ts: the timer
+ *
+ * Delete a timer from the active list.
+ */
+static inline void timer_del(QEMUTimer *ts)
+{
+ qemu_del_timer(ts);
+}
+
+/**
+ * timer_mod_ns:
+ * @ts: the timer
+ * @expire_time: the expiry time in nanoseconds
+ *
+ * Modify a timer to expire at @expire_time
+ */
+static inline void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
+{
+ qemu_mod_timer_ns(ts, expire_time);
+}
+
+/**
+ * timer_mod:
+ * @ts: the timer
+ * @expire_time: the expire time in the units associated with the timer
+ *
+ * Modify a timer to expiry at @expire_time, taking into
+ * account the scale associated with the timer.
+ */
+static inline void timer_mod(QEMUTimer *ts, int64_t expire_timer)
+{
+ qemu_mod_timer(ts, expire_timer);
+}
+
+/**
+ * timer_pending:
+ * @ts: the timer
+ *
+ * Determines whether a timer is pending (i.e. is on the
+ * active list of timers, whether or not it has not yet expired).
+ *
+ * Returns: true if the timer is pending
+ */
+static inline bool timer_pending(QEMUTimer *ts)
+{
+ return qemu_timer_pending(ts);
+}
+
+/**
+ * timer_expired:
+ * @ts: the timer
+ *
+ * Determines whether a timer has expired.
+ *
+ * Returns: true if the timer has expired
+ */
+static inline bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
+{
+ return qemu_timer_expired(timer_head, current_time);
+}
+
+/**
+ * timer_expire_time_ns:
+ * @ts: the timer
+ *
+ * Determine the expiry time of a timer
+ *
+ * Returns: the expiry time in nanoseconds
+ */
+static inline uint64_t timer_expire_time_ns(QEMUTimer *ts)
+{
+ return qemu_timer_expire_time_ns(ts);
+}
+
/**
* qemu_run_timers:
* @clock: clock on which to operate
*
- * Run all the timers associated with a clock.
+ * Run all the timers associated with the default timer list
+ * of a clock.
*
* Returns: true if any timer ran.
*/
@@ -123,7 +387,8 @@ bool qemu_run_timers(QEMUClock *clock);
/**
* qemu_run_all_timers:
*
- * Run all the timers associated with every clock.
+ * Run all the timers associated with the default timer list
+ * of every clock.
*
* Returns: true if any timer ran.
*/
@@ -156,18 +421,113 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
}
+/**
+ * qemu_new_timer_ns:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with nanosecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
void *opaque)
{
return qemu_new_timer(clock, SCALE_NS, cb, opaque);
}
-static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
+/**
+ * timer_new_ns:
+ * @timer_list: the timer list to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with nanosecond scale on the timer list
+ * specified.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_ns(QEMUTimerList *timer_list,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ return timer_new(timer_list, SCALE_NS, cb, opaque);
+}
+
+/**
+ * qemu_new_timer_us:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with microsecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *qemu_new_timer_us(QEMUClock *clock,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ return qemu_new_timer(clock, SCALE_US, cb, opaque);
+}
+
+/**
+ * timer_new_us:
+ * @timer_list: the timer list to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with microsecond scale on the timer list
+ * specified.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_us(QEMUTimerList *timer_list,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ return timer_new(timer_list, SCALE_US, cb, opaque);
+}
+
+/**
+ * qemu_new_timer_ms:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with millisecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock,
+ QEMUTimerCB *cb,
void *opaque)
{
return qemu_new_timer(clock, SCALE_MS, cb, opaque);
}
+/**
+ * timer_new_ms:
+ * @timer_list: the timer list to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with millisecond scale on the timer list
+ * specified.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_ms(QEMUTimerList *timer_list,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ return timer_new(timer_list, SCALE_MS, cb, opaque);
+}
+
static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
{
return qemu_get_clock_ns(clock) / SCALE_MS;
diff --git a/qemu-timer.c b/qemu-timer.c
index 388b98c..46f4029 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -49,18 +49,34 @@
/* timers */
struct QEMUClock {
- QEMUTimer *active_timers;
+ QEMUTimerList *default_timerlist;
+ QLIST_HEAD(, QEMUTimerList) timerlists;
NotifierList reset_notifiers;
int64_t last;
- int type;
+ QEMUClockType type;
bool enabled;
};
+QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
+
+/* A QEMUTimerList is a list of timers attached to a clock. More
+ * than one QEMUTimerList can be attached to each clock, for instance
+ * used by different AioContexts / threads. Each clock also has
+ * a list of the QEMUTimerLists associated with it, in order that
+ * reenabling the clock can call all the notifiers.
+ */
+
+struct QEMUTimerList {
+ QEMUClock *clock;
+ QEMUTimer *active_timers;
+ QLIST_ENTRY(QEMUTimerList) list;
+};
+
struct QEMUTimer {
int64_t expire_time; /* in nanoseconds */
- QEMUClock *clock;
+ QEMUTimerList *timer_list;
QEMUTimerCB *cb;
void *opaque;
QEMUTimer *next;
@@ -93,21 +109,25 @@ static int64_t qemu_next_alarm_deadline(void)
{
int64_t delta = INT64_MAX;
int64_t rtdelta;
+ int64_t hdelta;
- if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
- delta = vm_clock->active_timers->expire_time -
- qemu_get_clock_ns(vm_clock);
+ if (!use_icount && vm_clock->enabled &&
+ vm_clock->default_timerlist->active_timers) {
+ delta = vm_clock->default_timerlist->active_timers->expire_time -
+ qemu_get_clock_ns(vm_clock);
}
- if (host_clock->enabled && host_clock->active_timers) {
- int64_t hdelta = host_clock->active_timers->expire_time -
- qemu_get_clock_ns(host_clock);
+ if (host_clock->enabled &&
+ host_clock->default_timerlist->active_timers) {
+ hdelta = host_clock->default_timerlist->active_timers->expire_time -
+ qemu_get_clock_ns(host_clock);
if (hdelta < delta) {
delta = hdelta;
}
}
- if (rt_clock->enabled && rt_clock->active_timers) {
- rtdelta = (rt_clock->active_timers->expire_time -
- qemu_get_clock_ns(rt_clock));
+ if (rt_clock->enabled &&
+ rt_clock->default_timerlist->active_timers) {
+ rtdelta = (rt_clock->default_timerlist->active_timers->expire_time -
+ qemu_get_clock_ns(rt_clock));
if (rtdelta < delta) {
delta = rtdelta;
}
@@ -231,11 +251,42 @@ next:
}
}
-QEMUClock *rt_clock;
-QEMUClock *vm_clock;
-QEMUClock *host_clock;
+static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock)
+{
+ QEMUTimerList *timer_list;
+
+ /* Assert if we do not have a clock. If you see this
+ * assertion in means that the clocks have not been
+ * initialised before a timerlist is needed. This
+ * normally happens if an AioContext is used before
+ * init_clocks() is called within main().
+ */
+ assert(clock);
+
+ timer_list = g_malloc0(sizeof(QEMUTimerList));
+ timer_list->clock = clock;
+ QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
+ return timer_list;
+}
+
+QEMUTimerList *timerlist_new(QEMUClockType type)
+{
+ return timerlist_new_from_clock(qemu_get_clock(type));
+}
+
+void timerlist_free(QEMUTimerList *timer_list)
+{
+ assert(!timerlist_has_timers(timer_list));
+ if (timer_list->clock) {
+ QLIST_REMOVE(timer_list, list);
+ if (timer_list->clock->default_timerlist == timer_list) {
+ timer_list->clock->default_timerlist = NULL;
+ }
+ }
+ g_free(timer_list);
+}
-QEMUClock *qemu_clock_new(int type)
+QEMUClock *qemu_clock_new(QEMUClockType type)
{
QEMUClock *clock;
@@ -244,14 +295,21 @@ QEMUClock *qemu_clock_new(int type)
clock->enabled = true;
clock->last = INT64_MIN;
notifier_list_init(&clock->reset_notifiers);
+ clock->default_timerlist = timerlist_new_from_clock(clock);
return clock;
}
void qemu_clock_free(QEMUClock *clock)
{
+ timerlist_free(clock->default_timerlist);
g_free(clock);
}
+bool qemu_clock_use_for_deadline(QEMUClock *clock)
+{
+ return !(use_icount && (clock->type == QEMU_CLOCK_VIRTUAL));
+}
+
void qemu_clock_enable(QEMUClock *clock, bool enabled)
{
bool old = clock->enabled;
@@ -261,24 +319,36 @@ void qemu_clock_enable(QEMUClock *clock, bool enabled)
}
}
-int64_t qemu_clock_has_timers(QEMUClock *clock)
+bool timerlist_has_timers(QEMUTimerList *timer_list)
{
- return !!clock->active_timers;
+ return !!timer_list->active_timers;
}
-int64_t qemu_clock_expired(QEMUClock *clock)
+bool qemu_clock_has_timers(QEMUClock *clock)
{
- return (clock->active_timers &&
- clock->active_timers->expire_time < qemu_get_clock_ns(clock));
+ return timerlist_has_timers(clock->default_timerlist);
}
-int64_t qemu_clock_deadline(QEMUClock *clock)
+bool timerlist_expired(QEMUTimerList *timer_list)
+{
+ return (timer_list->active_timers &&
+ timer_list->active_timers->expire_time <
+ qemu_get_clock_ns(timer_list->clock));
+}
+
+bool qemu_clock_expired(QEMUClock *clock)
+{
+ return timerlist_expired(clock->default_timerlist);
+}
+
+int64_t timerlist_deadline(QEMUTimerList *timer_list)
{
/* To avoid problems with overflow limit this to 2^32. */
int64_t delta = INT32_MAX;
- if (clock->enabled && clock->active_timers) {
- delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+ if (timer_list->clock->enabled && timer_list->active_timers) {
+ delta = timer_list->active_timers->expire_time -
+ qemu_get_clock_ns(timer_list->clock);
}
if (delta < 0) {
delta = 0;
@@ -286,20 +356,26 @@ int64_t qemu_clock_deadline(QEMUClock *clock)
return delta;
}
+int64_t qemu_clock_deadline(QEMUClock *clock)
+{
+ return timerlist_deadline(clock->default_timerlist);
+}
+
/*
* As above, but return -1 for no deadline, and do not cap to 2^32
* as we know the result is always positive.
*/
-int64_t qemu_clock_deadline_ns(QEMUClock *clock)
+int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
{
int64_t delta;
- if (!clock->enabled || !clock->active_timers) {
+ if (!timer_list->clock->enabled || !timer_list->active_timers) {
return -1;
}
- delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+ delta = timer_list->active_timers->expire_time -
+ qemu_get_clock_ns(timer_list->clock);
if (delta <= 0) {
return 0;
@@ -308,6 +384,21 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock)
return delta;
}
+int64_t qemu_clock_deadline_ns(QEMUClock *clock)
+{
+ return timerlist_deadline_ns(clock->default_timerlist);
+}
+
+QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
+{
+ return timer_list->clock;
+}
+
+QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock)
+{
+ return clock->default_timerlist;
+}
+
/* Transition function to convert a nanosecond timeout to ms
* This is used where a system does not support ppoll
*/
@@ -356,19 +447,26 @@ int qemu_poll_ns(GPollFD *fds, uint nfds, int64_t timeout)
}
-QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
- QEMUTimerCB *cb, void *opaque)
+QEMUTimer *timer_new(QEMUTimerList *timer_list, int scale,
+ QEMUTimerCB *cb, void *opaque)
{
QEMUTimer *ts;
ts = g_malloc0(sizeof(QEMUTimer));
- ts->clock = clock;
+ ts->timer_list = timer_list;
ts->cb = cb;
ts->opaque = opaque;
ts->scale = scale;
return ts;
}
+QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ return timer_new(clock->default_timerlist,
+ scale, cb, opaque);
+}
+
void qemu_free_timer(QEMUTimer *ts)
{
g_free(ts);
@@ -381,7 +479,7 @@ void qemu_del_timer(QEMUTimer *ts)
/* NOTE: this code must be signal safe because
qemu_timer_expired() can be called from a signal. */
- pt = &ts->clock->active_timers;
+ pt = &ts->timer_list->active_timers;
for(;;) {
t = *pt;
if (!t)
@@ -405,7 +503,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
/* add the timer in the sorted list */
/* NOTE: this code must be signal safe because
qemu_timer_expired() can be called from a signal. */
- pt = &ts->clock->active_timers;
+ pt = &ts->timer_list->active_timers;
for(;;) {
t = *pt;
if (!qemu_timer_expired_ns(t, expire_time)) {
@@ -418,12 +516,12 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
*pt = ts;
/* Rearm if necessary */
- if (pt == &ts->clock->active_timers) {
+ if (pt == &ts->timer_list->active_timers) {
if (!alarm_timer->pending) {
qemu_rearm_alarm_timer(alarm_timer);
}
/* Interrupt execution to force deadline recalculation. */
- qemu_clock_warp(ts->clock);
+ qemu_clock_warp(ts->timer_list->clock);
if (use_icount) {
qemu_notify_event();
}
@@ -438,7 +536,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
bool qemu_timer_pending(QEMUTimer *ts)
{
QEMUTimer *t;
- for (t = ts->clock->active_timers; t != NULL; t = t->next) {
+ for (t = ts->timer_list->active_timers; t != NULL; t = t->next) {
if (t == ts) {
return true;
}
@@ -451,23 +549,24 @@ bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
}
-bool qemu_run_timers(QEMUClock *clock)
+bool timerlist_run_timers(QEMUTimerList *timer_list)
{
QEMUTimer *ts;
int64_t current_time;
bool progress = false;
- if (!clock->enabled)
+ if (!timer_list->clock->enabled) {
return progress;
+ }
- current_time = qemu_get_clock_ns(clock);
+ current_time = qemu_get_clock_ns(timer_list->clock);
for(;;) {
- ts = clock->active_timers;
+ ts = timer_list->active_timers;
if (!qemu_timer_expired_ns(ts, current_time)) {
break;
}
/* remove timer from the list before calling the callback */
- clock->active_timers = ts->next;
+ timer_list->active_timers = ts->next;
ts->next = NULL;
/* run the callback (the timer list can be modified) */
@@ -477,6 +576,11 @@ bool qemu_run_timers(QEMUClock *clock)
return progress;
}
+bool qemu_run_timers(QEMUClock *clock)
+{
+ return timerlist_run_timers(clock->default_timerlist);
+}
+
int64_t qemu_get_clock_ns(QEMUClock *clock)
{
int64_t now, last;
@@ -514,11 +618,13 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
void init_clocks(void)
{
- if (!rt_clock) {
- rt_clock = qemu_clock_new(QEMU_CLOCK_REALTIME);
- vm_clock = qemu_clock_new(QEMU_CLOCK_VIRTUAL);
- host_clock = qemu_clock_new(QEMU_CLOCK_HOST);
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ if (!qemu_clocks[type]) {
+ qemu_clocks[type] = qemu_clock_new(type);
+ }
}
+
#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
#endif
@@ -535,9 +641,10 @@ bool qemu_run_all_timers(void)
alarm_timer->pending = false;
/* vm time timers */
- progress |= qemu_run_timers(vm_clock);
- progress |= qemu_run_timers(rt_clock);
- progress |= qemu_run_timers(host_clock);
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ progress |= qemu_run_timers(qemu_get_clock(type));
+ }
/* rearm timer, if not periodic */
if (alarm_timer->expired) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 08/22] aio / timers: Untangle include files
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (6 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 09/22] aio / timers: Add QEMUTimerListGroup and helper functions Alex Bligh
` (14 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
include/qemu/timer.h has no need to include main-loop.h and
doing so causes an issue for the next patch. Unfortunately
various files assume including timers.h will pull in main-loop.h.
Untangle this mess.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
dma-helpers.c | 1 +
hw/dma/xilinx_axidma.c | 1 +
hw/timer/arm_timer.c | 1 +
hw/timer/exynos4210_mct.c | 1 +
hw/timer/exynos4210_pwm.c | 1 +
hw/timer/grlib_gptimer.c | 2 ++
hw/timer/imx_epit.c | 1 +
hw/timer/imx_gpt.c | 1 +
hw/timer/lm32_timer.c | 1 +
hw/timer/puv3_ost.c | 1 +
hw/timer/sh_timer.c | 1 +
hw/timer/slavio_timer.c | 1 +
hw/timer/xilinx_timer.c | 1 +
hw/tpm/tpm_tis.c | 1 +
hw/usb/hcd-uhci.c | 1 +
include/block/block_int.h | 1 +
include/block/coroutine.h | 2 ++
include/qemu/timer.h | 1 -
migration-exec.c | 1 +
migration-fd.c | 1 +
migration-tcp.c | 1 +
migration-unix.c | 1 +
migration.c | 1 +
nbd.c | 1 +
net/net.c | 1 +
net/socket.c | 1 +
qemu-coroutine-io.c | 1 +
qemu-io-cmds.c | 1 +
qemu-nbd.c | 1 +
slirp/misc.c | 1 +
thread-pool.c | 1 +
ui/vnc-auth-sasl.h | 1 +
ui/vnc-auth-vencrypt.c | 2 +-
ui/vnc-ws.c | 1 +
34 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/dma-helpers.c b/dma-helpers.c
index 499550f..c9620a5 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -11,6 +11,7 @@
#include "trace.h"
#include "qemu/range.h"
#include "qemu/thread.h"
+#include "qemu/main-loop.h"
/* #define DEBUG_IOMMU */
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index a48e3ba..59e8e35 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -27,6 +27,7 @@
#include "hw/ptimer.h"
#include "qemu/log.h"
#include "qapi/qmp/qerror.h"
+#include "qemu/main-loop.h"
#include "hw/stream.h"
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index acfea59..a47afde 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -12,6 +12,7 @@
#include "qemu-common.h"
#include "hw/qdev.h"
#include "hw/ptimer.h"
+#include "qemu/main-loop.h"
/* Common timer implementation. */
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index a8009a4..13b1889 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -54,6 +54,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "qemu-common.h"
#include "hw/ptimer.h"
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index a52f0f6..1aa8f4d 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -23,6 +23,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "hw/ptimer.h"
#include "hw/arm/exynos4210.h"
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 7c1055a..74c16d6 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -25,6 +25,8 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
+#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "trace.h"
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 117dc7b..efe2ff9 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -18,6 +18,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "qemu/main-loop.h"
#define TYPE_IMX_EPIT "imx.epit"
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 87db0e1..f2d1975 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -18,6 +18,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "qemu/main-loop.h"
#define TYPE_IMX_GPT "imx.gpt"
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index 986e6a1..8ed138c 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -27,6 +27,7 @@
#include "qemu/timer.h"
#include "hw/ptimer.h"
#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
#define DEFAULT_FREQUENCY (50*1000000)
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 4bd2b76..fa9eefd 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -10,6 +10,7 @@
*/
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "qemu/main-loop.h"
#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 251a10d..07f0670 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -11,6 +11,7 @@
#include "hw/hw.h"
#include "hw/sh4/sh.h"
#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "exec/address-spaces.h"
#include "hw/ptimer.h"
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 33e8f6c..f75b914 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -27,6 +27,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "trace.h"
+#include "qemu/main-loop.h"
/*
* Registers of hardware timer in sun4m.
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 5f2c902..6113b97 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -25,6 +25,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "qemu/log.h"
+#include "qemu/main-loop.h"
#define D(x)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index abe384b..6f0a4d2 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -28,6 +28,7 @@
#include "hw/pci/pci_ids.h"
#include "tpm_tis.h"
#include "qemu-common.h"
+#include "qemu/main-loop.h"
/*#define DEBUG_TIS */
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index ac82833..ec51883 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -32,6 +32,7 @@
#include "qemu/iov.h"
#include "sysemu/dma.h"
#include "trace.h"
+#include "qemu/main-loop.h"
//#define DEBUG
//#define DEBUG_DUMP_DATA
diff --git a/include/block/block_int.h b/include/block/block_int.h
index e45f2a0..3d798ce 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -34,6 +34,7 @@
#include "monitor/monitor.h"
#include "qemu/hbitmap.h"
#include "block/snapshot.h"
+#include "qemu/main-loop.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPAT6 4
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index 1f2db3e..9197bfb 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -19,6 +19,8 @@
#include "qemu/queue.h"
#include "qemu/timer.h"
+typedef struct AioContext AioContext;
+
/**
* Coroutines are a mechanism for stack switching and can be used for
* cooperative userspace threading. These functions provide a simple but
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index eb2b99e..0dbb982 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -2,7 +2,6 @@
#define QEMU_TIMER_H
#include "qemu-common.h"
-#include "qemu/main-loop.h"
#include "qemu/notify.h"
/* timers */
diff --git a/migration-exec.c b/migration-exec.c
index deab4e3..4790247 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -17,6 +17,7 @@
#include "qemu-common.h"
#include "qemu/sockets.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
diff --git a/migration-fd.c b/migration-fd.c
index 3d4613c..d2e523a 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -14,6 +14,7 @@
*/
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "migration/migration.h"
#include "monitor/monitor.h"
diff --git a/migration-tcp.c b/migration-tcp.c
index b20ee58..782572d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -18,6 +18,7 @@
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
+#include "qemu/main-loop.h"
//#define DEBUG_MIGRATION_TCP
diff --git a/migration-unix.c b/migration-unix.c
index 94b7022..651fc5b 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -15,6 +15,7 @@
#include "qemu-common.h"
#include "qemu/sockets.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
diff --git a/migration.c b/migration.c
index 1402fa7..ac200ed 100644
--- a/migration.c
+++ b/migration.c
@@ -14,6 +14,7 @@
*/
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "monitor/monitor.h"
#include "migration/qemu-file.h"
diff --git a/nbd.c b/nbd.c
index 2606403..0fd0583 100644
--- a/nbd.c
+++ b/nbd.c
@@ -38,6 +38,7 @@
#include "qemu/sockets.h"
#include "qemu/queue.h"
+#include "qemu/main-loop.h"
//#define DEBUG_NBD
diff --git a/net/net.c b/net/net.c
index c0d61bf..1148592 100644
--- a/net/net.c
+++ b/net/net.c
@@ -36,6 +36,7 @@
#include "qmp-commands.h"
#include "hw/qdev.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
diff --git a/net/socket.c b/net/socket.c
index 87af1d3..e61309d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -31,6 +31,7 @@
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
typedef struct NetSocketState {
NetClientState nc;
diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c
index c4df35a..054ca70 100644
--- a/qemu-coroutine-io.c
+++ b/qemu-coroutine-io.c
@@ -26,6 +26,7 @@
#include "qemu/sockets.h"
#include "block/coroutine.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
ssize_t coroutine_fn
qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index ffbcf31..f91b6c4 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -10,6 +10,7 @@
#include "qemu-io.h"
#include "block/block_int.h"
+#include "qemu/main-loop.h"
#define CMD_NOFILE_OK 0x01
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 9c31d45..f044546 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -19,6 +19,7 @@
#include "qemu-common.h"
#include "block/block.h"
#include "block/nbd.h"
+#include "qemu/main-loop.h"
#include <stdarg.h>
#include <stdio.h>
diff --git a/slirp/misc.c b/slirp/misc.c
index 0bcc481..c0d4899 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -9,6 +9,7 @@
#include <libslirp.h>
#include "monitor/monitor.h"
+#include "qemu/main-loop.h"
#ifdef DEBUG
int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
diff --git a/thread-pool.c b/thread-pool.c
index 0ebd4c2..25bfa41 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -23,6 +23,7 @@
#include "block/block_int.h"
#include "qemu/event_notifier.h"
#include "block/thread-pool.h"
+#include "qemu/main-loop.h"
static void do_spawn_thread(ThreadPool *pool);
diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h
index 8091d68..3f59da6 100644
--- a/ui/vnc-auth-sasl.h
+++ b/ui/vnc-auth-sasl.h
@@ -33,6 +33,7 @@ typedef struct VncStateSASL VncStateSASL;
typedef struct VncDisplaySASL VncDisplaySASL;
#include "qemu/acl.h"
+#include "qemu/main-loop.h"
struct VncStateSASL {
sasl_conn_t *conn;
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index c59b188..bc7032e 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -25,7 +25,7 @@
*/
#include "vnc.h"
-
+#include "qemu/main-loop.h"
static void start_auth_vencrypt_subauth(VncState *vs)
{
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index df89315..e304baf 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -19,6 +19,7 @@
*/
#include "vnc.h"
+#include "qemu/main-loop.h"
#ifdef CONFIG_VNC_TLS
#include "qemu/sockets.h"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 09/22] aio / timers: Add QEMUTimerListGroup and helper functions
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (7 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 08/22] aio / timers: Untangle include files Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 10/22] aio / timers: Add QEMUTimerListGroup to AioContext Alex Bligh
` (13 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add QEMUTimerListGroup and helper functions, to represent
a QEMUTimerList associated with each clock. Add a default
QEMUTimerListGroup representing the default timer lists
which are not associated with any other object (e.g.
an AioContext as added by future patches).
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
qemu-timer.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 0dbb982..bc258ec 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -52,8 +52,10 @@ typedef enum {
typedef struct QEMUClock QEMUClock;
typedef struct QEMUTimerList QEMUTimerList;
+typedef QEMUTimerList *QEMUTimerListGroup[QEMU_CLOCK_MAX];
typedef void QEMUTimerCB(void *opaque);
+extern QEMUTimerListGroup main_loop_tlg;
extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
/**
@@ -229,6 +231,49 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
bool timerlist_run_timers(QEMUTimerList *timer_list);
/**
+ * timerlistgroup_init:
+ * @tlg: the timer list group
+ *
+ * Initialise a timer list group. This must already be
+ * allocated in memory and zeroed.
+ */
+void timerlistgroup_init(QEMUTimerListGroup tlg);
+
+/**
+ * timerlistgroup_deinit:
+ * @tlg: the timer list group
+ *
+ * Deinitialise a timer list group. This must already be
+ * initialised. Note the memory is not freed.
+ */
+void timerlistgroup_deinit(QEMUTimerListGroup tlg);
+
+/**
+ * timerlistgroup_run_timers:
+ * @tlg: the timer list group
+ *
+ * Run the timers associated with a timer list group.
+ * This will run timers on multiple clocks.
+ *
+ * Returns: true if any timer callback ran
+ */
+bool timerlistgroup_run_timers(QEMUTimerListGroup tlg);
+
+/**
+ * timerlistgroup_deadline_ns
+ * @tlg: the timer list group
+ *
+ * Determine the deadline of the soonest timer to
+ * expire associated with any timer list linked to
+ * the timer list group. Only clocks suitable for
+ * deadline calculation are included.
+ *
+ * Returns: the deadline in nanoseconds or -1 if no
+ * timers are to expire.
+ */
+int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup tlg);
+
+/**
* qemu_timeout_ns_to_ms:
* @ns: nanosecond timeout value
*
diff --git a/qemu-timer.c b/qemu-timer.c
index 46f4029..5c55c1a 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -59,6 +59,7 @@ struct QEMUClock {
bool enabled;
};
+QEMUTimerListGroup main_loop_tlg;
QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
/* A QEMUTimerList is a list of timers attached to a clock. More
@@ -581,6 +582,45 @@ bool qemu_run_timers(QEMUClock *clock)
return timerlist_run_timers(clock->default_timerlist);
}
+void timerlistgroup_init(QEMUTimerListGroup tlg)
+{
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ tlg[type] = timerlist_new(type);
+ }
+}
+
+void timerlistgroup_deinit(QEMUTimerListGroup tlg)
+{
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ timerlist_free(tlg[type]);
+ }
+}
+
+bool timerlistgroup_run_timers(QEMUTimerListGroup tlg)
+{
+ QEMUClockType type;
+ bool progress = false;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ progress |= timerlist_run_timers(tlg[type]);
+ }
+ return progress;
+}
+
+int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup tlg)
+{
+ int64_t deadline = -1;
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ if (qemu_clock_use_for_deadline(tlg[type]->clock)) {
+ deadline = qemu_soonest_timeout(deadline,
+ timerlist_deadline_ns(tlg[type]));
+ }
+ }
+ return deadline;
+}
+
int64_t qemu_get_clock_ns(QEMUClock *clock)
{
int64_t now, last;
@@ -622,6 +662,7 @@ void init_clocks(void)
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
if (!qemu_clocks[type]) {
qemu_clocks[type] = qemu_clock_new(type);
+ main_loop_tlg[type] = qemu_clocks[type]->default_timerlist;
}
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 10/22] aio / timers: Add QEMUTimerListGroup to AioContext
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (8 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 09/22] aio / timers: Add QEMUTimerListGroup and helper functions Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 11/22] aio / timers: Add a notify callback to QEMUTimerList Alex Bligh
` (12 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add a QEMUTimerListGroup each AioContext (meaning a QEMUTimerList
associated with each clock is added) and delete it when the
AioContext is freed.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
async.c | 2 ++
include/block/aio.h | 4 ++++
tests/test-aio.c | 3 +++
tests/test-thread-pool.c | 3 +++
4 files changed, 12 insertions(+)
diff --git a/async.c b/async.c
index 5ce3633..99fb5a8 100644
--- a/async.c
+++ b/async.c
@@ -205,6 +205,7 @@ aio_ctx_finalize(GSource *source)
event_notifier_cleanup(&ctx->notifier);
qemu_mutex_destroy(&ctx->bh_lock);
g_array_free(ctx->pollfds, TRUE);
+ timerlistgroup_deinit(ctx->tlg);
}
static GSourceFuncs aio_source_funcs = {
@@ -244,6 +245,7 @@ AioContext *aio_context_new(void)
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
event_notifier_test_and_clear, NULL);
+ timerlistgroup_init(ctx->tlg);
return ctx;
}
diff --git a/include/block/aio.h b/include/block/aio.h
index cc77771..a13f6e8 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -18,6 +18,7 @@
#include "qemu/queue.h"
#include "qemu/event_notifier.h"
#include "qemu/thread.h"
+#include "qemu/timer.h"
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
@@ -72,6 +73,9 @@ typedef struct AioContext {
/* Thread pool for performing work and receiving completion callbacks */
struct ThreadPool *thread_pool;
+
+ /* TimerLists for calling timers - one per clock type */
+ QEMUTimerListGroup tlg;
} AioContext;
/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
diff --git a/tests/test-aio.c b/tests/test-aio.c
index c173870..2d7ec4c 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -12,6 +12,7 @@
#include <glib.h>
#include "block/aio.h"
+#include "qemu/timer.h"
AioContext *ctx;
@@ -628,6 +629,8 @@ int main(int argc, char **argv)
{
GSource *src;
+ init_clocks();
+
ctx = aio_context_new();
src = aio_get_g_source(ctx);
g_source_attach(src, NULL);
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index b62338f..27d6190 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -3,6 +3,7 @@
#include "block/aio.h"
#include "block/thread-pool.h"
#include "block/block.h"
+#include "qemu/timer.h"
static AioContext *ctx;
static ThreadPool *pool;
@@ -205,6 +206,8 @@ int main(int argc, char **argv)
{
int ret;
+ init_clocks();
+
ctx = aio_context_new();
pool = aio_get_thread_pool(ctx);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 11/22] aio / timers: Add a notify callback to QEMUTimerList
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (9 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 10/22] aio / timers: Add QEMUTimerListGroup to AioContext Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 12/22] aio / timers: aio_ctx_prepare sets timeout from AioContext timers Alex Bligh
` (11 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add a notify pointer to QEMUTimerList so it knows what to notify
on a timer change.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
async.c | 7 ++++++-
include/qemu/timer.h | 35 ++++++++++++++++++++++++++++++++---
qemu-timer.c | 24 ++++++++++++++++++++++--
3 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/async.c b/async.c
index 99fb5a8..2051921 100644
--- a/async.c
+++ b/async.c
@@ -234,6 +234,11 @@ void aio_notify(AioContext *ctx)
event_notifier_set(&ctx->notifier);
}
+static void aio_timerlist_notify(void *opaque)
+{
+ aio_notify(opaque);
+}
+
AioContext *aio_context_new(void)
{
AioContext *ctx;
@@ -245,7 +250,7 @@ AioContext *aio_context_new(void)
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
event_notifier_test_and_clear, NULL);
- timerlistgroup_init(ctx->tlg);
+ timerlistgroup_init(ctx->tlg, aio_timerlist_notify, ctx);
return ctx;
}
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index bc258ec..a866812 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -54,6 +54,7 @@ typedef struct QEMUClock QEMUClock;
typedef struct QEMUTimerList QEMUTimerList;
typedef QEMUTimerList *QEMUTimerListGroup[QEMU_CLOCK_MAX];
typedef void QEMUTimerCB(void *opaque);
+typedef void QEMUTimerListNotifyCB(void *opaque);
extern QEMUTimerListGroup main_loop_tlg;
extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
@@ -231,13 +232,41 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
bool timerlist_run_timers(QEMUTimerList *timer_list);
/**
+ * timerlist_set_notify_cb:
+ * @timer_list: the timer list to use
+ * @cb: the callback to call on notification
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Set the notify callback for a timer list. The notifier
+ * callback is called when the clock is reenabled or a timer
+ * on the list is modified.
+ */
+void timerlist_set_notify_cb(QEMUTimerList *timer_list,
+ QEMUTimerListNotifyCB *cb, void *opaque);
+
+/**
+ * timerlist_notify:
+ * @timer_list: the timer list to use
+ *
+ * call the notifier callback associated with the timer list.
+ */
+void timerlist_notify(QEMUTimerList *timer_list);
+
+/**
* timerlistgroup_init:
* @tlg: the timer list group
+ * @cb: the callback to call when a notify is required
+ * @opaque: the opaque pointer to be passed to the callback.
*
* Initialise a timer list group. This must already be
- * allocated in memory and zeroed.
- */
-void timerlistgroup_init(QEMUTimerListGroup tlg);
+ * allocated in memory and zeroed. The notifier callback is
+ * called whenever a clock in the timer list group is
+ * reenabled or whenever a timer associated with any timer
+ * list is modified. If @cb is specified as null, qemu_notify()
+ * is used instead.
+ */
+void timerlistgroup_init(QEMUTimerListGroup tlg,
+ QEMUTimerListNotifyCB *cb, void *opaque);
/**
* timerlistgroup_deinit:
diff --git a/qemu-timer.c b/qemu-timer.c
index 5c55c1a..59abffc 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -73,6 +73,8 @@ struct QEMUTimerList {
QEMUClock *clock;
QEMUTimer *active_timers;
QLIST_ENTRY(QEMUTimerList) list;
+ QEMUTimerListNotifyCB *notify_cb;
+ void *notify_opaque;
};
struct QEMUTimer {
@@ -400,6 +402,22 @@ QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock)
return clock->default_timerlist;
}
+void timerlist_set_notify_cb(QEMUTimerList *timer_list,
+ QEMUTimerListNotifyCB *cb, void *opaque)
+{
+ timer_list->notify_cb = cb;
+ timer_list->notify_opaque = opaque;
+}
+
+void timerlist_notify(QEMUTimerList *timer_list)
+{
+ if (timer_list->notify_cb) {
+ timer_list->notify_cb(timer_list->notify_opaque);
+ } else {
+ qemu_notify_event();
+ }
+}
+
/* Transition function to convert a nanosecond timeout to ms
* This is used where a system does not support ppoll
*/
@@ -524,7 +542,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
/* Interrupt execution to force deadline recalculation. */
qemu_clock_warp(ts->timer_list->clock);
if (use_icount) {
- qemu_notify_event();
+ timerlist_notify(ts->timer_list);
}
}
}
@@ -582,11 +600,13 @@ bool qemu_run_timers(QEMUClock *clock)
return timerlist_run_timers(clock->default_timerlist);
}
-void timerlistgroup_init(QEMUTimerListGroup tlg)
+void timerlistgroup_init(QEMUTimerListGroup tlg,
+ QEMUTimerListNotifyCB *cb, void *opaque)
{
QEMUClockType type;
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
tlg[type] = timerlist_new(type);
+ timerlist_set_notify_cb(tlg[type], cb, opaque);
}
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 12/22] aio / timers: aio_ctx_prepare sets timeout from AioContext timers
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (10 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 11/22] aio / timers: Add a notify callback to QEMUTimerList Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 13/22] aio / timers: Add aio_timer_new wrapper Alex Bligh
` (10 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Calculate the timeout in aio_ctx_prepare taking into account
the timers attached to the AioContext.
Alter aio_ctx_check similarly.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
async.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/async.c b/async.c
index 2051921..dd27459 100644
--- a/async.c
+++ b/async.c
@@ -150,13 +150,14 @@ aio_ctx_prepare(GSource *source, gint *timeout)
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
+ int deadline;
for (bh = ctx->first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
if (bh->idle) {
/* idle bottom halves will be polled at least
* every 10ms */
- *timeout = 10;
+ *timeout = qemu_soonest_timeout(*timeout, 10);
} else {
/* non-idle bottom halves will be executed
* immediately */
@@ -166,6 +167,14 @@ aio_ctx_prepare(GSource *source, gint *timeout)
}
}
+ deadline = qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(ctx->tlg));
+ if (deadline == 0) {
+ *timeout = 0;
+ return true;
+ } else {
+ *timeout = qemu_soonest_timeout(*timeout, deadline);
+ }
+
return false;
}
@@ -180,7 +189,7 @@ aio_ctx_check(GSource *source)
return true;
}
}
- return aio_pending(ctx);
+ return aio_pending(ctx) || (timerlistgroup_deadline_ns(ctx->tlg) == 0);
}
static gboolean
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 13/22] aio / timers: Add aio_timer_new wrapper
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (11 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 12/22] aio / timers: aio_ctx_prepare sets timeout from AioContext timers Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 14/22] aio / timers: Convert aio_poll to use AioContext timers' deadline Alex Bligh
` (9 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add aio_timer_new wrapper function.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/block/aio.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/include/block/aio.h b/include/block/aio.h
index a13f6e8..bd6f17c 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -255,4 +255,23 @@ void qemu_aio_set_fd_handler(int fd,
void *opaque);
#endif
+/**
+ * aio_timer_new:
+ * @ctx: the aio context
+ * @type: the clock type
+ * @scale: the scale
+ * @cb: the callback to call on timer expiry
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Generate a new timer attached to the context @ctx.
+ *
+ * Returns: a pointer to the new timer
+ */
+static inline QEMUTimer *aio_timer_new(AioContext *ctx, QEMUClockType type,
+ int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ return timer_new(ctx->tlg[type], scale, cb, opaque);
+}
+
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 14/22] aio / timers: Convert aio_poll to use AioContext timers' deadline
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (12 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 13/22] aio / timers: Add aio_timer_new wrapper Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 15/22] aio / timers: Convert mainloop to use timeout Alex Bligh
` (8 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Convert aio_poll to use deadline based on AioContext's timers.
aio_poll has been changed to return accurately whether progress
has occurred. Prior to this commit, aio_poll always returned
true if g_poll was entered, whether or not any progress was
made. This required a change to tests/test-aio.c where an
assert was backwards.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
aio-posix.c | 20 +++++++++++++-------
aio-win32.c | 22 +++++++++++++++++++---
tests/test-aio.c | 4 ++--
3 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/aio-posix.c b/aio-posix.c
index b68eccd..2ec419d 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -166,6 +166,10 @@ static bool aio_dispatch(AioContext *ctx)
g_free(tmp);
}
}
+
+ /* Run our timers */
+ progress |= timerlistgroup_run_timers(ctx->tlg);
+
return progress;
}
@@ -232,9 +236,9 @@ bool aio_poll(AioContext *ctx, bool blocking)
}
/* wait until next event */
- ret = g_poll((GPollFD *)ctx->pollfds->data,
- ctx->pollfds->len,
- blocking ? -1 : 0);
+ ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data,
+ ctx->pollfds->len,
+ blocking ? timerlistgroup_deadline_ns(ctx->tlg) : 0);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
@@ -245,11 +249,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
node->pfd.revents = pfd->revents;
}
}
- if (aio_dispatch(ctx)) {
- progress = true;
- }
+ }
+
+ /* Run dispatch even if there were no readable fds to run timers */
+ if (aio_dispatch(ctx)) {
+ progress = true;
}
assert(progress || busy);
- return true;
+ return progress;
}
diff --git a/aio-win32.c b/aio-win32.c
index 38723bf..90b232b 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -98,6 +98,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
bool busy, progress;
int count;
+ int timeout;
progress = false;
@@ -111,6 +112,9 @@ bool aio_poll(AioContext *ctx, bool blocking)
progress = true;
}
+ /* Run timers */
+ progress |= timerlistgroup_run_timers(ctx->tlg);
+
/*
* Then dispatch any pending callbacks from the GSource.
*
@@ -174,8 +178,11 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* wait until next event */
while (count > 0) {
- int timeout = blocking ? INFINITE : 0;
- int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
+ int ret;
+
+ timeout = blocking ?
+ qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(ctx->tlg)) : 0;
+ ret = WaitForMultipleObjects(count, events, FALSE, timeout);
/* if we have any signaled events, dispatch event */
if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
@@ -214,6 +221,15 @@ bool aio_poll(AioContext *ctx, bool blocking)
events[ret - WAIT_OBJECT_0] = events[--count];
}
+ if (blocking) {
+ /* Run the timers a second time. We do this because otherwise aio_wait
+ * will not note progress - and will stop a drain early - if we have
+ * a timer that was not ready to run entering g_poll but is ready
+ * after g_poll. This will only do anything if a timer has expired.
+ */
+ progress |= timerlistgroup_run_timers(ctx->timer_list);
+ }
+
assert(progress || busy);
- return true;
+ return progress;
}
diff --git a/tests/test-aio.c b/tests/test-aio.c
index 2d7ec4c..eedf7f8 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -316,13 +316,13 @@ static void test_wait_event_notifier_noflush(void)
event_notifier_set(&data.e);
g_assert(aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
- g_assert(aio_poll(ctx, false));
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
event_notifier_set(&data.e);
g_assert(aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
- g_assert(aio_poll(ctx, false));
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
event_notifier_set(&dummy.e);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 15/22] aio / timers: Convert mainloop to use timeout
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (13 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 14/22] aio / timers: Convert aio_poll to use AioContext timers' deadline Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 16/22] aio / timers: On timer modification, qemu_notify or aio_notify Alex Bligh
` (7 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Convert mainloop to use timeout from default timerlist group
(i.e. the current 3 static timers)
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
main-loop.c | 45 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/main-loop.c b/main-loop.c
index a44fff6..00e54bd 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -155,10 +155,11 @@ static int max_priority;
static int glib_pollfds_idx;
static int glib_n_poll_fds;
-static void glib_pollfds_fill(uint32_t *cur_timeout)
+static void glib_pollfds_fill(int64_t *cur_timeout)
{
GMainContext *context = g_main_context_default();
int timeout = 0;
+ int64_t timeout_ns;
int n;
g_main_context_prepare(context, &max_priority);
@@ -174,9 +175,13 @@ static void glib_pollfds_fill(uint32_t *cur_timeout)
glib_n_poll_fds);
} while (n != glib_n_poll_fds);
- if (timeout >= 0 && timeout < *cur_timeout) {
- *cur_timeout = timeout;
+ if (timeout < 0) {
+ timeout_ns = -1;
+ } else {
+ timeout_ns = (int64_t)timeout * (int64_t)SCALE_MS;
}
+
+ *cur_timeout = qemu_soonest_timeout(timeout_ns, *cur_timeout);
}
static void glib_pollfds_poll(void)
@@ -191,7 +196,7 @@ static void glib_pollfds_poll(void)
#define MAX_MAIN_LOOP_SPIN (1000)
-static int os_host_main_loop_wait(uint32_t timeout)
+static int os_host_main_loop_wait(int64_t timeout)
{
int ret;
static int spin_counter;
@@ -214,7 +219,7 @@ static int os_host_main_loop_wait(uint32_t timeout)
notified = true;
}
- timeout = 1;
+ timeout = SCALE_MS;
}
if (timeout > 0) {
@@ -224,7 +229,7 @@ static int os_host_main_loop_wait(uint32_t timeout)
spin_counter++;
}
- ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
+ ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout);
if (timeout > 0) {
qemu_mutex_lock_iothread();
@@ -373,7 +378,7 @@ static void pollfds_poll(GArray *pollfds, int nfds, fd_set *rfds,
}
}
-static int os_host_main_loop_wait(uint32_t timeout)
+static int os_host_main_loop_wait(int64_t timeout)
{
GMainContext *context = g_main_context_default();
GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
@@ -382,6 +387,7 @@ static int os_host_main_loop_wait(uint32_t timeout)
PollingEntry *pe;
WaitObjects *w = &wait_objects;
gint poll_timeout;
+ int64_t poll_timeout_ns;
static struct timeval tv0;
fd_set rfds, wfds, xfds;
int nfds;
@@ -419,12 +425,17 @@ static int os_host_main_loop_wait(uint32_t timeout)
poll_fds[n_poll_fds + i].events = G_IO_IN;
}
- if (poll_timeout < 0 || timeout < poll_timeout) {
- poll_timeout = timeout;
+ if (poll_timeout < 0) {
+ poll_timeout_ns = -1;
+ } else {
+ poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS;
}
+ poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout);
+
qemu_mutex_unlock_iothread();
- g_poll_ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
+ g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns);
+
qemu_mutex_lock_iothread();
if (g_poll_ret > 0) {
for (i = 0; i < w->num; i++) {
@@ -449,6 +460,7 @@ int main_loop_wait(int nonblocking)
{
int ret;
uint32_t timeout = UINT32_MAX;
+ int64_t timeout_ns;
if (nonblocking) {
timeout = 0;
@@ -462,7 +474,18 @@ int main_loop_wait(int nonblocking)
slirp_pollfds_fill(gpollfds);
#endif
qemu_iohandler_fill(gpollfds);
- ret = os_host_main_loop_wait(timeout);
+
+ if (timeout == UINT32_MAX) {
+ timeout_ns = -1;
+ } else {
+ timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS);
+ }
+
+ timeout_ns = qemu_soonest_timeout(timeout_ns,
+ timerlistgroup_deadline_ns(
+ main_loop_tlg));
+
+ ret = os_host_main_loop_wait(timeout_ns);
qemu_iohandler_poll(gpollfds, ret);
#ifdef CONFIG_SLIRP
slirp_pollfds_poll(gpollfds, (ret < 0));
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 16/22] aio / timers: On timer modification, qemu_notify or aio_notify
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (14 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 15/22] aio / timers: Convert mainloop to use timeout Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 17/22] aio / timers: Introduce new API qemu_timer_new and friends Alex Bligh
` (6 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
On qemu_mod_timer_ns, ensure qemu_notify or aio_notify is called to
end the appropriate poll(), irrespective of use_icount value.
On qemu_clock_enable, ensure qemu_notify or aio_notify is called for
all QEMUTimerLists attached to the QEMUClock.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 9 +++++++++
qemu-timer.c | 13 ++++++++++---
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index a866812..ddcd05a 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -140,6 +140,15 @@ bool qemu_clock_use_for_deadline(QEMUClock *clock);
QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock);
/**
+ * qemu_clock_nofify:
+ * @clock: the clock to operate on
+ *
+ * Call the notifier callback connected with the default timer
+ * list linked to the clock, or qemu_notify() if none.
+ */
+void qemu_clock_notify(QEMUClock *clock);
+
+/**
* timerlist_new:
* @type: the clock type to associate with the timerlist
*
diff --git a/qemu-timer.c b/qemu-timer.c
index 59abffc..bb45834 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -313,11 +313,20 @@ bool qemu_clock_use_for_deadline(QEMUClock *clock)
return !(use_icount && (clock->type == QEMU_CLOCK_VIRTUAL));
}
+void qemu_clock_notify(QEMUClock *clock)
+{
+ QEMUTimerList *timer_list;
+ QLIST_FOREACH(timer_list, &clock->timerlists, list) {
+ timerlist_notify(timer_list);
+ }
+}
+
void qemu_clock_enable(QEMUClock *clock, bool enabled)
{
bool old = clock->enabled;
clock->enabled = enabled;
if (enabled && !old) {
+ qemu_clock_notify(clock);
qemu_rearm_alarm_timer(alarm_timer);
}
}
@@ -541,9 +550,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
}
/* Interrupt execution to force deadline recalculation. */
qemu_clock_warp(ts->timer_list->clock);
- if (use_icount) {
- timerlist_notify(ts->timer_list);
- }
+ timerlist_notify(ts->timer_list);
}
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 17/22] aio / timers: Introduce new API qemu_timer_new and friends
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (15 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 16/22] aio / timers: On timer modification, qemu_notify or aio_notify Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 18/22] aio / timers: Use all timerlists in icount warp calculations Alex Bligh
` (5 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Introduce new API for creating timers - qemu_timer_new and
_ns, _ms, _us derivatives.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index ddcd05a..ca26b6f 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -358,6 +358,24 @@ QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimer *timer_new(QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque);
+/**
+ * qemu_timer_new:
+ * @type: the clock type to use
+ * @scale: the scale value for the tiemr
+ * @cb: the callback to be called when the timer expires
+ * @opaque: the opaque pointer to be passed to the callback
+ *
+ * Creeate a new timer and associate it with the default
+ * timer list for the clock type @type.
+ *
+ * Returns: a pointer to the timer
+ */
+static inline QEMUTimer *qemu_timer_new(QEMUClockType type, int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ return timer_new(main_loop_tlg[type], scale, cb, opaque);
+}
+
void qemu_free_timer(QEMUTimer *ts);
void qemu_del_timer(QEMUTimer *ts);
void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
@@ -521,6 +539,23 @@ static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
}
/**
+ * qemu_timer_new_ns:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with nanosecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *qemu_timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
+{
+ return qemu_timer_new(type, SCALE_NS, cb, opaque);
+}
+
+/**
* timer_new_ns:
* @timer_list: the timer list to associate with the timer
* @callback: the callback to call when the timer expires
@@ -557,6 +592,23 @@ static inline QEMUTimer *qemu_new_timer_us(QEMUClock *clock,
}
/**
+ * qemu_timer_new_us:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with microsecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *qemu_timer_new_us(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
+{
+ return qemu_timer_new(type, SCALE_US, cb, opaque);
+}
+
+/**
* timer_new_us:
* @timer_list: the timer list to associate with the timer
* @callback: the callback to call when the timer expires
@@ -593,6 +645,23 @@ static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock,
}
/**
+ * qemu_timer_new_ms:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with millisecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *qemu_timer_new_ms(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
+{
+ return qemu_timer_new(type, SCALE_MS, cb, opaque);
+}
+
+/**
* timer_new_ms:
* @timer_list: the timer list to associate with the timer
* @callback: the callback to call when the timer expires
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 18/22] aio / timers: Use all timerlists in icount warp calculations
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (16 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 17/22] aio / timers: Introduce new API qemu_timer_new and friends Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 19/22] aio / timers: Add documentation and new format calls Alex Bligh
` (4 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Notify all timerlists derived from vm_clock in icount warp
calculations.
When calculating timer delay based on vm_clock deadline, use
all timerlists.
For compatibility, maintain an apparent bug where when using
icount, if no vm_clock timer was set, qemu_clock_deadline
would return INT32_MAX and always set an icount clock expiry
about 2 seconds ahead.
NB: thread safety - when different timerlists sit on different
threads, this will need some locking.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
cpus.c | 46 +++++++++++++++++++++++++++++++++++++---------
include/qemu/timer.h | 13 +++++++++++++
qemu-timer.c | 16 ++++++++++++++++
qtest.c | 2 +-
4 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/cpus.c b/cpus.c
index 0f65e76..673d506 100644
--- a/cpus.c
+++ b/cpus.c
@@ -262,7 +262,7 @@ static void icount_warp_rt(void *opaque)
qemu_icount_bias += MIN(warp_delta, delta);
}
if (qemu_clock_expired(vm_clock)) {
- qemu_notify_event();
+ qemu_clock_notify(vm_clock);
}
}
vm_clock_warp_start = -1;
@@ -273,13 +273,13 @@ void qtest_clock_warp(int64_t dest)
int64_t clock = qemu_get_clock_ns(vm_clock);
assert(qtest_enabled());
while (clock < dest) {
- int64_t deadline = qemu_clock_deadline(vm_clock);
+ int64_t deadline = qemu_clock_deadline_ns_all(vm_clock);
int64_t warp = MIN(dest - clock, deadline);
qemu_icount_bias += warp;
qemu_run_timers(vm_clock);
clock = qemu_get_clock_ns(vm_clock);
}
- qemu_notify_event();
+ qemu_clock_notify(vm_clock);
}
void qemu_clock_warp(QEMUClock *clock)
@@ -314,7 +314,18 @@ void qemu_clock_warp(QEMUClock *clock)
}
vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
- deadline = qemu_clock_deadline(vm_clock);
+ /* We want to use the earliest deadline from ALL vm_clocks */
+ deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no vm_clock timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
if (deadline > 0) {
/*
* Ensure the vm_clock proceeds even when the virtual CPU goes to
@@ -333,8 +344,8 @@ void qemu_clock_warp(QEMUClock *clock)
* packets continuously instead of every 100ms.
*/
qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
- } else {
- qemu_notify_event();
+ } else if (deadline == 0) {
+ qemu_clock_notify(vm_clock);
}
}
@@ -866,8 +877,13 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
while (1) {
tcg_exec_all();
- if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
- qemu_notify_event();
+
+ if (use_icount) {
+ int64_t deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ if (deadline == 0) {
+ qemu_clock_notify(vm_clock);
+ }
}
qemu_tcg_wait_io_event();
}
@@ -1145,11 +1161,23 @@ static int tcg_cpu_exec(CPUArchState *env)
#endif
if (use_icount) {
int64_t count;
+ int64_t deadline;
int decr;
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
env->icount_decr.u16.low = 0;
env->icount_extra = 0;
- count = qemu_icount_round(qemu_clock_deadline(vm_clock));
+ deadline = qemu_clock_deadline_ns_all(vm_clock);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no vm_clock timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
+ count = qemu_icount_round(deadline);
qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index ca26b6f..c093e4e 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -107,6 +107,7 @@ int64_t qemu_clock_deadline(QEMUClock *clock);
* @clock: the clock to operate on
*
* Calculate the timeout of the earliest expiring timer
+ * on the default timer list associated with the clock
* in nanoseconds, or -1 if no timer is set to expire.
*
* Returns: time until expiry in nanoseconds or -1
@@ -130,6 +131,18 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock);
bool qemu_clock_use_for_deadline(QEMUClock *clock);
/**
+ * qemu_clock_use_for_deadline:
+ * @clock: the clock to operate on
+ *
+ * Calculate the deadline across all timer lists associated
+ * with a clock (as opposed to just the default one)
+ * in nanoseconds, or -1 if no timer is set to expire.
+ *
+ * Returns: time until expiry in nanoseconds or -1
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClock *clock);
+
+/**
* qemu_clock_get_default_timerlist:
* @clock: the clock to operate on
*
diff --git a/qemu-timer.c b/qemu-timer.c
index bb45834..47e3103 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -401,6 +401,22 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock)
return timerlist_deadline_ns(clock->default_timerlist);
}
+/* Calculate the soonest deadline across all timerlists attached
+ * to the clock. This is used for the icount timeout so we
+ * ignore whether or not the clock should be used in deadline
+ * calculations.
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClock *clock)
+{
+ int64_t deadline = -1;
+ QEMUTimerList *timer_list;
+ QLIST_FOREACH(timer_list, &clock->timerlists, list) {
+ deadline = qemu_soonest_timeout(deadline,
+ timerlist_deadline_ns(timer_list));
+ }
+ return deadline;
+}
+
QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
{
return timer_list->clock;
diff --git a/qtest.c b/qtest.c
index 74f1842..c038e24 100644
--- a/qtest.c
+++ b/qtest.c
@@ -412,7 +412,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
if (words[1]) {
ns = strtoll(words[1], NULL, 0);
} else {
- ns = qemu_clock_deadline(vm_clock);
+ ns = qemu_clock_deadline_ns_all(vm_clock);
}
qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
qtest_send_prefix(chr);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 19/22] aio / timers: Add documentation and new format calls
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (17 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 18/22] aio / timers: Use all timerlists in icount warp calculations Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 20/22] aio / timers: Remove alarm timers Alex Bligh
` (3 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add documentation for existing qemu timer calls. Add new format
calls of the format qemu_timer_XXX rather than qemu_XXX_timer
for consistency.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
configure | 18 +++++
include/qemu/timer.h | 215 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 231 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 4e54d1b..331139e 100755
--- a/configure
+++ b/configure
@@ -2834,6 +2834,21 @@ if compile_prog "" "" ; then
ppoll=yes
fi
+# check for prctl(PR_SET_TIMERSLACK , ... ) support
+prctl_pr_set_timerslack=no
+cat > $TMPC << EOF
+#include <sys/prctl.h>
+
+int main(void)
+{
+ prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
+ return 0;
+}
+EOF
+if compile_prog "" "" ; then
+ prctl_pr_set_timerslack=yes
+fi
+
# check for epoll support
epoll=no
cat > $TMPC << EOF
@@ -3828,6 +3843,9 @@ fi
if test "$ppoll" = "yes" ; then
echo "CONFIG_PPOLL=y" >> $config_host_mak
fi
+if test "$prctl_pr_set_timerslack" = "yes" ; then
+ echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak
+fi
if test "$epoll" = "yes" ; then
echo "CONFIG_EPOLL=y" >> $config_host_mak
fi
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index c093e4e..50014a9 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -97,8 +97,52 @@ QEMUClock *qemu_clock_new(QEMUClockType type);
*/
void qemu_clock_free(QEMUClock *clock);
+/**
+ * qemu_get_clock_ns:
+ * @clock: the clock to operate on
+ *
+ * Get the nanosecond value of a clock
+ *
+ * Returns: the clock value in nanoseconds
+ */
int64_t qemu_get_clock_ns(QEMUClock *clock);
+
+/**
+ * qemu_clock_get_ns;
+ * @type: the clock type
+ *
+ * Get the nanosecond value of a clock with
+ * type @type
+ *
+ * Returns: the clock value in nanoseconds
+ */
+static inline int64_t qemu_clock_get_ns(QEMUClockType type)
+{
+ return qemu_get_clock_ns(qemu_get_clock(type));
+}
+
+/**
+ * qemu_clock_has_timers:
+ * @clock: the clock to operate on
+ *
+ * Determines whether a clock's default timer list
+ * has timers attached
+ *
+ * Returns: true if the clock's default timer list
+ * has timers attached
+ */
bool qemu_clock_has_timers(QEMUClock *clock);
+
+/**
+ * qemu_clock_expired:
+ * @clock: the clock to operate on
+ *
+ * Determines whether a clock's default timer list
+ * has an expired clock.
+ *
+ * Returns: true if the clock's default timer list has
+ * an expired timer
+ */
bool qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);
@@ -311,7 +355,7 @@ void timerlistgroup_deinit(QEMUTimerListGroup tlg);
bool timerlistgroup_run_timers(QEMUTimerListGroup tlg);
/**
- * timerlistgroup_deadline_ns
+ * timerlistgroup_deadline_ns:
* @tlg: the timer list group
*
* Determine the deadline of the soonest timer to
@@ -347,13 +391,57 @@ int qemu_timeout_ns_to_ms(int64_t ns);
* Returns: number of fds ready
*/
int qemu_poll_ns(GPollFD *fds, uint nfds, int64_t timeout);
+
+/**
+ * qemu_clock_enable:
+ * @clock: the clock to operate on
+ * @enabled: true to enable, false to disable
+ *
+ * Enable or disable a clock
+ */
void qemu_clock_enable(QEMUClock *clock, bool enabled);
+
+/**
+ * qemu_clock_warp:
+ * @clock: the clock to operate on
+ *
+ * Warp a clock to a new value
+ */
void qemu_clock_warp(QEMUClock *clock);
+/**
+ * qemu_register_clock_reset_notifier:
+ * @clock: the clock to operate on
+ * @notifier: the notifier function
+ *
+ * Register a notifier function to call when the clock
+ * concerned is reset.
+ */
void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
+
+/**
+ * qemu_unregister_clock_reset_notifier:
+ * @clock: the clock to operate on
+ * @notifier: the notifier function
+ *
+ * Unregister a notifier function to call when the clock
+ * concerned is reset.
+ */
void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
Notifier *notifier);
+/**
+ * qemu_new_timer:
+ * @clock: the clock to operate on
+ * @scale: the scale of the clock
+ * @cb: the callback function to call when the timer expires
+ * @opaque: an opaque pointer to pass to the callback
+ *
+ * Produce a new timer attached to clock @clock. This is a legacy
+ * function. Use qemu_timer_new instead.
+ *
+ * Returns: a pointer to the new timer allocated.
+ */
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque);
@@ -389,12 +477,129 @@ static inline QEMUTimer *qemu_timer_new(QEMUClockType type, int scale,
return timer_new(main_loop_tlg[type], scale, cb, opaque);
}
+/**
+ * qemu_free_timer:
+ * @ts: the timer to operate on
+ *
+ * free the timer @ts. @ts must not be active.
+ *
+ * This is a legacy function. Use qemu_timer_free instead.
+ */
void qemu_free_timer(QEMUTimer *ts);
+
+/**
+ * qemu_timer_free:
+ * @ts: the timer to operate on
+ *
+ * free the timer @ts. @ts must not be active.
+ */
+static inline void qemu_timer_free(QEMUTimer *ts)
+{
+ qemu_free_timer(ts);
+}
+
+/**
+ * qemu_del_timer:
+ * @ts: the timer to operate on
+ *
+ * Delete a timer. This makes it inactive. It does not free
+ * memory.
+ *
+ * This is a legacy function. Use qemu_timer_del instead.
+ */
void qemu_del_timer(QEMUTimer *ts);
+
+/**
+ * qemu_timer_del:
+ * @ts: the timer to operate on
+ *
+ * Delete a timer. This makes it inactive. It does not free
+ * memory.
+ */
+static inline void qemu_timer_del(QEMUTimer *ts)
+{
+ qemu_del_timer(ts);
+}
+
+/**
+ * qemu_mod_timer_ns:
+ * @ts: the timer to operate on
+ * @expire_time: the expiry time in nanoseconds
+ *
+ * Modify a timer such that the expiry time is @expire_time
+ * as measured in nanoseconds
+ *
+ * This is a legacy function. Use qemu_timer_mod_ns.
+ */
void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
+
+/**
+ * qemu_timer_mod_ns:
+ * @ts: the timer to operate on
+ * @expire_time: the expiry time in nanoseconds
+ *
+ * Modify a timer such that the expiry time is @expire_time
+ * as measured in nanoseconds
+ */
+static inline void qemu_timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
+{
+ qemu_mod_timer_ns(ts, expire_time);
+}
+
+/**
+ * qemu_mod_timer:
+ * @ts: the timer to operate on
+ * @expire_time: the expiry time
+ *
+ * Modify a timer such that the expiry time is @expire_time
+ * as measured in the timer's scale
+ *
+ * This is a legacy function. Use qemu_timer_mod.
+ */
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
+
+/**
+ * qemu_timer_mod:
+ * @ts: the timer to operate on
+ * @expire_time: the expiry time in nanoseconds
+ *
+ * Modify a timer such that the expiry time is @expire_time
+ * as measured in the timer's scale
+ */
+static inline void qemu_timer_mod(QEMUTimer *ts, int64_t expire_time)
+{
+ qemu_mod_timer(ts, expire_time);
+}
+
+/**
+ * qemu_timer_pending:
+ * @ts: the timer to operate on
+ *
+ * Determines whether a timer is pending (i.e. is on the
+ * active list of timers, whether or not it has not yet expired).
+ *
+ * Returns: true if the timer is pending
+ */
bool qemu_timer_pending(QEMUTimer *ts);
+
+/**
+ * qemu_timer_expired:
+ * @ts: the timer to operate on
+ *
+ * Determines whether a timer has expired.
+ *
+ * Returns: true if the timer has expired
+ */
bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
+
+/**
+ * qemu_timer_expire_time_ns:
+ * @ts: the timer to operate on
+ *
+ * Determines the time until a timer expires
+ *
+ * Returns: the time (in nanoseonds) until a timer expires
+ */
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
/* New format calling conventions for timers */
@@ -508,9 +713,15 @@ bool qemu_run_timers(QEMUClock *clock);
bool qemu_run_all_timers(void);
void configure_alarms(char const *opt);
-void init_clocks(void);
int init_timer_alarm(void);
+/**
+ * initclocks:
+ *
+ * Initialise the clock & timer infrastructure
+ */
+void init_clocks(void);
+
int64_t cpu_get_ticks(void);
void cpu_enable_ticks(void);
void cpu_disable_ticks(void);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 20/22] aio / timers: Remove alarm timers
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (18 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 19/22] aio / timers: Add documentation and new format calls Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 21/22] aio / timers: Add test harness for AioContext timers Alex Bligh
` (2 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Remove alarm timers from qemu-timers.c now we use g_poll / ppoll
instead.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 3 -
main-loop.c | 4 -
qemu-timer.c | 500 +-------------------------------------------------
vl.c | 4 +-
4 files changed, 4 insertions(+), 507 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 50014a9..21c1b04 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -712,9 +712,6 @@ bool qemu_run_timers(QEMUClock *clock);
*/
bool qemu_run_all_timers(void);
-void configure_alarms(char const *opt);
-int init_timer_alarm(void);
-
/**
* initclocks:
*
diff --git a/main-loop.c b/main-loop.c
index 00e54bd..d9ad6c7 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -131,10 +131,6 @@ int qemu_init_main_loop(void)
GSource *src;
init_clocks();
- if (init_timer_alarm() < 0) {
- fprintf(stderr, "could not initialize alarm timer\n");
- exit(1);
- }
ret = qemu_signal_init();
if (ret) {
diff --git a/qemu-timer.c b/qemu-timer.c
index 47e3103..a6b274c 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -33,10 +33,6 @@
#include <pthread.h>
#endif
-#ifdef _WIN32
-#include <mmsystem.h>
-#endif
-
#ifdef CONFIG_PPOLL
#include <poll.h>
#endif
@@ -86,174 +82,11 @@ struct QEMUTimer {
int scale;
};
-struct qemu_alarm_timer {
- char const *name;
- int (*start)(struct qemu_alarm_timer *t);
- void (*stop)(struct qemu_alarm_timer *t);
- void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
-#if defined(__linux__)
- timer_t timer;
- int fd;
-#elif defined(_WIN32)
- HANDLE timer;
-#endif
- bool expired;
- bool pending;
-};
-
-static struct qemu_alarm_timer *alarm_timer;
-
static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
{
return timer_head && (timer_head->expire_time <= current_time);
}
-static int64_t qemu_next_alarm_deadline(void)
-{
- int64_t delta = INT64_MAX;
- int64_t rtdelta;
- int64_t hdelta;
-
- if (!use_icount && vm_clock->enabled &&
- vm_clock->default_timerlist->active_timers) {
- delta = vm_clock->default_timerlist->active_timers->expire_time -
- qemu_get_clock_ns(vm_clock);
- }
- if (host_clock->enabled &&
- host_clock->default_timerlist->active_timers) {
- hdelta = host_clock->default_timerlist->active_timers->expire_time -
- qemu_get_clock_ns(host_clock);
- if (hdelta < delta) {
- delta = hdelta;
- }
- }
- if (rt_clock->enabled &&
- rt_clock->default_timerlist->active_timers) {
- rtdelta = (rt_clock->default_timerlist->active_timers->expire_time -
- qemu_get_clock_ns(rt_clock));
- if (rtdelta < delta) {
- delta = rtdelta;
- }
- }
-
- return delta;
-}
-
-static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
-{
- int64_t nearest_delta_ns = qemu_next_alarm_deadline();
- if (nearest_delta_ns < INT64_MAX) {
- t->rearm(t, nearest_delta_ns);
- }
-}
-
-/* TODO: MIN_TIMER_REARM_NS should be optimized */
-#define MIN_TIMER_REARM_NS 250000
-
-#ifdef _WIN32
-
-static int mm_start_timer(struct qemu_alarm_timer *t);
-static void mm_stop_timer(struct qemu_alarm_timer *t);
-static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-static int win32_start_timer(struct qemu_alarm_timer *t);
-static void win32_stop_timer(struct qemu_alarm_timer *t);
-static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#else
-
-static int unix_start_timer(struct qemu_alarm_timer *t);
-static void unix_stop_timer(struct qemu_alarm_timer *t);
-static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#ifdef __linux__
-
-static int dynticks_start_timer(struct qemu_alarm_timer *t);
-static void dynticks_stop_timer(struct qemu_alarm_timer *t);
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#endif /* __linux__ */
-
-#endif /* _WIN32 */
-
-static struct qemu_alarm_timer alarm_timers[] = {
-#ifndef _WIN32
-#ifdef __linux__
- {"dynticks", dynticks_start_timer,
- dynticks_stop_timer, dynticks_rearm_timer},
-#endif
- {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
-#else
- {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
- {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
-#endif
- {NULL, }
-};
-
-static void show_available_alarms(void)
-{
- int i;
-
- printf("Available alarm timers, in order of precedence:\n");
- for (i = 0; alarm_timers[i].name; i++)
- printf("%s\n", alarm_timers[i].name);
-}
-
-void configure_alarms(char const *opt)
-{
- int i;
- int cur = 0;
- int count = ARRAY_SIZE(alarm_timers) - 1;
- char *arg;
- char *name;
- struct qemu_alarm_timer tmp;
-
- if (is_help_option(opt)) {
- show_available_alarms();
- exit(0);
- }
-
- arg = g_strdup(opt);
-
- /* Reorder the array */
- name = strtok(arg, ",");
- while (name) {
- for (i = 0; i < count && alarm_timers[i].name; i++) {
- if (!strcmp(alarm_timers[i].name, name))
- break;
- }
-
- if (i == count) {
- fprintf(stderr, "Unknown clock %s\n", name);
- goto next;
- }
-
- if (i < cur)
- /* Ignore */
- goto next;
-
- /* Swap */
- tmp = alarm_timers[i];
- alarm_timers[i] = alarm_timers[cur];
- alarm_timers[cur] = tmp;
-
- cur++;
-next:
- name = strtok(NULL, ",");
- }
-
- g_free(arg);
-
- if (cur) {
- /* Disable remaining timers */
- for (i = cur; i < count; i++)
- alarm_timers[i].name = NULL;
- } else {
- show_available_alarms();
- exit(1);
- }
-}
-
static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock)
{
QEMUTimerList *timer_list;
@@ -327,7 +160,6 @@ void qemu_clock_enable(QEMUClock *clock, bool enabled)
clock->enabled = enabled;
if (enabled && !old) {
qemu_clock_notify(clock);
- qemu_rearm_alarm_timer(alarm_timer);
}
}
@@ -561,9 +393,6 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
/* Rearm if necessary */
if (pt == &ts->timer_list->active_timers) {
- if (!alarm_timer->pending) {
- qemu_rearm_alarm_timer(alarm_timer);
- }
/* Interrupt execution to force deadline recalculation. */
qemu_clock_warp(ts->timer_list->clock);
timerlist_notify(ts->timer_list);
@@ -722,338 +551,11 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
bool qemu_run_all_timers(void)
{
bool progress = false;
- alarm_timer->pending = false;
-
- /* vm time timers */
QEMUClockType type;
+
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
progress |= qemu_run_timers(qemu_get_clock(type));
}
- /* rearm timer, if not periodic */
- if (alarm_timer->expired) {
- alarm_timer->expired = false;
- qemu_rearm_alarm_timer(alarm_timer);
- }
-
return progress;
}
-
-#ifdef _WIN32
-static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
-#else
-static void host_alarm_handler(int host_signum)
-#endif
-{
- struct qemu_alarm_timer *t = alarm_timer;
- if (!t)
- return;
-
- t->expired = true;
- t->pending = true;
- qemu_notify_event();
-}
-
-#if defined(__linux__)
-
-#include "qemu/compatfd.h"
-
-static int dynticks_start_timer(struct qemu_alarm_timer *t)
-{
- struct sigevent ev;
- timer_t host_timer;
- struct sigaction act;
-
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = host_alarm_handler;
-
- sigaction(SIGALRM, &act, NULL);
-
- /*
- * Initialize ev struct to 0 to avoid valgrind complaining
- * about uninitialized data in timer_create call
- */
- memset(&ev, 0, sizeof(ev));
- ev.sigev_value.sival_int = 0;
- ev.sigev_notify = SIGEV_SIGNAL;
-#ifdef CONFIG_SIGEV_THREAD_ID
- if (qemu_signalfd_available()) {
- ev.sigev_notify = SIGEV_THREAD_ID;
- ev._sigev_un._tid = qemu_get_thread_id();
- }
-#endif /* CONFIG_SIGEV_THREAD_ID */
- ev.sigev_signo = SIGALRM;
-
- if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
- perror("timer_create");
- return -1;
- }
-
- t->timer = host_timer;
-
- return 0;
-}
-
-static void dynticks_stop_timer(struct qemu_alarm_timer *t)
-{
- timer_t host_timer = t->timer;
-
- timer_delete(host_timer);
-}
-
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- timer_t host_timer = t->timer;
- struct itimerspec timeout;
- int64_t current_ns;
-
- if (nearest_delta_ns < MIN_TIMER_REARM_NS)
- nearest_delta_ns = MIN_TIMER_REARM_NS;
-
- /* check whether a timer is already running */
- if (timer_gettime(host_timer, &timeout)) {
- perror("gettime");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
- current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
- if (current_ns && current_ns <= nearest_delta_ns)
- return;
-
- timeout.it_interval.tv_sec = 0;
- timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
- timeout.it_value.tv_sec = nearest_delta_ns / 1000000000;
- timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
- if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
- perror("settime");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
-}
-
-#endif /* defined(__linux__) */
-
-#if !defined(_WIN32)
-
-static int unix_start_timer(struct qemu_alarm_timer *t)
-{
- struct sigaction act;
-
- /* timer signal */
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = host_alarm_handler;
-
- sigaction(SIGALRM, &act, NULL);
- return 0;
-}
-
-static void unix_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- struct itimerval itv;
- int err;
-
- if (nearest_delta_ns < MIN_TIMER_REARM_NS)
- nearest_delta_ns = MIN_TIMER_REARM_NS;
-
- itv.it_interval.tv_sec = 0;
- itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
- itv.it_value.tv_sec = nearest_delta_ns / 1000000000;
- itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
- err = setitimer(ITIMER_REAL, &itv, NULL);
- if (err) {
- perror("setitimer");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
-}
-
-static void unix_stop_timer(struct qemu_alarm_timer *t)
-{
- struct itimerval itv;
-
- memset(&itv, 0, sizeof(itv));
- setitimer(ITIMER_REAL, &itv, NULL);
-}
-
-#endif /* !defined(_WIN32) */
-
-
-#ifdef _WIN32
-
-static MMRESULT mm_timer;
-static TIMECAPS mm_tc;
-
-static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
- DWORD_PTR dwUser, DWORD_PTR dw1,
- DWORD_PTR dw2)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- if (!t) {
- return;
- }
- t->expired = true;
- t->pending = true;
- qemu_notify_event();
-}
-
-static int mm_start_timer(struct qemu_alarm_timer *t)
-{
- timeGetDevCaps(&mm_tc, sizeof(mm_tc));
- return 0;
-}
-
-static void mm_stop_timer(struct qemu_alarm_timer *t)
-{
- if (mm_timer) {
- timeKillEvent(mm_timer);
- }
-}
-
-static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
-{
- int64_t nearest_delta_ms = delta / 1000000;
- if (nearest_delta_ms < mm_tc.wPeriodMin) {
- nearest_delta_ms = mm_tc.wPeriodMin;
- } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
- nearest_delta_ms = mm_tc.wPeriodMax;
- }
-
- if (mm_timer) {
- timeKillEvent(mm_timer);
- }
- mm_timer = timeSetEvent((UINT)nearest_delta_ms,
- mm_tc.wPeriodMin,
- mm_alarm_handler,
- (DWORD_PTR)t,
- TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
-
- if (!mm_timer) {
- fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
- timeEndPeriod(mm_tc.wPeriodMin);
- exit(1);
- }
-}
-
-static int win32_start_timer(struct qemu_alarm_timer *t)
-{
- HANDLE hTimer;
- BOOLEAN success;
-
- /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
- is zero) that has already expired, the timer is not updated. Since
- creating a new timer is relatively expensive, set a bogus one-hour
- interval in the dynticks case. */
- success = CreateTimerQueueTimer(&hTimer,
- NULL,
- host_alarm_handler,
- t,
- 1,
- 3600000,
- WT_EXECUTEINTIMERTHREAD);
-
- if (!success) {
- fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
- GetLastError());
- return -1;
- }
-
- t->timer = hTimer;
- return 0;
-}
-
-static void win32_stop_timer(struct qemu_alarm_timer *t)
-{
- HANDLE hTimer = t->timer;
-
- if (hTimer) {
- DeleteTimerQueueTimer(NULL, hTimer, NULL);
- }
-}
-
-static void win32_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- HANDLE hTimer = t->timer;
- int64_t nearest_delta_ms;
- BOOLEAN success;
-
- nearest_delta_ms = nearest_delta_ns / 1000000;
- if (nearest_delta_ms < 1) {
- nearest_delta_ms = 1;
- }
- /* ULONG_MAX can be 32 bit */
- if (nearest_delta_ms > ULONG_MAX) {
- nearest_delta_ms = ULONG_MAX;
- }
- success = ChangeTimerQueueTimer(NULL,
- hTimer,
- (unsigned long) nearest_delta_ms,
- 3600000);
-
- if (!success) {
- fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
- GetLastError());
- exit(-1);
- }
-
-}
-
-#endif /* _WIN32 */
-
-static void quit_timers(void)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- alarm_timer = NULL;
- t->stop(t);
-}
-
-#ifdef CONFIG_POSIX
-static void reinit_timers(void)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- t->stop(t);
- if (t->start(t)) {
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
- qemu_rearm_alarm_timer(t);
-}
-#endif /* CONFIG_POSIX */
-
-int init_timer_alarm(void)
-{
- struct qemu_alarm_timer *t = NULL;
- int i, err = -1;
-
- if (alarm_timer) {
- return 0;
- }
-
- for (i = 0; alarm_timers[i].name; i++) {
- t = &alarm_timers[i];
-
- err = t->start(t);
- if (!err)
- break;
- }
-
- if (err) {
- err = -ENOENT;
- goto fail;
- }
-
- atexit(quit_timers);
-#ifdef CONFIG_POSIX
- pthread_atfork(NULL, NULL, reinit_timers);
-#endif
- alarm_timer = t;
- return 0;
-
-fail:
- return err;
-}
-
diff --git a/vl.c b/vl.c
index f422a1c..4c68668 100644
--- a/vl.c
+++ b/vl.c
@@ -3714,7 +3714,9 @@ int main(int argc, char **argv, char **envp)
old_param = 1;
break;
case QEMU_OPTION_clock:
- configure_alarms(optarg);
+ /* Clock options no longer exist. Keep this option for
+ * backward compatibility.
+ */
break;
case QEMU_OPTION_startdate:
configure_rtc_date_offset(optarg, 1);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 21/22] aio / timers: Add test harness for AioContext timers
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (19 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 20/22] aio / timers: Remove alarm timers Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 22/22] aio / timers: Remove legacy qemu_clock_deadline & qemu_timerlist_deadline Alex Bligh
2013-08-08 7:52 ` [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Add a test harness for AioContext timers. The g_source equivalent is
unsatisfactory as it suffers from false wakeups.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
tests/test-aio.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/tests/test-aio.c b/tests/test-aio.c
index eedf7f8..1d16046 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -32,6 +32,15 @@ typedef struct {
int max;
} BHTestData;
+typedef struct {
+ QEMUTimer *timer;
+ QEMUTimerList *timer_list;
+ int n;
+ int max;
+ int64_t ns;
+ AioContext *ctx;
+} TimerTestData;
+
static void bh_test_cb(void *opaque)
{
BHTestData *data = opaque;
@@ -40,6 +49,26 @@ static void bh_test_cb(void *opaque)
}
}
+static void timer_test_cb(void *opaque)
+{
+ TimerTestData *data = opaque;
+ if (++data->n < data->max) {
+ qemu_mod_timer(data->timer,
+ qemu_get_clock_ns(
+ timerlist_get_clock(data->timer_list)) +
+ data->ns);
+ }
+}
+
+static void dummy_io_handler_read(void *opaque)
+{
+}
+
+static int dummy_io_handler_flush(void *opaque)
+{
+ return 1;
+}
+
static void bh_delete_cb(void *opaque)
{
BHTestData *data = opaque;
@@ -341,6 +370,64 @@ static void test_wait_event_notifier_noflush(void)
event_notifier_cleanup(&data.e);
}
+static void test_timer_schedule(void)
+{
+ TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
+ .max = 2,
+ .timer_list = ctx->tlg[QEMU_CLOCK_VIRTUAL] };
+ int pipefd[2];
+
+ /* aio_poll will not block to wait for timers to complete unless it has
+ * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
+ */
+ g_assert(!pipe2(pipefd, O_NONBLOCK));
+ aio_set_fd_handler(ctx, pipefd[0],
+ dummy_io_handler_read, NULL, dummy_io_handler_flush,
+ NULL);
+ aio_poll(ctx, false);
+
+ data.timer = timer_new(data.timer_list, SCALE_NS, timer_test_cb, &data);
+ qemu_mod_timer(data.timer,
+ qemu_get_clock_ns(timerlist_get_clock(data.timer_list)) +
+ data.ns);
+
+ g_assert_cmpint(data.n, ==, 0);
+
+ /* qemu_mod_timer may well cause an event notifer to have gone off,
+ * so clear that
+ */
+ do {} while (aio_poll(ctx, false));
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 0);
+
+ sleep(1);
+ g_assert_cmpint(data.n, ==, 0);
+
+ g_assert(aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ /* qemu_mod_timer called by our callback */
+ do {} while (aio_poll(ctx, false));
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ g_assert(aio_poll(ctx, true));
+ g_assert_cmpint(data.n, ==, 2);
+
+ /* As max is now 2, an event notifier should not have gone off */
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 2);
+
+ aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL, NULL);
+ close(pipefd[0]);
+ close(pipefd[1]);
+
+ qemu_del_timer(data.timer);
+}
+
/* Now the same tests, using the context as a GSource. They are
* very similar to the ones above, with g_main_context_iteration
* replacing aio_poll. However:
@@ -623,6 +710,54 @@ static void test_source_wait_event_notifier_noflush(void)
event_notifier_cleanup(&data.e);
}
+static void test_source_timer_schedule(void)
+{
+ TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
+ .max = 2,
+ .timer_list = ctx->tlg[QEMU_CLOCK_VIRTUAL] };
+ int pipefd[2];
+ int64_t expiry;
+
+ /* aio_poll will not block to wait for timers to complete unless it has
+ * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
+ */
+ g_assert(!pipe2(pipefd, O_NONBLOCK));
+ aio_set_fd_handler(ctx, pipefd[0],
+ dummy_io_handler_read, NULL, dummy_io_handler_flush,
+ NULL);
+ do {} while (g_main_context_iteration(NULL, false));
+
+ data.timer = timer_new(data.timer_list, SCALE_NS, timer_test_cb, &data);
+ expiry = qemu_get_clock_ns(timerlist_get_clock(data.timer_list)) +
+ data.ns;
+ qemu_mod_timer(data.timer, expiry);
+
+ g_assert_cmpint(data.n, ==, 0);
+
+ sleep(1);
+ g_assert_cmpint(data.n, ==, 0);
+
+ g_assert(g_main_context_iteration(NULL, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ /* The comment above was not kidding when it said this wakes up itself */
+ do {
+ g_assert(g_main_context_iteration(NULL, true));
+ } while (qemu_get_clock_ns(
+ timerlist_get_clock(data.timer_list)) <= expiry);
+ sleep(1);
+ g_main_context_iteration(NULL, false);
+
+ g_assert_cmpint(data.n, ==, 2);
+
+ aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL, NULL);
+ close(pipefd[0]);
+ close(pipefd[1]);
+
+ qemu_del_timer(data.timer);
+}
+
+
/* End of tests. */
int main(int argc, char **argv)
@@ -651,6 +786,7 @@ int main(int argc, char **argv)
g_test_add_func("/aio/event/wait", test_wait_event_notifier);
g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush);
g_test_add_func("/aio/event/flush", test_flush_event_notifier);
+ g_test_add_func("/aio/timer/schedule", test_timer_schedule);
g_test_add_func("/aio-gsource/notify", test_source_notify);
g_test_add_func("/aio-gsource/flush", test_source_flush);
@@ -665,5 +801,6 @@ int main(int argc, char **argv)
g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier);
g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush);
g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier);
+ g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule);
return g_test_run();
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [RFC] [PATCHv7 22/22] aio / timers: Remove legacy qemu_clock_deadline & qemu_timerlist_deadline
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (20 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 21/22] aio / timers: Add test harness for AioContext timers Alex Bligh
@ 2013-08-06 23:49 ` Alex Bligh
2013-08-08 7:52 ` [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-06 23:49 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Remove qemu_clock_deadline and qemu_timerlist_deadline now we are using
the ns functions throughout.
Signed-off-by: Alex Bligh <alex@alex.org.uk>
---
include/qemu/timer.h | 16 ----------------
qemu-timer.c | 20 --------------------
2 files changed, 36 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 21c1b04..9989d0e 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -144,7 +144,6 @@ bool qemu_clock_has_timers(QEMUClock *clock);
* an expired timer
*/
bool qemu_clock_expired(QEMUClock *clock);
-int64_t qemu_clock_deadline(QEMUClock *clock);
/**
* qemu_clock_deadline_ns:
@@ -247,21 +246,6 @@ bool timerlist_has_timers(QEMUTimerList *timer_list);
bool timerlist_expired(QEMUTimerList *timer_list);
/**
- * timerlist_deadline:
- * @timer_list: the timer list to operate on
- *
- * Determine the deadline for a timer_list. This is
- * a legacy function which returns INT32_MAX if the
- * timer list has no timers or if the earliest timer
- * expires later than INT32_MAX nanoseconds away.
- *
- * Returns: the number of nanoseconds until the earliest
- * timer expires or INT32_MAX in the situations listed
- * above
- */
-int64_t timerlist_deadline(QEMUTimerList *timer_list);
-
-/**
* timerlist_deadline_ns:
* @timer_list: the timer list to operate on
*
diff --git a/qemu-timer.c b/qemu-timer.c
index a6b274c..491b6d6 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -185,26 +185,6 @@ bool qemu_clock_expired(QEMUClock *clock)
return timerlist_expired(clock->default_timerlist);
}
-int64_t timerlist_deadline(QEMUTimerList *timer_list)
-{
- /* To avoid problems with overflow limit this to 2^32. */
- int64_t delta = INT32_MAX;
-
- if (timer_list->clock->enabled && timer_list->active_timers) {
- delta = timer_list->active_timers->expire_time -
- qemu_get_clock_ns(timer_list->clock);
- }
- if (delta < 0) {
- delta = 0;
- }
- return delta;
-}
-
-int64_t qemu_clock_deadline(QEMUClock *clock)
-{
- return timerlist_deadline(clock->default_timerlist);
-}
-
/*
* As above, but return -1 for no deadline, and do not cap to 2^32
* as we know the result is always positive.
--
1.7.9.5
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
@ 2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-07 11:37 ` Alex Bligh
2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-08 6:21 ` liu ping fan
2 siblings, 1 reply; 31+ messages in thread
From: Stefan Hajnoczi @ 2013-08-07 11:31 UTC (permalink / raw)
To: Alex Bligh
Cc: Kevin Wolf, Anthony Liguori, qemu-devel, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
On Wed, Aug 07, 2013 at 12:48:55AM +0100, Alex Bligh wrote:
> Add qemu_clock_free and expose qemu_new_clock as qemu_clock_new.
>
> Expose clock types.
>
> Signed-off-by: Alex Bligh <alex@alex.org.uk>
> ---
> include/qemu/timer.h | 22 ++++++++++++++++++++++
> qemu-timer.c | 11 ++++++-----
> 2 files changed, 28 insertions(+), 5 deletions(-)
Regarding doc comments: if the function is self-documenting then the doc
comment might not add much. I think in those cases it's okay to omit
details about arguments or return values if they are clear from the
function prototype.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
2013-08-07 11:31 ` Stefan Hajnoczi
@ 2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-08 6:21 ` liu ping fan
2 siblings, 0 replies; 31+ messages in thread
From: Stefan Hajnoczi @ 2013-08-07 11:31 UTC (permalink / raw)
To: Alex Bligh
Cc: Kevin Wolf, Anthony Liguori, qemu-devel, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
On Wed, Aug 07, 2013 at 12:48:55AM +0100, Alex Bligh wrote:
I forgot to mention that there's no need to change the doc comments
you've already written. I just wanted to share that to save you work in
the future.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-07 11:31 ` Stefan Hajnoczi
@ 2013-08-07 11:37 ` Alex Bligh
2013-08-07 15:47 ` Paolo Bonzini
0 siblings, 1 reply; 31+ messages in thread
From: Alex Bligh @ 2013-08-07 11:37 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, qemu-devel, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
--On 7 August 2013 13:31:07 +0200 Stefan Hajnoczi <stefanha@gmail.com>
wrote:
> Regarding doc comments: if the function is self-documenting then the doc
> comment might not add much. I think in those cases it's okay to omit
> details about arguments or return values if they are clear from the
> function prototype.
Given I've done them for every function, I hope they don't cause any
active harm. I was concerned that with an API change some things that
one might have thought were obvious are in fact not obvious (e.g.
timer_del vs. timer_free).
--
Alex Bligh
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-07 11:37 ` Alex Bligh
@ 2013-08-07 15:47 ` Paolo Bonzini
0 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2013-08-07 15:47 UTC (permalink / raw)
To: Alex Bligh
Cc: Kevin Wolf, Anthony Liguori, Stefan Hajnoczi, qemu-devel,
liu ping fan, Stefan Hajnoczi, MORITA Kazutaka, rth
On Aug 07 2013, Alex Bligh wrote:
>
> --On 7 August 2013 13:31:07 +0200 Stefan Hajnoczi
> <stefanha@gmail.com> wrote:
>
> > Regarding doc comments: if the function is self-documenting then the doc
> > comment might not add much. I think in those cases it's okay to omit
> > details about arguments or return values if they are clear from the
> > function prototype.
>
> Given I've done them for every function, I hope they don't cause any
> active harm. I was concerned that with an API change some things that
> one might have thought were obvious are in fact not obvious (e.g.
> timer_del vs. timer_free).
No, they definitely do not harm.
Paolo
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList Alex Bligh
@ 2013-08-08 6:12 ` liu ping fan
0 siblings, 0 replies; 31+ messages in thread
From: liu ping fan @ 2013-08-08 6:12 UTC (permalink / raw)
To: Alex Bligh
Cc: Kevin Wolf, Anthony Liguori, qemu-devel, Stefan Hajnoczi,
Paolo Bonzini, MORITA Kazutaka, rth
On Wed, Aug 7, 2013 at 7:49 AM, Alex Bligh <alex@alex.org.uk> wrote:
> Split QEMUClock into QEMUClock and QEMUTimerList so that we can
> have more than one QEMUTimerList associated with the same clock.
>
> Introduce a default_timerlist concept and make existing
> qemu_clock_* calls that actually should operate on a QEMUTimerList
> call the relevant QEMUTimerList implementations, using the clock's
> default timerlist. This vastly reduces the invasiveness of this
> change and means the API stays constant for existing users.
>
> Introduce a list of QEMUTimerLists associated with each clock
> so that reenabling the clock can cause all the notifiers
> to be called. Note the code to do the notifications is added
> in a later patch.
>
> Switch QEMUClockType to an enum. Remove global variables vm_clock,
> host_clock and rt_clock and add compatibility defines. Do not
I think that as clock event source, QemuClock can not be created
arbitrary, i.e only three instance allowed. So what about comment
"Fold *_clock into qemu_clocks[]"
> fix qemu_next_alarm_deadline as it's going to be deleted.
>
> Add qemu_clock_use_for_deadline to indicate whether a particular
> clock should be used for deadline calculations. When use_icount
> is true, vm_clock should not be used for deadline calculations
> as it does not contain a nanosecond count. Instead, icount
> timeouts come from the execution thread doing aio_notify or
> qemu_notify as appropriate. This function is used in the next
> patch.
>
> Signed-off-by: Alex Bligh <alex@alex.org.uk>
> ---
> include/qemu/timer.h | 408 +++++++++++++++++++++++++++++++++++++++++++++++---
> qemu-timer.c | 201 +++++++++++++++++++------
> 2 files changed, 538 insertions(+), 71 deletions(-)
>
> diff --git a/include/qemu/timer.h b/include/qemu/timer.h
> index 0d368cc..eb2b99e 100644
> --- a/include/qemu/timer.h
> +++ b/include/qemu/timer.h
> @@ -11,30 +11,71 @@
> #define SCALE_US 1000
> #define SCALE_NS 1
>
> -#define QEMU_CLOCK_REALTIME 0
> -#define QEMU_CLOCK_VIRTUAL 1
> -#define QEMU_CLOCK_HOST 2
> +/**
> + * QEMUClockType:
> + *
> + * The following clock types are available:
> + *
> + * @QEMU_CLOCK_REALTIME: Real time clock
> + *
> + * The real time clock should be used only for stuff which does not
> + * change the virtual machine state, as it is run even if the virtual
> + * machine is stopped. The real time clock has a frequency of 1000
> + * Hz.
> + *
> + * Formerly rt_clock
> + *
> + * @QEMU_CLOCK_VIRTUAL: virtual clock
> + *
> + * The virtual clock is only run during the emulation. It is stopped
> + * when the virtual machine is stopped. Virtual timers use a high
> + * precision clock, usually cpu cycles (use ticks_per_sec).
> + *
> + * Formerly vm_clock
> + *
> + * @QEMU_CLOCK_HOST: host clock
> + *
> + * The host clock should be use for device models that emulate accurate
> + * real time sources. It will continue to run when the virtual machine
> + * is suspended, and it will reflect system time changes the host may
> + * undergo (e.g. due to NTP). The host clock has the same precision as
> + * the virtual clock.
> + *
> + * Formerly host_clock
> + */
> +
> +typedef enum {
> + QEMU_CLOCK_REALTIME = 0,
> + QEMU_CLOCK_VIRTUAL = 1,
> + QEMU_CLOCK_HOST = 2,
> + QEMU_CLOCK_MAX
> +} QEMUClockType;
>
> typedef struct QEMUClock QEMUClock;
> +typedef struct QEMUTimerList QEMUTimerList;
> typedef void QEMUTimerCB(void *opaque);
>
> -/* The real time clock should be used only for stuff which does not
> - change the virtual machine state, as it is run even if the virtual
> - machine is stopped. The real time clock has a frequency of 1000
> - Hz. */
> -extern QEMUClock *rt_clock;
> +extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
>
> -/* The virtual clock is only run during the emulation. It is stopped
> - when the virtual machine is stopped. Virtual timers use a high
> - precision clock, usually cpu cycles (use ticks_per_sec). */
> -extern QEMUClock *vm_clock;
> +/**
> + * qemu_get_clock:
> + * @type: type of clock
> + *
> + * Translate a clock type into a pointer to QEMUClock object.
> + *
> + * Returns: a pointer to the QEMUClock object
> + */
> +static inline QEMUClock *qemu_get_clock(QEMUClockType type)
> +{
> + return qemu_clocks[type];
> +}
>
> -/* The host clock should be use for device models that emulate accurate
> - real time sources. It will continue to run when the virtual machine
> - is suspended, and it will reflect system time changes the host may
> - undergo (e.g. due to NTP). The host clock has the same precision as
> - the virtual clock. */
> -extern QEMUClock *host_clock;
> +/* These three clocks are maintained here with separate variable
> + * names for compatibility only.
> + */
> +#define rt_clock (qemu_get_clock(QEMU_CLOCK_REALTIME))
> +#define vm_clock (qemu_get_clock(QEMU_CLOCK_VIRTUAL))
> +#define host_clock (qemu_get_clock(QEMU_CLOCK_HOST))
>
> /**
> * qemu_clock_new:
> @@ -44,7 +85,7 @@ extern QEMUClock *host_clock;
> *
> * Returns: A pointer to the clock object
> */
> -QEMUClock *qemu_clock_new(int type);
> +QEMUClock *qemu_clock_new(QEMUClockType type);
>
> /**
> * qemu_clock_free:
> @@ -55,8 +96,8 @@ QEMUClock *qemu_clock_new(int type);
> void qemu_clock_free(QEMUClock *clock);
>
> int64_t qemu_get_clock_ns(QEMUClock *clock);
> -int64_t qemu_clock_has_timers(QEMUClock *clock);
> -int64_t qemu_clock_expired(QEMUClock *clock);
> +bool qemu_clock_has_timers(QEMUClock *clock);
> +bool qemu_clock_expired(QEMUClock *clock);
> int64_t qemu_clock_deadline(QEMUClock *clock);
>
> /**
> @@ -71,6 +112,124 @@ int64_t qemu_clock_deadline(QEMUClock *clock);
> int64_t qemu_clock_deadline_ns(QEMUClock *clock);
>
> /**
> + * qemu_clock_use_for_deadline:
> + * @clock: the clock to operate on
> + *
> + * Determine whether a clock should be used for deadline
> + * calculations. Some clocks, for instance vm_clock with
> + * use_icount set, do not count in nanoseconds. Such clocks
> + * are not used for deadline calculations, and are presumed
> + * to interrupt any poll using qemu_notify/aio_notify
> + * etc.
> + *
> + * Returns: true if the clock runs in nanoseconds and
> + * should be used for a deadline.
> + */
> +bool qemu_clock_use_for_deadline(QEMUClock *clock);
> +
> +/**
> + * qemu_clock_get_default_timerlist:
> + * @clock: the clock to operate on
> + *
> + * Return the default timer list assocatiated with a clock.
> + *
> + * Returns: the default timer list
> + */
> +QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock);
> +
> +/**
> + * timerlist_new:
> + * @type: the clock type to associate with the timerlist
> + *
> + * Create a new timerlist associated with the clock of
> + * type @type.
> + *
> + * Returns: a pointer to the QEMUTimerList created
> + */
> +QEMUTimerList *timerlist_new(QEMUClockType type);
> +
> +/**
> + * timerlist_free:
> + * @timer_list: the timer list to free
> + *
> + * Frees a timer_list. It must have no active timers.
> + */
> +void timerlist_free(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_has_timers:
> + * @timer_list: the timer list to operate on
> + *
> + * Determine whether a timer list has active timers
> + *
> + * Returns: true if the timer list has timers.
> + */
> +bool timerlist_has_timers(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_expired:
> + * @timer_list: the timer list to operate on
> + *
> + * Determine whether a timer list has any timers which
> + * are expired.
> + *
> + * Returns: true if the timer list has timers which
> + * have expired.
> + */
> +bool timerlist_expired(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_deadline:
> + * @timer_list: the timer list to operate on
> + *
> + * Determine the deadline for a timer_list. This is
> + * a legacy function which returns INT32_MAX if the
> + * timer list has no timers or if the earliest timer
> + * expires later than INT32_MAX nanoseconds away.
> + *
> + * Returns: the number of nanoseconds until the earliest
> + * timer expires or INT32_MAX in the situations listed
> + * above
> + */
> +int64_t timerlist_deadline(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_deadline_ns:
> + * @timer_list: the timer list to operate on
> + *
> + * Determine the deadline for a timer_list, i.e.
> + * the number of nanoseconds until the first timer
> + * expires. Return -1 if there are no timers.
> + *
> + * Returns: the number of nanoseconds until the earliest
> + * timer expires -1 if none
> + */
> +int64_t timerlist_deadline_ns(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_getclock:
> + * @timer_list: the timer list to operate on
> + *
> + * Read the clock value associated with a timer list.
> + * The clock value is normally in nanoseconds, but may
> + * not be in some instances (e.g. vm_clock with use_icount).
> + *
> + * Returns: the value of the clock associated with the
> + * timer list.
> + */
> +QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
> +
> +/**
> + * timerlist_run_timers:
> + * @timer_list: the timer list to use
> + *
> + * Call all expired timers associated with the timer list.
> + *
> + * Returns: true if any timer expired
> + */
> +bool timerlist_run_timers(QEMUTimerList *timer_list);
> +
> +/**
> * qemu_timeout_ns_to_ms:
> * @ns: nanosecond timeout value
> *
> @@ -102,6 +261,21 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
>
> QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
> QEMUTimerCB *cb, void *opaque);
> +
> +/**
> + * timer_new:
> + * @timer_list: the timer list to attach the timer to
> + * @scale: the scale value for the tiemr
> + * @cb: the callback to be called when the timer expires
> + * @opaque: the opaque pointer to be passed to the callback
> + *
> + * Creeate a new timer and associate it with @timer_list.
> + *
> + * Returns: a pointer to the timer
> + */
> +QEMUTimer *timer_new(QEMUTimerList *timer_list, int scale,
> + QEMUTimerCB *cb, void *opaque);
> +
> void qemu_free_timer(QEMUTimer *ts);
> void qemu_del_timer(QEMUTimer *ts);
> void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
> @@ -110,11 +284,101 @@ bool qemu_timer_pending(QEMUTimer *ts);
> bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
> uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
>
> +/* New format calling conventions for timers */
> +
> +/**
> + * timer_free:
> + * @ts: the timer
> + *
> + * Free a timer (it must not be on the active list)
> + */
> +static inline void timer_free(QEMUTimer *ts)
> +{
> + qemu_free_timer(ts);
> +}
> +
> +/**
> + * timer_del:
> + * @ts: the timer
> + *
> + * Delete a timer from the active list.
> + */
> +static inline void timer_del(QEMUTimer *ts)
> +{
> + qemu_del_timer(ts);
> +}
> +
> +/**
> + * timer_mod_ns:
> + * @ts: the timer
> + * @expire_time: the expiry time in nanoseconds
> + *
> + * Modify a timer to expire at @expire_time
> + */
> +static inline void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
> +{
> + qemu_mod_timer_ns(ts, expire_time);
> +}
> +
> +/**
> + * timer_mod:
> + * @ts: the timer
> + * @expire_time: the expire time in the units associated with the timer
> + *
> + * Modify a timer to expiry at @expire_time, taking into
> + * account the scale associated with the timer.
> + */
> +static inline void timer_mod(QEMUTimer *ts, int64_t expire_timer)
> +{
> + qemu_mod_timer(ts, expire_timer);
> +}
> +
> +/**
> + * timer_pending:
> + * @ts: the timer
> + *
> + * Determines whether a timer is pending (i.e. is on the
> + * active list of timers, whether or not it has not yet expired).
> + *
> + * Returns: true if the timer is pending
> + */
> +static inline bool timer_pending(QEMUTimer *ts)
> +{
> + return qemu_timer_pending(ts);
> +}
> +
> +/**
> + * timer_expired:
> + * @ts: the timer
> + *
> + * Determines whether a timer has expired.
> + *
> + * Returns: true if the timer has expired
> + */
> +static inline bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
> +{
> + return qemu_timer_expired(timer_head, current_time);
> +}
> +
> +/**
> + * timer_expire_time_ns:
> + * @ts: the timer
> + *
> + * Determine the expiry time of a timer
> + *
> + * Returns: the expiry time in nanoseconds
> + */
> +static inline uint64_t timer_expire_time_ns(QEMUTimer *ts)
> +{
> + return qemu_timer_expire_time_ns(ts);
> +}
> +
> /**
> * qemu_run_timers:
> * @clock: clock on which to operate
> *
> - * Run all the timers associated with a clock.
> + * Run all the timers associated with the default timer list
> + * of a clock.
> *
> * Returns: true if any timer ran.
> */
> @@ -123,7 +387,8 @@ bool qemu_run_timers(QEMUClock *clock);
> /**
> * qemu_run_all_timers:
> *
> - * Run all the timers associated with every clock.
> + * Run all the timers associated with the default timer list
> + * of every clock.
> *
> * Returns: true if any timer ran.
> */
> @@ -156,18 +421,113 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
> return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
> }
>
> +/**
> + * qemu_new_timer_ns:
> + * @clock: the clock to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with nanosecond scale on the default timer list
> + * associated with the clock.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
> void *opaque)
> {
> return qemu_new_timer(clock, SCALE_NS, cb, opaque);
> }
>
> -static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
> +/**
> + * timer_new_ns:
> + * @timer_list: the timer list to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with nanosecond scale on the timer list
> + * specified.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> +static inline QEMUTimer *timer_new_ns(QEMUTimerList *timer_list,
> + QEMUTimerCB *cb,
> + void *opaque)
> +{
> + return timer_new(timer_list, SCALE_NS, cb, opaque);
> +}
> +
> +/**
> + * qemu_new_timer_us:
> + * @clock: the clock to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with microsecond scale on the default timer list
> + * associated with the clock.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> +static inline QEMUTimer *qemu_new_timer_us(QEMUClock *clock,
> + QEMUTimerCB *cb,
> + void *opaque)
> +{
> + return qemu_new_timer(clock, SCALE_US, cb, opaque);
> +}
> +
> +/**
> + * timer_new_us:
> + * @timer_list: the timer list to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with microsecond scale on the timer list
> + * specified.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> +static inline QEMUTimer *timer_new_us(QEMUTimerList *timer_list,
> + QEMUTimerCB *cb,
> + void *opaque)
> +{
> + return timer_new(timer_list, SCALE_US, cb, opaque);
> +}
> +
> +/**
> + * qemu_new_timer_ms:
> + * @clock: the clock to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with millisecond scale on the default timer list
> + * associated with the clock.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> +static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock,
> + QEMUTimerCB *cb,
> void *opaque)
> {
> return qemu_new_timer(clock, SCALE_MS, cb, opaque);
> }
>
> +/**
> + * timer_new_ms:
> + * @timer_list: the timer list to associate with the timer
> + * @callback: the callback to call when the timer expires
> + * @opaque: the opaque pointer to pass to the callback
> + *
> + * Create a new timer with millisecond scale on the timer list
> + * specified.
> + *
> + * Returns: a pointer to the newly created timer
> + */
> +static inline QEMUTimer *timer_new_ms(QEMUTimerList *timer_list,
> + QEMUTimerCB *cb,
> + void *opaque)
> +{
> + return timer_new(timer_list, SCALE_MS, cb, opaque);
> +}
> +
> static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
> {
> return qemu_get_clock_ns(clock) / SCALE_MS;
> diff --git a/qemu-timer.c b/qemu-timer.c
> index 388b98c..46f4029 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -49,18 +49,34 @@
> /* timers */
>
> struct QEMUClock {
> - QEMUTimer *active_timers;
> + QEMUTimerList *default_timerlist;
> + QLIST_HEAD(, QEMUTimerList) timerlists;
>
> NotifierList reset_notifiers;
> int64_t last;
>
> - int type;
> + QEMUClockType type;
> bool enabled;
> };
>
> +QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
> +
> +/* A QEMUTimerList is a list of timers attached to a clock. More
> + * than one QEMUTimerList can be attached to each clock, for instance
> + * used by different AioContexts / threads. Each clock also has
> + * a list of the QEMUTimerLists associated with it, in order that
> + * reenabling the clock can call all the notifiers.
> + */
> +
> +struct QEMUTimerList {
> + QEMUClock *clock;
> + QEMUTimer *active_timers;
> + QLIST_ENTRY(QEMUTimerList) list;
> +};
> +
> struct QEMUTimer {
> int64_t expire_time; /* in nanoseconds */
> - QEMUClock *clock;
> + QEMUTimerList *timer_list;
> QEMUTimerCB *cb;
> void *opaque;
> QEMUTimer *next;
> @@ -93,21 +109,25 @@ static int64_t qemu_next_alarm_deadline(void)
> {
> int64_t delta = INT64_MAX;
> int64_t rtdelta;
> + int64_t hdelta;
>
> - if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
> - delta = vm_clock->active_timers->expire_time -
> - qemu_get_clock_ns(vm_clock);
> + if (!use_icount && vm_clock->enabled &&
> + vm_clock->default_timerlist->active_timers) {
> + delta = vm_clock->default_timerlist->active_timers->expire_time -
> + qemu_get_clock_ns(vm_clock);
> }
> - if (host_clock->enabled && host_clock->active_timers) {
> - int64_t hdelta = host_clock->active_timers->expire_time -
> - qemu_get_clock_ns(host_clock);
> + if (host_clock->enabled &&
> + host_clock->default_timerlist->active_timers) {
> + hdelta = host_clock->default_timerlist->active_timers->expire_time -
> + qemu_get_clock_ns(host_clock);
> if (hdelta < delta) {
> delta = hdelta;
> }
> }
> - if (rt_clock->enabled && rt_clock->active_timers) {
> - rtdelta = (rt_clock->active_timers->expire_time -
> - qemu_get_clock_ns(rt_clock));
> + if (rt_clock->enabled &&
> + rt_clock->default_timerlist->active_timers) {
> + rtdelta = (rt_clock->default_timerlist->active_timers->expire_time -
> + qemu_get_clock_ns(rt_clock));
> if (rtdelta < delta) {
> delta = rtdelta;
> }
> @@ -231,11 +251,42 @@ next:
> }
> }
>
> -QEMUClock *rt_clock;
> -QEMUClock *vm_clock;
> -QEMUClock *host_clock;
> +static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock)
> +{
> + QEMUTimerList *timer_list;
> +
> + /* Assert if we do not have a clock. If you see this
> + * assertion in means that the clocks have not been
> + * initialised before a timerlist is needed. This
> + * normally happens if an AioContext is used before
> + * init_clocks() is called within main().
> + */
> + assert(clock);
> +
> + timer_list = g_malloc0(sizeof(QEMUTimerList));
> + timer_list->clock = clock;
> + QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
> + return timer_list;
> +}
> +
> +QEMUTimerList *timerlist_new(QEMUClockType type)
> +{
> + return timerlist_new_from_clock(qemu_get_clock(type));
> +}
> +
> +void timerlist_free(QEMUTimerList *timer_list)
> +{
> + assert(!timerlist_has_timers(timer_list));
> + if (timer_list->clock) {
> + QLIST_REMOVE(timer_list, list);
> + if (timer_list->clock->default_timerlist == timer_list) {
> + timer_list->clock->default_timerlist = NULL;
> + }
> + }
> + g_free(timer_list);
> +}
>
> -QEMUClock *qemu_clock_new(int type)
> +QEMUClock *qemu_clock_new(QEMUClockType type)
> {
> QEMUClock *clock;
>
> @@ -244,14 +295,21 @@ QEMUClock *qemu_clock_new(int type)
> clock->enabled = true;
> clock->last = INT64_MIN;
> notifier_list_init(&clock->reset_notifiers);
> + clock->default_timerlist = timerlist_new_from_clock(clock);
> return clock;
> }
>
> void qemu_clock_free(QEMUClock *clock)
> {
> + timerlist_free(clock->default_timerlist);
> g_free(clock);
> }
>
> +bool qemu_clock_use_for_deadline(QEMUClock *clock)
> +{
> + return !(use_icount && (clock->type == QEMU_CLOCK_VIRTUAL));
> +}
> +
> void qemu_clock_enable(QEMUClock *clock, bool enabled)
> {
> bool old = clock->enabled;
> @@ -261,24 +319,36 @@ void qemu_clock_enable(QEMUClock *clock, bool enabled)
> }
> }
>
> -int64_t qemu_clock_has_timers(QEMUClock *clock)
> +bool timerlist_has_timers(QEMUTimerList *timer_list)
> {
> - return !!clock->active_timers;
> + return !!timer_list->active_timers;
> }
>
> -int64_t qemu_clock_expired(QEMUClock *clock)
> +bool qemu_clock_has_timers(QEMUClock *clock)
> {
> - return (clock->active_timers &&
> - clock->active_timers->expire_time < qemu_get_clock_ns(clock));
> + return timerlist_has_timers(clock->default_timerlist);
> }
>
> -int64_t qemu_clock_deadline(QEMUClock *clock)
> +bool timerlist_expired(QEMUTimerList *timer_list)
> +{
> + return (timer_list->active_timers &&
> + timer_list->active_timers->expire_time <
> + qemu_get_clock_ns(timer_list->clock));
> +}
> +
> +bool qemu_clock_expired(QEMUClock *clock)
> +{
> + return timerlist_expired(clock->default_timerlist);
> +}
> +
> +int64_t timerlist_deadline(QEMUTimerList *timer_list)
> {
> /* To avoid problems with overflow limit this to 2^32. */
> int64_t delta = INT32_MAX;
>
> - if (clock->enabled && clock->active_timers) {
> - delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
> + if (timer_list->clock->enabled && timer_list->active_timers) {
> + delta = timer_list->active_timers->expire_time -
> + qemu_get_clock_ns(timer_list->clock);
> }
> if (delta < 0) {
> delta = 0;
> @@ -286,20 +356,26 @@ int64_t qemu_clock_deadline(QEMUClock *clock)
> return delta;
> }
>
> +int64_t qemu_clock_deadline(QEMUClock *clock)
> +{
> + return timerlist_deadline(clock->default_timerlist);
> +}
> +
> /*
> * As above, but return -1 for no deadline, and do not cap to 2^32
> * as we know the result is always positive.
> */
>
> -int64_t qemu_clock_deadline_ns(QEMUClock *clock)
> +int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
> {
> int64_t delta;
>
> - if (!clock->enabled || !clock->active_timers) {
> + if (!timer_list->clock->enabled || !timer_list->active_timers) {
> return -1;
> }
>
> - delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
> + delta = timer_list->active_timers->expire_time -
> + qemu_get_clock_ns(timer_list->clock);
>
> if (delta <= 0) {
> return 0;
> @@ -308,6 +384,21 @@ int64_t qemu_clock_deadline_ns(QEMUClock *clock)
> return delta;
> }
>
> +int64_t qemu_clock_deadline_ns(QEMUClock *clock)
> +{
> + return timerlist_deadline_ns(clock->default_timerlist);
> +}
> +
> +QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list)
> +{
> + return timer_list->clock;
> +}
> +
> +QEMUTimerList *qemu_clock_get_default_timerlist(QEMUClock *clock)
> +{
> + return clock->default_timerlist;
> +}
> +
> /* Transition function to convert a nanosecond timeout to ms
> * This is used where a system does not support ppoll
> */
> @@ -356,19 +447,26 @@ int qemu_poll_ns(GPollFD *fds, uint nfds, int64_t timeout)
> }
>
>
> -QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
> - QEMUTimerCB *cb, void *opaque)
> +QEMUTimer *timer_new(QEMUTimerList *timer_list, int scale,
> + QEMUTimerCB *cb, void *opaque)
> {
> QEMUTimer *ts;
>
> ts = g_malloc0(sizeof(QEMUTimer));
> - ts->clock = clock;
> + ts->timer_list = timer_list;
> ts->cb = cb;
> ts->opaque = opaque;
> ts->scale = scale;
> return ts;
> }
>
> +QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
> + QEMUTimerCB *cb, void *opaque)
> +{
> + return timer_new(clock->default_timerlist,
> + scale, cb, opaque);
> +}
> +
> void qemu_free_timer(QEMUTimer *ts)
> {
> g_free(ts);
> @@ -381,7 +479,7 @@ void qemu_del_timer(QEMUTimer *ts)
>
> /* NOTE: this code must be signal safe because
> qemu_timer_expired() can be called from a signal. */
> - pt = &ts->clock->active_timers;
> + pt = &ts->timer_list->active_timers;
> for(;;) {
> t = *pt;
> if (!t)
> @@ -405,7 +503,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
> /* add the timer in the sorted list */
> /* NOTE: this code must be signal safe because
> qemu_timer_expired() can be called from a signal. */
> - pt = &ts->clock->active_timers;
> + pt = &ts->timer_list->active_timers;
> for(;;) {
> t = *pt;
> if (!qemu_timer_expired_ns(t, expire_time)) {
> @@ -418,12 +516,12 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
> *pt = ts;
>
> /* Rearm if necessary */
> - if (pt == &ts->clock->active_timers) {
> + if (pt == &ts->timer_list->active_timers) {
> if (!alarm_timer->pending) {
> qemu_rearm_alarm_timer(alarm_timer);
> }
> /* Interrupt execution to force deadline recalculation. */
> - qemu_clock_warp(ts->clock);
> + qemu_clock_warp(ts->timer_list->clock);
> if (use_icount) {
> qemu_notify_event();
> }
> @@ -438,7 +536,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
> bool qemu_timer_pending(QEMUTimer *ts)
> {
> QEMUTimer *t;
> - for (t = ts->clock->active_timers; t != NULL; t = t->next) {
> + for (t = ts->timer_list->active_timers; t != NULL; t = t->next) {
> if (t == ts) {
> return true;
> }
> @@ -451,23 +549,24 @@ bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
> return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
> }
>
> -bool qemu_run_timers(QEMUClock *clock)
> +bool timerlist_run_timers(QEMUTimerList *timer_list)
> {
> QEMUTimer *ts;
> int64_t current_time;
> bool progress = false;
>
> - if (!clock->enabled)
> + if (!timer_list->clock->enabled) {
> return progress;
> + }
>
> - current_time = qemu_get_clock_ns(clock);
> + current_time = qemu_get_clock_ns(timer_list->clock);
> for(;;) {
> - ts = clock->active_timers;
> + ts = timer_list->active_timers;
> if (!qemu_timer_expired_ns(ts, current_time)) {
> break;
> }
> /* remove timer from the list before calling the callback */
> - clock->active_timers = ts->next;
> + timer_list->active_timers = ts->next;
> ts->next = NULL;
>
> /* run the callback (the timer list can be modified) */
> @@ -477,6 +576,11 @@ bool qemu_run_timers(QEMUClock *clock)
> return progress;
> }
>
> +bool qemu_run_timers(QEMUClock *clock)
> +{
> + return timerlist_run_timers(clock->default_timerlist);
> +}
> +
> int64_t qemu_get_clock_ns(QEMUClock *clock)
> {
> int64_t now, last;
> @@ -514,11 +618,13 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
>
> void init_clocks(void)
> {
> - if (!rt_clock) {
> - rt_clock = qemu_clock_new(QEMU_CLOCK_REALTIME);
> - vm_clock = qemu_clock_new(QEMU_CLOCK_VIRTUAL);
> - host_clock = qemu_clock_new(QEMU_CLOCK_HOST);
> + QEMUClockType type;
> + for (type = 0; type < QEMU_CLOCK_MAX; type++) {
> + if (!qemu_clocks[type]) {
> + qemu_clocks[type] = qemu_clock_new(type);
> + }
> }
> +
> #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
> prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
> #endif
> @@ -535,9 +641,10 @@ bool qemu_run_all_timers(void)
> alarm_timer->pending = false;
>
> /* vm time timers */
> - progress |= qemu_run_timers(vm_clock);
> - progress |= qemu_run_timers(rt_clock);
> - progress |= qemu_run_timers(host_clock);
> + QEMUClockType type;
> + for (type = 0; type < QEMU_CLOCK_MAX; type++) {
> + progress |= qemu_run_timers(qemu_get_clock(type));
> + }
>
> /* rearm timer, if not periodic */
> if (alarm_timer->expired) {
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-07 11:31 ` Stefan Hajnoczi
@ 2013-08-08 6:21 ` liu ping fan
2013-08-08 6:37 ` Alex Bligh
2 siblings, 1 reply; 31+ messages in thread
From: liu ping fan @ 2013-08-08 6:21 UTC (permalink / raw)
To: Alex Bligh
Cc: Kevin Wolf, Anthony Liguori, qemu-devel, Stefan Hajnoczi,
Paolo Bonzini, MORITA Kazutaka, rth
On Wed, Aug 7, 2013 at 7:48 AM, Alex Bligh <alex@alex.org.uk> wrote:
> Add qemu_clock_free and expose qemu_new_clock as qemu_clock_new.
>
> Expose clock types.
>
> Signed-off-by: Alex Bligh <alex@alex.org.uk>
> ---
> include/qemu/timer.h | 22 ++++++++++++++++++++++
> qemu-timer.c | 11 ++++++-----
> 2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/include/qemu/timer.h b/include/qemu/timer.h
> index 9dd206c..3dd20bf 100644
> --- a/include/qemu/timer.h
> +++ b/include/qemu/timer.h
> @@ -11,6 +11,10 @@
> #define SCALE_US 1000
> #define SCALE_NS 1
>
> +#define QEMU_CLOCK_REALTIME 0
> +#define QEMU_CLOCK_VIRTUAL 1
> +#define QEMU_CLOCK_HOST 2
> +
> typedef struct QEMUClock QEMUClock;
> typedef void QEMUTimerCB(void *opaque);
>
> @@ -32,6 +36,24 @@ extern QEMUClock *vm_clock;
> the virtual clock. */
> extern QEMUClock *host_clock;
>
> +/**
> + * qemu_clock_new:
> + * @type: the type of clock to be created
> + *
> + * Create a new clock of type @type
> + *
> + * Returns: A pointer to the clock object
> + */
> +QEMUClock *qemu_clock_new(int type);
> +
> +/**
> + * qemu_clock_free:
> + * @clock: the clock to free
> + *
> + * Free clock object @clock
> + */
> +void qemu_clock_free(QEMUClock *clock);
Go through this series, I can not find the caller of it. I think as
clock source, the QEMUClock can not be destroyed, except exit(2), so
could we let exit to reclaim the resource? Or at least, this interface
should not be public.
> +
> int64_t qemu_get_clock_ns(QEMUClock *clock);
> int64_t qemu_clock_has_timers(QEMUClock *clock);
> int64_t qemu_clock_expired(QEMUClock *clock);
> diff --git a/qemu-timer.c b/qemu-timer.c
> index b2d95e2..531aa05 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -40,10 +40,6 @@
> /***********************************************************/
> /* timers */
>
> -#define QEMU_CLOCK_REALTIME 0
> -#define QEMU_CLOCK_VIRTUAL 1
> -#define QEMU_CLOCK_HOST 2
> -
> struct QEMUClock {
> QEMUTimer *active_timers;
>
> @@ -231,7 +227,7 @@ QEMUClock *rt_clock;
> QEMUClock *vm_clock;
> QEMUClock *host_clock;
>
> -static QEMUClock *qemu_new_clock(int type)
> +QEMUClock *qemu_clock_new(int type)
> {
> QEMUClock *clock;
>
> @@ -243,6 +239,11 @@ static QEMUClock *qemu_new_clock(int type)
> return clock;
> }
>
> +void qemu_clock_free(QEMUClock *clock)
> +{
> + g_free(clock);
> +}
> +
> void qemu_clock_enable(QEMUClock *clock, bool enabled)
> {
> bool old = clock->enabled;
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types
2013-08-08 6:21 ` liu ping fan
@ 2013-08-08 6:37 ` Alex Bligh
0 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-08 6:37 UTC (permalink / raw)
To: liu ping fan
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, qemu-devel,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Pingfan,
--On 8 August 2013 14:21:34 +0800 liu ping fan <qemulist@gmail.com> wrote:
> Go through this series, I can not find the caller of it. I think as
> clock source, the QEMUClock can not be destroyed, except exit(2), so
> could we let exit to reclaim the resource? Or at least, this interface
> should not be public.
Yes I think this a holdover from when I allowed multiple qemu clocks
to avoid changing the API.
--
Alex Bligh
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
` (21 preceding siblings ...)
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 22/22] aio / timers: Remove legacy qemu_clock_deadline & qemu_timerlist_deadline Alex Bligh
@ 2013-08-08 7:52 ` Alex Bligh
22 siblings, 0 replies; 31+ messages in thread
From: Alex Bligh @ 2013-08-08 7:52 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Anthony Liguori, Alex Bligh, liu ping fan,
Stefan Hajnoczi, Paolo Bonzini, MORITA Kazutaka, rth
Pingfan has given me an idea here. I can convert the API over to solely
use QEMUClockType and not even expose struct QEMUClock *. I'll do this in
v8. I have that working here and the API is much cleaner. Now I just need
to reengineer it into git.
Alex
--On 7 August 2013 00:48:54 +0100 Alex Bligh <alex@alex.org.uk> wrote:
> This patch series adds support for timers attached to an AioContext clock
> which get called within aio_poll.
>
> In doing so it removes alarm timers and moves to use ppoll where possible.
>
> This patch set 'sort of' passes make check (see below for caveat)
> including a new test harness for the aio timers, but has not been
> tested much beyond that. In particular, the win32 changes have not
> even been compile tested. Equally, alterations to use_icount
> are untested.
>
> Caveat: I have had to alter tests/test-aio.c so the following error
> no longer occurs.
>
> ERROR:tests/test-aio.c:346:test_wait_event_notifier_noflush: assertion
> failed: (aio_poll(ctx, false))
>
> As gar as I can tell, this check was incorrect, in that it checking
> aio_poll makes progress when in fact it should not make progress. I
> fixed an issue where aio_poll was (as far as I can tell) wrongly
> returning true on a timeout, and that generated this error.
>
> Note also the comment on patch 18 in relation to a possible bug
> in cpus.c.
>
> Changes since v6:
> * Fix build failure in vnc-auth-sasl.c
> * Split first patch into 3
> * Add assert on timerlist_free
> * Fix ==/= error on qemu_clock_use_for_deadline
> * Remove unnecessary cast in aio_timerlist_notify
> * Fix bad deadline comparison in aio_ctx_check
> * Add assert to timerlist_new_from_clock to check init_clocks
> * Use timer_list not tl
> * Change default_timerlistgroup to main_loop_timerlistgroup
> * Add comment on commit for qemu_clock_use_for_deadline
> * Fixed various include file issues
> * Convert *_has_timers and *_has_expired to return bool
> * Make loop variable consistent when looping through clock types
> * Add documentation to existing qemu_timer calls
> * Remove qemu_clock_deadline and move to qemu_clock_deadline_ns
>
> Changes since v5:
> * Rebase onto master (b9ac5d9)
> * Fix spacing in typedef QEMUTimerList
> * Rename 'QEMUClocks' extern to 'qemu_clocks'
>
> Changes since v4:
> * Rename qemu_timerlist_ functions to timer_list (per Paolo Bonzini)
> * Rename qemu_timer_.*timerlist.* to timer_ (per Paolo Bonzini)
> * Use enum for QEMUClockType
> * Put clocks into an array; remove global variables
> * Introduce QEMUTimerListGroup - a timeliest of each type
> * Add a QEMUTimerListGroup to AioContext
> * Use a callback on timer modification, rather than binding in
> AioContext into the timeliest
> * Make cpus.c iterate over all timerlists when it does a notify
> * Make cpus.c icount timeout use soonest timeout
> across all timerlists
>
> Changes since v3:
> * Split up QEMUClock and QEMUClock list
> * Improve commenting
> * Fix comment in vl.c
> * Change test/test-aio.c to reflect correct behaviour in aio_poll.
>
> Changes since v2:
> * Reordered to remove alarm timers last
> * Added prctl(PR_SET_TIMERSLACK, 1, ...)
> * Renamed qemu_g_poll_ns to qemu_poll_ns
> * Moved declaration of above & drop glib types
> * Do not use a global list of qemu clocks
> * Add AioContext * to QEMUClock
> * Split up conversion to use ppoll and timers
> * Indentation fix
> * Fix aio_win32.c aio_poll to return progress
> * aio_notify / qemu_notify when timers are modified
> * change comment in deprecation of clock options
>
> Alex Bligh (22):
> aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock
> types
> aio / timers: add qemu-timer.c utility functions
> aio / timers: Consistent treatment of disabled clocks for deadlines
> aio / timers: add ppoll support with qemu_poll_ns
> aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer
> slack
> aio / timers: Make qemu_run_timers and qemu_run_all_timers return
> progress
> aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList
> aio / timers: Untangle include files
> aio / timers: Add QEMUTimerListGroup and helper functions
> aio / timers: Add QEMUTimerListGroup to AioContext
> aio / timers: Add a notify callback to QEMUTimerList
> aio / timers: aio_ctx_prepare sets timeout from AioContext timers
> aio / timers: Add aio_timer_new wrapper
> aio / timers: Convert aio_poll to use AioContext timers' deadline
> aio / timers: Convert mainloop to use timeout
> aio / timers: On timer modification, qemu_notify or aio_notify
> aio / timers: Introduce new API qemu_timer_new and friends
> aio / timers: Use all timerlists in icount warp calculations
> aio / timers: Add documentation and new format calls
> aio / timers: Remove alarm timers
> aio / timers: Add test harness for AioContext timers
> aio / timers: Remove legacy qemu_clock_deadline &
> qemu_timerlist_deadline
>
> aio-posix.c | 20 +-
> aio-win32.c | 22 +-
> async.c | 20 +-
> configure | 37 ++
> cpus.c | 46 ++-
> dma-helpers.c | 1 +
> hw/dma/xilinx_axidma.c | 1 +
> hw/timer/arm_timer.c | 1 +
> hw/timer/exynos4210_mct.c | 1 +
> hw/timer/exynos4210_pwm.c | 1 +
> hw/timer/grlib_gptimer.c | 2 +
> hw/timer/imx_epit.c | 1 +
> hw/timer/imx_gpt.c | 1 +
> hw/timer/lm32_timer.c | 1 +
> hw/timer/puv3_ost.c | 1 +
> hw/timer/sh_timer.c | 1 +
> hw/timer/slavio_timer.c | 1 +
> hw/timer/xilinx_timer.c | 1 +
> hw/tpm/tpm_tis.c | 1 +
> hw/usb/hcd-uhci.c | 1 +
> include/block/aio.h | 23 ++
> include/block/block_int.h | 1 +
> include/block/coroutine.h | 2 +
> include/qemu/timer.h | 857
> +++++++++++++++++++++++++++++++++++++++++++-- main-loop.c
> | 49 ++-
> migration-exec.c | 1 +
> migration-fd.c | 1 +
> migration-tcp.c | 1 +
> migration-unix.c | 1 +
> migration.c | 1 +
> nbd.c | 1 +
> net/net.c | 1 +
> net/socket.c | 1 +
> qemu-coroutine-io.c | 1 +
> qemu-io-cmds.c | 1 +
> qemu-nbd.c | 1 +
> qemu-timer.c | 803
> +++++++++++++++--------------------------- qtest.c |
> 2 +-
> slirp/misc.c | 1 +
> tests/test-aio.c | 144 +++++++-
> tests/test-thread-pool.c | 3 +
> thread-pool.c | 1 +
> ui/vnc-auth-sasl.h | 1 +
> ui/vnc-auth-vencrypt.c | 2 +-
> ui/vnc-ws.c | 1 +
> vl.c | 4 +-
> 46 files changed, 1480 insertions(+), 586 deletions(-)
>
> --
> 1.7.9.5
>
>
--
Alex Bligh
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2013-08-08 7:53 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-06 23:48 [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 01/22] aio / timers: Add qemu_clock_free and expose qemu_clock_new and clock types Alex Bligh
2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-07 11:37 ` Alex Bligh
2013-08-07 15:47 ` Paolo Bonzini
2013-08-07 11:31 ` Stefan Hajnoczi
2013-08-08 6:21 ` liu ping fan
2013-08-08 6:37 ` Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 02/22] aio / timers: add qemu-timer.c utility functions Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 03/22] aio / timers: Consistent treatment of disabled clocks for deadlines Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 04/22] aio / timers: add ppoll support with qemu_poll_ns Alex Bligh
2013-08-06 23:48 ` [Qemu-devel] [RFC] [PATCHv7 05/22] aio / timers: Add prctl(PR_SET_TIMERSLACK, 1, ...) to reduce timer slack Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 06/22] aio / timers: Make qemu_run_timers and qemu_run_all_timers return progress Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 07/22] aio / timers: Split QEMUClock into QEMUClock and QEMUTimerList Alex Bligh
2013-08-08 6:12 ` liu ping fan
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 08/22] aio / timers: Untangle include files Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 09/22] aio / timers: Add QEMUTimerListGroup and helper functions Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 10/22] aio / timers: Add QEMUTimerListGroup to AioContext Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 11/22] aio / timers: Add a notify callback to QEMUTimerList Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 12/22] aio / timers: aio_ctx_prepare sets timeout from AioContext timers Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 13/22] aio / timers: Add aio_timer_new wrapper Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 14/22] aio / timers: Convert aio_poll to use AioContext timers' deadline Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 15/22] aio / timers: Convert mainloop to use timeout Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 16/22] aio / timers: On timer modification, qemu_notify or aio_notify Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 17/22] aio / timers: Introduce new API qemu_timer_new and friends Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 18/22] aio / timers: Use all timerlists in icount warp calculations Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 19/22] aio / timers: Add documentation and new format calls Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 20/22] aio / timers: Remove alarm timers Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 21/22] aio / timers: Add test harness for AioContext timers Alex Bligh
2013-08-06 23:49 ` [Qemu-devel] [RFC] [PATCHv7 22/22] aio / timers: Remove legacy qemu_clock_deadline & qemu_timerlist_deadline Alex Bligh
2013-08-08 7:52 ` [Qemu-devel] [RFC] [PATCHv7 00/22] aio / timers: Add AioContext timers and use ppoll Alex Bligh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).