From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com,
Jes.Sorensen@redhat.com, mdroth@linux.vnet.ibm.com,
markus_mueller@de.ibm.com, aliguori@linux.vnet.ibm.com,
abeekhof@redhat.com
Subject: [Qemu-devel] [RFC][PATCH v7 03/16] Make qemu timers available for tools
Date: Mon, 7 Mar 2011 14:10:29 -0600 [thread overview]
Message-ID: <1299528642-23631-4-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1299528642-23631-1-git-send-email-mdroth@linux.vnet.ibm.com>
To be able to use qemu_mod_timer() and friends to register timeout
events for virtagent's qemu-va tool, we need to do the following:
Move several blocks of code out of cpus.c that handle initialization
of qemu's io_thread_fd and working with it via
qemu_notify_event()/qemu_event_read()/etc, and make them accessible
as backend functions to both the emulator code and qemu-tool.c via
wrapper functions within cpus.c and qemu-tool.c, respectively. These
have been added to qemu-ioh.c, where similar treatment was given to
qemu_set_fd_handler() and friends.
Some of these wrapper functions lack declarations when being
built into tools, so we add those via qemu-tool.h, which can be included
by a tool to access them. With these changes we can drive timers in a
tool linking it against qemu-timer.o and then implementing something
similar to the main i/o loop in vl.c:
init_clocks();
configure_alarms("dynticks");
if (init_timer_alarm() < 0) {
errx(EXIT_FAILURE, "could not initialize alarm timer");
}
while (running) {
//do work
qemu_run_all_timers();
}
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
cpus.c | 83 +++++++--------------------------------------------
qemu-ioh.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-ioh.h | 9 +++++
qemu-tool.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
qemu-tool.h | 26 ++++++++++++++++
5 files changed, 231 insertions(+), 74 deletions(-)
create mode 100644 qemu-tool.h
diff --git a/cpus.c b/cpus.c
index 0f33945..507a660 100644
--- a/cpus.c
+++ b/cpus.c
@@ -246,64 +246,12 @@ static int io_thread_fd = -1;
static void qemu_event_increment(void)
{
- /* Write 8 bytes to be compatible with eventfd. */
- static const uint64_t val = 1;
- ssize_t ret;
-
- if (io_thread_fd == -1) {
- return;
- }
- do {
- ret = write(io_thread_fd, &val, sizeof(val));
- } while (ret < 0 && errno == EINTR);
-
- /* EAGAIN is fine, a read must be pending. */
- if (ret < 0 && errno != EAGAIN) {
- fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
- strerror(errno));
- exit (1);
- }
-}
-
-static void qemu_event_read(void *opaque)
-{
- int fd = (unsigned long)opaque;
- ssize_t len;
- char buffer[512];
-
- /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
- do {
- len = read(fd, buffer, sizeof(buffer));
- } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
+ return iothread_event_increment(&io_thread_fd);
}
static int qemu_event_init(void)
{
- int err;
- int fds[2];
-
- err = qemu_eventfd(fds);
- if (err == -1) {
- return -errno;
- }
- err = fcntl_setfl(fds[0], O_NONBLOCK);
- if (err < 0) {
- goto fail;
- }
- err = fcntl_setfl(fds[1], O_NONBLOCK);
- if (err < 0) {
- goto fail;
- }
- qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
- (void *)(unsigned long)fds[0]);
-
- io_thread_fd = fds[1];
- return 0;
-
-fail:
- close(fds[0]);
- close(fds[1]);
- return err;
+ return iothread_event_init(&io_thread_fd);
}
static void dummy_signal(int sig)
@@ -410,28 +358,14 @@ static void qemu_kvm_eat_signals(CPUState *env)
HANDLE qemu_event_handle;
-static void dummy_event_handler(void *opaque)
-{
-}
-
static int qemu_event_init(void)
{
- qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!qemu_event_handle) {
- fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
- return -1;
- }
- qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
- return 0;
+ return win32_event_init(&qemu_event_handle);
}
static void qemu_event_increment(void)
{
- if (!SetEvent(qemu_event_handle)) {
- fprintf(stderr, "qemu_event_increment: SetEvent failed: %ld\n",
- GetLastError());
- exit (1);
- }
+ win32_event_increment(&qemu_event_handle);
}
static void qemu_kvm_eat_signals(CPUState *env)
@@ -564,11 +498,10 @@ void qemu_cpu_kick_self(void)
#endif
}
-void qemu_notify_event(void)
+static void qemu_stop_all_vcpus(void)
{
CPUState *env = cpu_single_env;
- qemu_event_increment ();
if (env) {
cpu_exit(env);
}
@@ -578,6 +511,12 @@ void qemu_notify_event(void)
exit_request = 1;
}
+void qemu_notify_event(void)
+{
+ qemu_event_increment();
+ qemu_stop_all_vcpus();
+}
+
void qemu_mutex_lock_iothread(void) {}
void qemu_mutex_unlock_iothread(void) {}
diff --git a/qemu-ioh.c b/qemu-ioh.c
index cc71470..5c3f94c 100644
--- a/qemu-ioh.c
+++ b/qemu-ioh.c
@@ -22,7 +22,11 @@
* THE SOFTWARE.
*/
#include "qemu-ioh.h"
+#include "qemu-char.h"
#include "qlist.h"
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
/* XXX: fd_read_poll should be suppressed, but an API change is
necessary in the character devices to suppress fd_can_read(). */
@@ -113,3 +117,94 @@ void qemu_process_fd_handlers2(void *ioh_record_list, const fd_set *rfds,
}
}
}
+
+#ifndef _WIN32
+void iothread_event_increment(int *io_thread_fd)
+{
+ /* Write 8 bytes to be compatible with eventfd. */
+ static const uint64_t val = 1;
+ ssize_t ret;
+
+ if (*io_thread_fd == -1) {
+ return;
+ }
+
+ do {
+ ret = write(*io_thread_fd, &val, sizeof(val));
+ } while (ret < 0 && errno == EINTR);
+
+ /* EAGAIN is fine, a read must be pending. */
+ if (ret < 0 && errno != EAGAIN) {
+ fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
+ strerror(errno));
+ exit (1);
+ }
+}
+
+static void qemu_event_read(void *opaque)
+{
+ int fd = (unsigned long)opaque;
+ ssize_t len;
+ char buffer[512];
+
+ /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
+ do {
+ len = read(fd, buffer, sizeof(buffer));
+ } while (len == -1 && errno == EINTR);
+}
+
+
+int iothread_event_init(int *io_thread_fd)
+{
+ int err;
+ int fds[2];
+
+ err = qemu_eventfd(fds);
+ if (err == -1)
+ return -errno;
+
+ err = fcntl_setfl(fds[0], O_NONBLOCK);
+ if (err < 0)
+ goto fail;
+
+ err = fcntl_setfl(fds[1], O_NONBLOCK);
+ if (err < 0) {
+ goto fail;
+ }
+
+ qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
+ (void *)(unsigned long)fds[0]);
+
+ *io_thread_fd = fds[1];
+ return 0;
+
+fail:
+ close(fds[0]);
+ close(fds[1]);
+ return err;
+}
+#else
+static void dummy_event_handler(void *opaque)
+{
+}
+
+int win32_event_init(HANDLE *qemu_event_handle)
+{
+ *qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!qemu_event_handle) {
+ fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
+ return -1;
+ }
+ qemu_add_wait_object(*qemu_event_handle, dummy_event_handler, NULL);
+ return 0;
+}
+
+void win32_event_increment(HANDLE *qemu_event_handle)
+{
+ if (!SetEvent(*qemu_event_handle)) {
+ fprintf(stderr, "qemu_event_increment: SetEvent failed: %ld\n",
+ GetLastError());
+ exit (1);
+ }
+}
+#endif
diff --git a/qemu-ioh.h b/qemu-ioh.h
index 7c6e833..2c714a9 100644
--- a/qemu-ioh.h
+++ b/qemu-ioh.h
@@ -31,4 +31,13 @@ void qemu_get_fdset2(void *ioh_record_list, int *nfds, fd_set *rfds,
void qemu_process_fd_handlers2(void *ioh_record_list, const fd_set *rfds,
const fd_set *wfds, const fd_set *xfds);
+
+#ifndef _WIN32
+void iothread_event_increment(int *io_thread_fd);
+int iothread_event_init(int *io_thread_fd);
+#else
+int win32_event_init(HANDLE *qemu_event_handle);
+void win32_event_increment(HANDLE *qemu_event_handle);
+#endif
+
#endif
diff --git a/qemu-tool.c b/qemu-tool.c
index 78d3532..027ea31 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -12,6 +12,7 @@
*/
#include "qemu-common.h"
+#include "qemu-tool.h"
#include "monitor.h"
#include "qemu-timer.h"
#include "qemu-log.h"
@@ -19,12 +20,11 @@
#include <sys/time.h>
-QEMUClock *rt_clock;
+QEMUClock *rtc_clock;
FILE *logfile;
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
QLIST_HEAD_INITIALIZER(io_handlers);
-
struct QEMUBH
{
QEMUBHFunc *cb;
@@ -134,3 +134,91 @@ void qemu_process_fd_handlers(const fd_set *rfds, const fd_set *wfds,
{
return qemu_process_fd_handlers2(&io_handlers, rfds, wfds, xfds);
}
+
+#ifndef _WIN32
+static int io_thread_fd = -1;
+
+void qemu_event_increment(void)
+{
+ return iothread_event_increment(&io_thread_fd);
+}
+
+int qemu_event_init(void)
+{
+ return iothread_event_init(&io_thread_fd);
+}
+#else
+HANDLE qemu_event_handle;
+
+int qemu_event_init(void)
+{
+ return win32_event_init(&qemu_event_handle);
+}
+
+void qemu_event_increment(void)
+{
+ win32_event_increment(&qemu_event_handle);
+}
+#endif
+
+void qemu_notify_event(void)
+{
+ qemu_event_increment ();
+}
+
+/*
+ * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
+ */
+int qemu_eventfd(int fds[2])
+{
+#ifdef CONFIG_EVENTFD
+ int ret;
+
+ ret = eventfd(0, 0);
+ if (ret >= 0) {
+ fds[0] = ret;
+ qemu_set_cloexec(ret);
+ if ((fds[1] = dup(ret)) == -1) {
+ close(ret);
+ return -1;
+ }
+ qemu_set_cloexec(fds[1]);
+ return 0;
+ }
+
+ if (errno != ENOSYS) {
+ return -1;
+ }
+#endif
+
+ return qemu_pipe(fds);
+}
+
+void qemu_put_be64(QEMUFile *f, uint64_t v)
+{
+}
+
+uint64_t qemu_get_be64(QEMUFile *f)
+{
+ return 0;
+}
+
+const VMStateInfo vmstate_info_int64;
+int use_icount = 0;
+int vm_running = 1;
+int64_t qemu_icount;
+
+int vmstate_register(DeviceState *dev, int instance_id,
+ const VMStateDescription *vmsd, void *opaque)
+{
+ return 0;
+}
+int64_t cpu_get_icount(void) {
+ return 0;
+}
+
+VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
+ void *opaque)
+{
+ return NULL;
+}
diff --git a/qemu-tool.h b/qemu-tool.h
new file mode 100644
index 0000000..fd693cf
--- /dev/null
+++ b/qemu-tool.h
@@ -0,0 +1,26 @@
+#ifndef QEMU_TOOL_H
+#define QEMU_TOOL_H
+
+#include "qemu-common.h"
+
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
+typedef void VMStateDescription;
+typedef int VMStateInfo;
+
+#ifndef _WIN32
+void qemu_event_increment(void);
+int qemu_event_init(void);
+#else
+int qemu_event_init(void);
+void qemu_event_increment(void);
+#endif
+
+void qemu_put_be64(QEMUFile *f, uint64_t v);
+uint64_t qemu_get_be64(QEMUFile *f);
+int vmstate_register(DeviceState *dev, int instance_id,
+ const VMStateDescription *vmsd, void *opaque);
+
+#endif
--
1.7.0.4
next prev parent reply other threads:[~2011-03-07 20:43 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-07 20:10 [Qemu-devel] [RFC][PATCH v7 00/16] virtagent: host/guest communication agent Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 01/16] Move code related to fd handlers into utility functions Michael Roth
2011-03-09 13:58 ` [Qemu-devel] " Paolo Bonzini
2011-03-09 14:11 ` Michael Roth
2011-03-09 14:38 ` Paolo Bonzini
2011-03-09 15:01 ` Michael Roth
2011-03-09 15:15 ` Paolo Bonzini
2011-03-09 14:28 ` Anthony Liguori
2011-03-09 14:40 ` Anthony Liguori
2011-03-09 14:45 ` Paolo Bonzini
2011-03-09 15:39 ` Anthony Liguori
2011-03-09 14:09 ` Paolo Bonzini
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 02/16] Add qemu_set_fd_handler() wrappers to qemu-tools.c Michael Roth
2011-03-07 20:10 ` Michael Roth [this message]
2011-03-09 10:33 ` [Qemu-devel] Re: [RFC][PATCH v7 03/16] Make qemu timers available for tools Jes Sorensen
2011-03-09 13:04 ` Michael Roth
2011-03-09 13:06 ` Jes Sorensen
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 04/16] virtagent: bi-directional RPC handling logic Michael Roth
2011-03-07 21:24 ` [Qemu-devel] " Adam Litke
2011-03-07 22:35 ` Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 05/16] virtagent: common helpers and init routines Michael Roth
2011-03-09 10:38 ` [Qemu-devel] " Jes Sorensen
2011-03-09 13:17 ` Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 06/16] virtagent: transport definitions Michael Roth
2011-03-07 21:38 ` [Qemu-devel] " Adam Litke
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 07/16] virtagent: base RPC client definitions Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 08/16] virtagnet: base RPC server definitions Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 09/16] virtagent: add va_capabilities HMP/QMP command Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 10/16] virtagent: add "ping" RPC to server Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 11/16] virtagent: add va_ping HMP/QMP command Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 12/16] virtagent: add "shutdown" RPC to server Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 13/16] virtagent: add va_shutdown HMP/QMP command Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 14/16] virtagent: add virtagent chardev Michael Roth
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 15/16] virtagent: qemu-va, system-level virtagent guest agent Michael Roth
2011-03-09 10:48 ` [Qemu-devel] " Jes Sorensen
2011-03-07 20:10 ` [Qemu-devel] [RFC][PATCH v7 16/16] virtagent: add bits to build virtagent host/guest components Michael Roth
2011-03-07 21:43 ` [Qemu-devel] Re: [RFC][PATCH v7 00/16] virtagent: host/guest communication agent Anthony Liguori
2011-03-07 22:49 ` Michael Roth
2011-03-07 22:56 ` Anthony Liguori
2011-03-08 0:11 ` Michael Roth
2011-03-08 0:24 ` Anthony Liguori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1299528642-23631-4-git-send-email-mdroth@linux.vnet.ibm.com \
--to=mdroth@linux.vnet.ibm.com \
--cc=Jes.Sorensen@redhat.com \
--cc=abeekhof@redhat.com \
--cc=agl@linux.vnet.ibm.com \
--cc=aliguori@linux.vnet.ibm.com \
--cc=markus_mueller@de.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).