[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC][PATCH v7 03/16] Make qemu timers available for tools
From: |
Michael Roth |
Subject: |
[Qemu-devel] [RFC][PATCH v7 03/16] Make qemu timers available for tools |
Date: |
Mon, 7 Mar 2011 14:10:29 -0600 |
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 <address@hidden>
---
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
- [Qemu-devel] [RFC][PATCH v7 12/16] virtagent: add "shutdown" RPC to server, (continued)
- [Qemu-devel] [RFC][PATCH v7 12/16] virtagent: add "shutdown" RPC to server, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 14/16] virtagent: add virtagent chardev, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 07/16] virtagent: base RPC client definitions, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 08/16] virtagnet: base RPC server definitions, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 04/16] virtagent: bi-directional RPC handling logic, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 05/16] virtagent: common helpers and init routines, Michael Roth, 2011/03/07
- [Qemu-devel] [RFC][PATCH v7 03/16] Make qemu timers available for tools,
Michael Roth <=
- [Qemu-devel] Re: [RFC][PATCH v7 00/16] virtagent: host/guest communication agent, Anthony Liguori, 2011/03/07