From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@qumranet.com>, Anthony Liguori <aliguori@us.ibm.com>
Cc: kvm-devel <kvm-devel@lists.sourceforge.net>
Subject: [patch 08/13] QEMU: character device locking
Date: Thu, 17 Apr 2008 17:10:29 -0300 [thread overview]
Message-ID: <20080417203026.770795557@localhost.localdomain> (raw)
In-Reply-To: 20080417201021.515148882@localhost.localdomain
[-- Attachment #1: qemu-char-lock --]
[-- Type: text/plain, Size: 8173 bytes --]
Grab device locks when moving data through char devices in the host->guest direction.
Index: kvm-userspace.io/qemu/hw/serial.c
===================================================================
--- kvm-userspace.io.orig/qemu/hw/serial.c
+++ kvm-userspace.io/qemu/hw/serial.c
@@ -305,18 +305,21 @@ static void serial_receive_break(SerialS
static int serial_can_receive1(void *opaque)
{
SerialState *s = opaque;
+ assert_is_locked(&s->qemu_dev.lock);
return serial_can_receive(s);
}
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
{
SerialState *s = opaque;
+ assert_is_locked(&s->qemu_dev.lock);
serial_receive_byte(s, buf[0]);
}
static void serial_event(void *opaque, int event)
{
SerialState *s = opaque;
+ assert_is_locked(&s->qemu_dev.lock);
if (event == CHR_EVENT_BREAK)
serial_receive_break(s);
}
@@ -400,6 +403,7 @@ SerialState *serial_init(int base, qemu_
register_ioport_write(dev, base, 8, 1, serial_ioport_write, s);
register_ioport_read(dev, base, 8, 1, serial_ioport_read, s);
s->chr = chr;
+ chr->qemu_dev = dev;
qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
serial_event, s);
return s;
Index: kvm-userspace.io/qemu/qemu-char.h
===================================================================
--- kvm-userspace.io.orig/qemu/qemu-char.h
+++ kvm-userspace.io/qemu/qemu-char.h
@@ -44,6 +44,7 @@ struct CharDriverState {
void *opaque;
int focus;
QEMUBH *bh;
+ QEMUDevice *qemu_dev;
};
CharDriverState *qemu_chr_open(const char *filename);
Index: kvm-userspace.io/qemu/vl.c
===================================================================
--- kvm-userspace.io.orig/qemu/vl.c
+++ kvm-userspace.io/qemu/vl.c
@@ -1690,6 +1690,18 @@ int qemu_timedate_diff(struct tm *tm)
/***********************************************************/
/* character device */
+static void qemu_chr_lock(CharDriverState *s)
+{
+ if (!s->qemu_dev)
+ hw_error("%s: no qemu_dev\n", __func__);
+ qemu_mutex_lock(&s->qemu_dev->lock);
+}
+
+static void qemu_chr_unlock(CharDriverState *s)
+{
+ qemu_mutex_unlock(&s->qemu_dev->lock);
+}
+
static void qemu_chr_event(CharDriverState *s, int event)
{
if (!s->chr_event)
@@ -1715,7 +1727,12 @@ void qemu_chr_reset(CharDriverState *s)
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
{
- return s->chr_write(s, buf, len);
+ int ret;
+
+ assert_is_dev_locked(s->qemu_dev);
+ ret = s->chr_write(s, buf, len);
+
+ return ret;
}
int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
@@ -1727,9 +1744,11 @@ int qemu_chr_ioctl(CharDriverState *s, i
int qemu_chr_can_read(CharDriverState *s)
{
+ int ret = 0;
if (!s->chr_can_read)
- return 0;
- return s->chr_can_read(s->handler_opaque);
+ return ret;
+ ret = s->chr_can_read(s->handler_opaque);
+ return ret;
}
void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
@@ -1755,8 +1774,10 @@ void qemu_chr_printf(CharDriverState *s,
void qemu_chr_send_event(CharDriverState *s, int event)
{
+ qemu_chr_lock(s);
if (s->chr_send_event)
s->chr_send_event(s, event);
+ qemu_chr_unlock(s);
}
void qemu_chr_add_handlers(CharDriverState *s,
@@ -1799,8 +1820,10 @@ typedef struct {
IOCanRWHandler *chr_can_read[MAX_MUX];
IOReadHandler *chr_read[MAX_MUX];
IOEventHandler *chr_event[MAX_MUX];
+ QEMUDevice *devices[MAX_MUX];
void *ext_opaque[MAX_MUX];
CharDriverState *drv;
+ QEMUDevice qemu_dev;
unsigned char buffer[MUX_BUFFER_SIZE];
int prod;
int cons;
@@ -1935,11 +1958,13 @@ static void mux_chr_accept_input(CharDri
int m = chr->focus;
MuxDriver *d = chr->opaque;
- while (d->prod != d->cons &&
- d->chr_can_read[m] &&
- d->chr_can_read[m](d->ext_opaque[m])) {
- d->chr_read[m](d->ext_opaque[m],
- &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+ while (d->prod != d->cons) {
+ qemu_mutex_lock(&d->devices[m]->lock);
+ if (d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) {
+ d->chr_read[m](d->ext_opaque[m],
+ &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+ }
+ qemu_mutex_unlock(&d->devices[m]->lock);
}
}
@@ -1950,8 +1975,13 @@ static int mux_chr_can_read(void *opaque
if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
return 1;
- if (d->chr_can_read[chr->focus])
- return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+ if (d->chr_can_read[chr->focus]) {
+ int ret;
+ qemu_mutex_lock(&d->devices[chr->focus]->lock);
+ ret = d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+ qemu_mutex_unlock(&d->devices[chr->focus]->lock);
+ return ret;
+ }
return 0;
}
@@ -1966,11 +1996,13 @@ static void mux_chr_read(void *opaque, c
for(i = 0; i < size; i++)
if (mux_proc_byte(chr, d, buf[i])) {
- if (d->prod == d->cons &&
- d->chr_can_read[m] &&
- d->chr_can_read[m](d->ext_opaque[m]))
- d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
- else
+ if (d->prod == d->cons) {
+ qemu_mutex_lock(&d->devices[m]->lock);
+ if (d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) {
+ d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
+ }
+ qemu_mutex_unlock(&d->devices[m]->lock);
+ } else
d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
}
}
@@ -1982,9 +2014,13 @@ static void mux_chr_event(void *opaque,
int i;
/* Send the event to all registered listeners */
- for (i = 0; i < d->mux_cnt; i++)
- if (d->chr_event[i])
+ for (i = 0; i < d->mux_cnt; i++) {
+ if (d->chr_event[i]) {
+ qemu_mutex_lock(&d->devices[i]->lock);
d->chr_event[i](d->ext_opaque[i], event);
+ qemu_mutex_unlock(&d->devices[i]->lock);
+ }
+ }
}
static void mux_chr_update_read_handler(CharDriverState *chr)
@@ -1999,6 +2035,7 @@ static void mux_chr_update_read_handler(
d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
d->chr_read[d->mux_cnt] = chr->chr_read;
d->chr_event[d->mux_cnt] = chr->chr_event;
+ d->devices[d->mux_cnt] = chr->qemu_dev;
/* Fix up the real driver with mux routines */
if (d->mux_cnt == 0) {
qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
@@ -2021,8 +2058,10 @@ static CharDriverState *qemu_chr_open_mu
free(chr);
return NULL;
}
+ qemu_register_device(&d->qemu_dev);
chr->opaque = d;
+ chr->qemu_dev = &d->qemu_dev;
d->drv = drv;
chr->focus = -1;
chr->chr_write = mux_chr_write;
Index: kvm-userspace.io/qemu/qemu-device.h
===================================================================
--- kvm-userspace.io.orig/qemu/qemu-device.h
+++ kvm-userspace.io/qemu/qemu-device.h
@@ -10,6 +10,7 @@
#define qemu_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define qemu_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#define assert_is_locked(mutex) do { } while (0)
+#define assert_is_dev_locked(mutex) do { } while (0)
static inline void qemu_mutex_init(qemu_mutex_t *mutex)
{
pthread_mutex_init(mutex, NULL);
@@ -42,6 +43,16 @@ static inline void assert_is_locked(qemu
}
}
+static inline void assert_is_dev_locked(void *dev)
+{
+ if (!dev) {
+ printf("assert failure, qemu_dev is null\n");
+ print_backtrace();
+ exit(0);
+ }
+ assert_is_locked((qemu_mutex_t *)dev);
+}
+
static inline void qemu_mutex_lock(qemu_mutex_t *mutex)
{
if (!mutex) {
--
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
next prev parent reply other threads:[~2008-04-17 20:10 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-17 20:10 [patch 00/13] RFC: split the global mutex Marcelo Tosatti
2008-04-17 20:10 ` [patch 01/13] QEMU: get rid of global cpu_single_env Marcelo Tosatti
2008-04-17 20:10 ` [patch 02/13] QEMU: introduce QEMUDevice Marcelo Tosatti
2008-04-17 20:10 ` [patch 03/13] QEMU: make esp.c build conditional to SPARC target Marcelo Tosatti
2008-04-17 20:10 ` [patch 04/13] QEMU: plug QEMUDevice pt1 / ioport awareness Marcelo Tosatti
2008-04-17 20:10 ` [patch 05/13] QEMU: add a mutex to protect IRQ chip data structures Marcelo Tosatti
2008-04-17 20:10 ` [patch 06/13] QEMU: plug QEMUDevice pt2 / iomem awareness Marcelo Tosatti
2008-04-17 20:10 ` [patch 07/13] QEMU: grab device lock for ioport/iomem processing Marcelo Tosatti
2008-04-17 20:10 ` Marcelo Tosatti [this message]
2008-04-17 20:10 ` [patch 09/13] QEMU: network device locking Marcelo Tosatti
2008-04-17 20:10 ` [patch 10/13] QEMU: get rid of aiocb cache Marcelo Tosatti
2008-04-17 20:10 ` [patch 11/13] QEMU: block device locking Marcelo Tosatti
2008-04-17 20:10 ` [patch 12/13] QEMU: scsi-disk reentrancy fix Marcelo Tosatti
2008-04-17 20:10 ` [patch 13/13] QEMU/KVM: get rid of global lock Marcelo Tosatti
2008-04-20 11:16 ` [patch 00/13] RFC: split the global mutex Avi Kivity
2008-04-21 0:00 ` Marcelo Tosatti
2008-04-21 6:10 ` Avi Kivity
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=20080417203026.770795557@localhost.localdomain \
--to=mtosatti@redhat.com \
--cc=aliguori@us.ibm.com \
--cc=avi@qumranet.com \
--cc=kvm-devel@lists.sourceforge.net \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.