From patchwork Mon Jan 17 13:14:57 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 79161 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D44C1B70D5 for ; Tue, 18 Jan 2011 00:24:39 +1100 (EST) Received: from localhost ([127.0.0.1]:35922 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pep4J-0002T1-TC for incoming@patchwork.ozlabs.org; Mon, 17 Jan 2011 08:24:23 -0500 Received: from [140.186.70.92] (port=60939 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PeowM-0006sL-VL for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PeowK-0006D5-Qh for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:10 -0500 Received: from e6.ny.us.ibm.com ([32.97.182.146]:51916) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PeowK-0006D0-MB for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:08 -0500 Received: from d01dlp02.pok.ibm.com (d01dlp02.pok.ibm.com [9.56.224.85]) by e6.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p0HD1SeN000477 for ; Mon, 17 Jan 2011 08:01:38 -0500 Received: from d01relay06.pok.ibm.com (d01relay06.pok.ibm.com [9.56.227.116]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 52E104DE8041 for ; Mon, 17 Jan 2011 08:12:54 -0500 (EST) Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay06.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0HDG6eg2506962 for ; Mon, 17 Jan 2011 08:16:06 -0500 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0HDG6sM030068 for ; Mon, 17 Jan 2011 08:16:06 -0500 Received: from localhost.localdomain (sig-9-76-0-14.mts.ibm.com [9.76.0.14]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p0HDFUKx026421; Mon, 17 Jan 2011 08:16:05 -0500 From: Michael Roth To: qemu-devel@nongnu.org Date: Mon, 17 Jan 2011 07:14:57 -0600 Message-Id: <1295270117-24760-4-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1295270117-24760-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1295270117-24760-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, marcel.mittelstaedt@de.ibm.com, mdroth@linux.vnet.ibm.com, markus_mueller@de.ibm.com, aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com, abeekhof@redhat.com Subject: [Qemu-devel] [RFC][PATCH v6 03/23] Make qemu timers available for tools X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- cpus.c | 83 +++++++--------------------------------------------- qemu-ioh.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-ioh.h | 9 ++++++ qemu-tool.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-tool.h | 26 ++++++++++++++++ 5 files changed, 229 insertions(+), 74 deletions(-) create mode 100644 qemu-tool.h diff --git a/cpus.c b/cpus.c index 0309189..2f1adf6 100644 --- a/cpus.c +++ b/cpus.c @@ -163,90 +163,24 @@ 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); } #else 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); } #endif @@ -296,11 +230,10 @@ void qemu_cpu_kick(void *env) return; } -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); } @@ -309,6 +242,12 @@ void qemu_notify_event(void) } } +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..001e7a2 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 +#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,92 @@ 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 -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 +#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