On 22/10/2016 12:16, Marc-André Lureau wrote: > Use a single allocation for CharDriverState, this avoids extra > allocations & pointers, and is a step towards more object-oriented > CharDriver. > > Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> > --- > backends/baum.c | 23 ++--- > backends/msmouse.c | 16 +-- > backends/testdev.c | 22 ++-- > gdbstub.c | 1 + > hw/bt/hci-csr.c | 10 +- > qemu-char.c | 275 > ++++++++++++++++++++++++++------------------------ > spice-qemu-char.c | 39 +++---- > ui/console.c | 21 ++-- > ui/gtk.c | 11 +- > include/sysemu/char.h | 2 +- > include/ui/gtk.h | 3 + > 11 files changed, 215 insertions(+), 208 deletions(-) > > diff --git a/backends/baum.c b/backends/baum.c > index b2d4719..45a6fd4 100644 > --- a/backends/baum.c > +++ b/backends/baum.c > @@ -87,7 +87,7 @@ > #define BUF_SIZE 256 > > typedef struct { > - CharDriverState *chr; > + CharDriverState parent; > > brlapi_handle_t *brlapi; > int brlapi_fd; > @@ -219,7 +219,7 @@ static const uint8_t nabcc_translation[256] = { > /* The serial port can receive more of our data */ > static void baum_accept_input(struct CharDriverState *chr) > { > - BaumDriverState *baum = chr->opaque; > + BaumDriverState *baum = (BaumDriverState *)chr; > int room, first; > > if (!baum->out_buf_used) > @@ -245,22 +245,23 @@ static void baum_accept_input(struct CharDriverState > *chr) > /* We want to send a packet */ > static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int > len) > { > + CharDriverState *chr = (CharDriverState *)baum; > uint8_t io_buf[1 + 2 * len], *cur = io_buf; > int room; > *cur++ = ESC; > while (len--) > if ((*cur++ = *buf++) == ESC) > *cur++ = ESC; > - room = qemu_chr_be_can_write(baum->chr); > + room = qemu_chr_be_can_write(chr);
Let's use &baum->chr instead, and likewise everywhere else. Paolo > len = cur - io_buf; > if (len <= room) { > /* Fits */ > - qemu_chr_be_write(baum->chr, io_buf, len); > + qemu_chr_be_write(chr, io_buf, len); > } else { > int first; > uint8_t out; > /* Can't fit all, send what can be, and store the rest. */ > - qemu_chr_be_write(baum->chr, io_buf, room); > + qemu_chr_be_write(chr, io_buf, room); > len -= room; > cur = io_buf + room; > if (len > BUF_SIZE - baum->out_buf_used) { > @@ -433,7 +434,7 @@ static int baum_eat_packet(BaumDriverState *baum, const > uint8_t *buf, int len) > /* The other end is writing some data. Store it and try to interpret */ > static int baum_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - BaumDriverState *baum = chr->opaque; > + BaumDriverState *baum = (BaumDriverState *)chr; > int tocopy, cur, eaten, orig_len = len; > > if (!len) > @@ -553,14 +554,13 @@ static void baum_chr_read(void *opaque) > > static void baum_free(struct CharDriverState *chr) > { > - BaumDriverState *baum = chr->opaque; > + BaumDriverState *baum = (BaumDriverState *)chr; > > timer_free(baum->cellCount_timer); > if (baum->brlapi) { > brlapi__closeConnection(baum->brlapi); > g_free(baum->brlapi); > } > - g_free(baum); > } > > static CharDriverState *chr_baum_init(const CharDriver *driver, > @@ -585,10 +585,7 @@ static CharDriverState *chr_baum_init(const CharDriver > *driver, > if (!chr) { > return NULL; > } > - baum = g_malloc0(sizeof(BaumDriverState)); > - baum->chr = chr; > - > - chr->opaque = baum; > + baum = (BaumDriverState *)chr; > > handle = g_malloc0(brlapi_getHandleSize()); > baum->brlapi = handle; > @@ -635,7 +632,6 @@ fail: > fail_handle: > g_free(handle); > g_free(chr); > - g_free(baum); > return NULL; > } > > @@ -643,6 +639,7 @@ static void register_types(void) > { > static const CharDriver driver = { > { "braille" }, CHARDEV_BACKEND_KIND_BRAILLE, NULL, chr_baum_init, > + sizeof(BaumDriverState), > .chr_write = baum_write, > .chr_accept_input = baum_accept_input, > .chr_free = baum_free, > diff --git a/backends/msmouse.c b/backends/msmouse.c > index f71aab0..37e7b82 100644 > --- a/backends/msmouse.c > +++ b/backends/msmouse.c > @@ -31,7 +31,8 @@ > #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) > > typedef struct { > - CharDriverState *chr; > + CharDriverState parent; > + > QemuInputHandlerState *hs; > int axis[INPUT_AXIS__MAX]; > bool btns[INPUT_BUTTON__MAX]; > @@ -42,7 +43,7 @@ typedef struct { > > static void msmouse_chr_accept_input(CharDriverState *chr) > { > - MouseState *mouse = chr->opaque; > + MouseState *mouse = (MouseState *)chr; > int len; > > len = qemu_chr_be_can_write(chr); > @@ -122,9 +123,10 @@ static void msmouse_input_event(DeviceState *dev, > QemuConsole *src, > static void msmouse_input_sync(DeviceState *dev) > { > MouseState *mouse = (MouseState *)dev; > + CharDriverState *chr = (CharDriverState *)dev; > > msmouse_queue_event(mouse); > - msmouse_chr_accept_input(mouse->chr); > + msmouse_chr_accept_input(chr); > } > > static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, > int len) > @@ -135,10 +137,9 @@ static int msmouse_chr_write (struct CharDriverState *s, > const uint8_t *buf, int > > static void msmouse_chr_free(struct CharDriverState *chr) > { > - MouseState *mouse = chr->opaque; > + MouseState *mouse = (MouseState *)chr; > > qemu_input_handler_unregister(mouse->hs); > - g_free(mouse); > } > > static QemuInputHandler msmouse_handler = { > @@ -165,12 +166,10 @@ static CharDriverState *qemu_chr_open_msmouse(const > CharDriver *driver, > } > *be_opened = false; > > - mouse = g_new0(MouseState, 1); > + mouse = (MouseState *)chr; > mouse->hs = qemu_input_handler_register((DeviceState *)mouse, > &msmouse_handler); > > - mouse->chr = chr; > - chr->opaque = mouse; > > return chr; > } > @@ -180,6 +179,7 @@ static void register_types(void) > static const CharDriver driver = { > { "msmouse" }, CHARDEV_BACKEND_KIND_MSMOUSE, > NULL, qemu_chr_open_msmouse, > + sizeof(MouseState), > .chr_write = msmouse_chr_write, > .chr_accept_input = msmouse_chr_accept_input, > .chr_free = msmouse_chr_free, > diff --git a/backends/testdev.c b/backends/testdev.c > index 774cd47..4b1953b 100644 > --- a/backends/testdev.c > +++ b/backends/testdev.c > @@ -30,7 +30,8 @@ > #define BUF_SIZE 32 > > typedef struct { > - CharDriverState *chr; > + CharDriverState parent; > + > uint8_t in_buf[32]; > int in_buf_used; > } TestdevCharState; > @@ -79,7 +80,7 @@ static int testdev_eat_packet(TestdevCharState *testdev) > /* The other end is writing some data. Store it and try to interpret */ > static int testdev_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - TestdevCharState *testdev = chr->opaque; > + TestdevCharState *testdev = (TestdevCharState *)chr; > int tocopy, eaten, orig_len = len; > > while (len) { > @@ -102,13 +103,6 @@ static int testdev_write(CharDriverState *chr, const > uint8_t *buf, int len) > return orig_len; > } > > -static void testdev_free(struct CharDriverState *chr) > -{ > - TestdevCharState *testdev = chr->opaque; > - > - g_free(testdev); > -} > - > static CharDriverState *chr_testdev_init(const CharDriver *driver, > const char *id, > ChardevBackend *backend, > @@ -116,14 +110,10 @@ static CharDriverState *chr_testdev_init(const > CharDriver *driver, > bool *be_opened, > Error **errp) > { > - TestdevCharState *testdev; > - CharDriverState *chr; > - > - testdev = g_new0(TestdevCharState, 1); > - testdev->chr = chr = g_new0(CharDriverState, 1); > + TestdevCharState *testdev = g_new0(TestdevCharState, 1);; > + CharDriverState *chr = (CharDriverState *)testdev; > > chr->driver = driver; > - chr->opaque = testdev; > > return chr; > } > @@ -132,8 +122,8 @@ static void register_types(void) > { > static const CharDriver driver = { > { "testdev" }, CHARDEV_BACKEND_KIND_TESTDEV, NULL, chr_testdev_init, > + sizeof(TestdevCharState), > .chr_write = testdev_write, > - .chr_free = testdev_free, > }; > register_char_driver(&driver); > } > diff --git a/gdbstub.c b/gdbstub.c > index 8e43836..3a9f857 100644 > --- a/gdbstub.c > +++ b/gdbstub.c > @@ -1732,6 +1732,7 @@ int gdbserver_start(const char *device) > CharDriverState *mon_chr; > ChardevCommon common = { 0 }; > static const CharDriver driver = { > + .instance_size = sizeof(CharDriverState), > .kind = -1, > .chr_write = gdb_monitor_write > }; > diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c > index 9c3fb3c..bf2deb0 100644 > --- a/hw/bt/hci-csr.c > +++ b/hw/bt/hci-csr.c > @@ -28,11 +28,11 @@ > #include "hw/bt.h" > > struct csrhci_s { > + CharDriverState chr; > int enable; > qemu_irq *pins; > int pin_state; > int modem_state; > - CharDriverState chr; > #define FIFO_LEN 4096 > int out_start; > int out_len; > @@ -314,7 +314,7 @@ static void csrhci_ready_for_next_inpkt(struct csrhci_s > *s) > static int csrhci_write(struct CharDriverState *chr, > const uint8_t *buf, int len) > { > - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; > + struct csrhci_s *s = (struct csrhci_s *)chr; > int total = 0; > > if (!s->enable) > @@ -387,7 +387,7 @@ static void csrhci_out_hci_packet_acl(void *opaque, > static int csrhci_ioctl(struct CharDriverState *chr, int cmd, void *arg) > { > QEMUSerialSetParams *ssp; > - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; > + struct csrhci_s *s = (struct csrhci_s *) chr; > int prev_state = s->modem_state; > > switch (cmd) { > @@ -455,7 +455,7 @@ static void csrhci_pins(void *opaque, int line, int level) > > qemu_irq *csrhci_pins_get(CharDriverState *chr) > { > - struct csrhci_s *s = (struct csrhci_s *) chr->opaque; > + struct csrhci_s *s = (struct csrhci_s *) chr; > > return s->pins; > } > @@ -463,6 +463,7 @@ qemu_irq *csrhci_pins_get(CharDriverState *chr) > CharDriverState *uart_hci_init(void) > { > static const CharDriver hci_driver = { > + .instance_size = sizeof(struct csrhci_s), > .kind = -1, > .chr_write = csrhci_write, > .chr_ioctl = csrhci_ioctl, > @@ -470,7 +471,6 @@ CharDriverState *uart_hci_init(void) > struct csrhci_s *s = (struct csrhci_s *) > g_malloc0(sizeof(struct csrhci_s)); > > - s->chr.opaque = s; > s->chr.driver = &hci_driver; > > s->hci = qemu_next_hci(); > diff --git a/qemu-char.c b/qemu-char.c > index fe8f717..1da7244 100644 > --- a/qemu-char.c > +++ b/qemu-char.c > @@ -165,12 +165,14 @@ static void qemu_chr_free_common(CharDriverState *chr); > CharDriverState *qemu_chr_alloc(const CharDriver *driver, > ChardevCommon *backend, Error **errp) > { > - CharDriverState *chr = g_malloc0(sizeof(CharDriverState)); > - qemu_mutex_init(&chr->chr_write_lock); > + CharDriverState *chr; > > assert(driver); > assert(driver->chr_write); > + assert(driver->instance_size >= sizeof(CharDriverState)); > > + chr = g_malloc0(driver->instance_size); > + qemu_mutex_init(&chr->chr_write_lock); > if (backend->has_logfile) { > int flags = O_WRONLY | O_CREAT; > if (backend->has_logappend && > @@ -537,6 +539,7 @@ static CharDriverState *qemu_chr_open_null(const > CharDriver *driver, > > static const CharDriver null_driver = { > { "null" }, CHARDEV_BACKEND_KIND_NULL, NULL, qemu_chr_open_null, > + sizeof(CharDriverState), > .chr_write = null_chr_write > }; > > @@ -545,6 +548,7 @@ static const CharDriver null_driver = { > #define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ > #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) > struct MuxDriver { > + CharDriverState parent; > CharBackend *backends[MAX_MUX]; > CharBackend chr; > int focus; > @@ -567,7 +571,7 @@ struct MuxDriver { > /* Called with chr_write_lock held. */ > static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - MuxDriver *d = chr->opaque; > + MuxDriver *d = (MuxDriver *)chr; > int ret; > if (!d->timestamps) { > ret = qemu_chr_fe_write(&d->chr, buf, len); > @@ -701,7 +705,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver > *d, int ch) > > static void mux_chr_accept_input(CharDriverState *chr) > { > - MuxDriver *d = chr->opaque; > + MuxDriver *d = (MuxDriver *)chr; > int m = d->focus; > CharBackend *be = d->backends[m]; > > @@ -714,8 +718,7 @@ static void mux_chr_accept_input(CharDriverState *chr) > > static int mux_chr_can_read(void *opaque) > { > - CharDriverState *chr = opaque; > - MuxDriver *d = chr->opaque; > + MuxDriver *d = opaque; > int m = d->focus; > CharBackend *be = d->backends[m]; > > @@ -733,7 +736,7 @@ static int mux_chr_can_read(void *opaque) > static void mux_chr_read(void *opaque, const uint8_t *buf, int size) > { > CharDriverState *chr = opaque; > - MuxDriver *d = chr->opaque; > + MuxDriver *d = opaque; > int m = d->focus; > CharBackend *be = d->backends[m]; > int i; > @@ -753,8 +756,7 @@ static void mux_chr_read(void *opaque, const uint8_t > *buf, int size) > > static void mux_chr_event(void *opaque, int event) > { > - CharDriverState *chr = opaque; > - MuxDriver *d = chr->opaque; > + MuxDriver *d = opaque; > int i; > > /* Send the event to all registered listeners */ > @@ -782,7 +784,7 @@ static void muxes_realize_done(Notifier *notifier, void > *unused) > > QTAILQ_FOREACH(chr, &chardevs, next) { > if (qemu_chr_get_kind(chr) == CHARDEV_BACKEND_KIND_MUX) { > - MuxDriver *d = chr->opaque; > + MuxDriver *d = (MuxDriver *)chr; > int i; > > /* send OPENED to all already-attached FEs */ > @@ -804,7 +806,7 @@ static Notifier muxes_realize_notify = { > > static GSource *mux_chr_add_watch(CharDriverState *s, GIOCondition cond) > { > - MuxDriver *d = s->opaque; > + MuxDriver *d = (MuxDriver *)s; > CharDriverState *chr = qemu_chr_fe_get_driver(&d->chr); > > if (!chr->driver->chr_add_watch) { > @@ -816,7 +818,7 @@ static GSource *mux_chr_add_watch(CharDriverState *s, > GIOCondition cond) > > static void mux_chr_free(struct CharDriverState *chr) > { > - MuxDriver *d = chr->opaque; > + MuxDriver *d = (MuxDriver *)chr; > int i; > > for (i = 0; i < d->mux_cnt; i++) { > @@ -826,12 +828,11 @@ static void mux_chr_free(struct CharDriverState *chr) > } > } > qemu_chr_fe_deinit(&d->chr); > - g_free(d); > } > > static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context) > { > - MuxDriver *d = chr->opaque; > + MuxDriver *d = (MuxDriver *)chr; > > /* Fix up the real driver with mux routines */ > qemu_chr_fe_set_handlers(&d->chr, > @@ -877,9 +878,7 @@ static CharDriverState *qemu_chr_open_mux(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - d = g_new0(MuxDriver, 1); > - > - chr->opaque = d; > + d = (MuxDriver *)chr; > d->focus = -1; > /* only default to opened state if we've realized the initial > * set of muxes > @@ -908,7 +907,7 @@ bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, > Error **errp) > assert(s); > > if (qemu_chr_get_kind(s) == CHARDEV_BACKEND_KIND_MUX) { > - MuxDriver *d = s->opaque; > + MuxDriver *d = (MuxDriver *)s; > > if (d->mux_cnt >= MAX_MUX) { > goto unavailable; > @@ -940,7 +939,7 @@ void qemu_chr_fe_deinit(CharBackend *b) > qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true); > b->chr->be = NULL; > if (qemu_chr_get_kind(b->chr) == CHARDEV_BACKEND_KIND_MUX) { > - MuxDriver *d = b->chr->opaque; > + MuxDriver *d = (MuxDriver *)b->chr; > d->backends[b->tag] = NULL; > } > b->chr = NULL; > @@ -1006,7 +1005,7 @@ void qemu_chr_fe_take_focus(CharBackend *b) > } > > if (qemu_chr_get_kind(b->chr) == CHARDEV_BACKEND_KIND_MUX) { > - mux_set_focus(b->chr->opaque, b->tag); > + mux_set_focus((MuxDriver *)b->chr, b->tag); > } > } > > @@ -1178,6 +1177,7 @@ static int io_channel_send(QIOChannel *ioc, const void > *buf, size_t len) > > > typedef struct FDCharDriver { > + CharDriverState parent; > CharDriverState *chr; > QIOChannel *ioc_in, *ioc_out; > int max_size; > @@ -1186,15 +1186,15 @@ typedef struct FDCharDriver { > /* Called with chr_write_lock held. */ > static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - FDCharDriver *s = chr->opaque; > - > + FDCharDriver *s = (FDCharDriver *)chr; > + > return io_channel_send(s->ioc_out, buf, len); > } > > static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void > *opaque) > { > CharDriverState *chr = opaque; > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = opaque; > int len; > uint8_t buf[READ_BUF_LEN]; > ssize_t ret; > @@ -1224,7 +1224,7 @@ static gboolean fd_chr_read(QIOChannel *chan, > GIOCondition cond, void *opaque) > static int fd_chr_read_poll(void *opaque) > { > CharDriverState *chr = opaque; > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = opaque; > > s->max_size = qemu_chr_be_can_write(chr); > return s->max_size; > @@ -1232,14 +1232,14 @@ static int fd_chr_read_poll(void *opaque) > > static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond) > { > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = (FDCharDriver *)chr; > return qio_channel_create_watch(s->ioc_out, cond); > } > > static void fd_chr_update_read_handler(CharDriverState *chr, > GMainContext *context) > { > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = (FDCharDriver *)chr; > > remove_fd_in_watch(chr); > if (s->ioc_in) { > @@ -1252,7 +1252,7 @@ static void fd_chr_update_read_handler(CharDriverState > *chr, > > static void fd_chr_free(struct CharDriverState *chr) > { > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = (FDCharDriver *)chr; > > remove_fd_in_watch(chr); > if (s->ioc_in) { > @@ -1262,7 +1262,6 @@ static void fd_chr_free(struct CharDriverState *chr) > object_unref(OBJECT(s->ioc_out)); > } > > - g_free(s); > qemu_chr_be_event(chr, CHR_EVENT_CLOSED); > } > > @@ -1278,12 +1277,11 @@ static CharDriverState *qemu_chr_open_fd(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - s = g_new0(FDCharDriver, 1); > + s = (FDCharDriver *)chr; > s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in)); > s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out)); > qemu_set_nonblock(fd_out); > s->chr = chr; > - chr->opaque = s; > > return chr; > } > @@ -1424,6 +1422,7 @@ static CharDriverState *qemu_chr_open_stdio(const > CharDriver *driver, > #define HAVE_CHARDEV_PTY 1 > > typedef struct { > + CharDriverState parent; > QIOChannel *ioc; > int read_bytes; > > @@ -1439,7 +1438,7 @@ static void pty_chr_state(CharDriverState *chr, int > connected); > static gboolean pty_chr_timer(gpointer opaque) > { > struct CharDriverState *chr = opaque; > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = opaque; > > qemu_mutex_lock(&chr->chr_write_lock); > s->timer_tag = 0; > @@ -1455,7 +1454,7 @@ static gboolean pty_chr_timer(gpointer opaque) > /* Called with chr_write_lock held. */ > static void pty_chr_rearm_timer(CharDriverState *chr, int ms) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > > if (s->timer_tag) { > g_source_remove(s->timer_tag); > @@ -1472,7 +1471,7 @@ static void pty_chr_rearm_timer(CharDriverState *chr, > int ms) > /* Called with chr_write_lock held. */ > static void pty_chr_update_read_handler_locked(CharDriverState *chr) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > GPollFD pfd; > int rc; > QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc); > @@ -1503,7 +1502,7 @@ static void pty_chr_update_read_handler(CharDriverState > *chr, > /* Called with chr_write_lock held. */ > static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > > if (!s->connected) { > /* guest sends data, check for (re-)connect */ > @@ -1517,7 +1516,7 @@ static int pty_chr_write(CharDriverState *chr, const > uint8_t *buf, int len) > > static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > if (!s->connected) { > return NULL; > } > @@ -1527,7 +1526,7 @@ static GSource *pty_chr_add_watch(CharDriverState *chr, > GIOCondition cond) > static int pty_chr_read_poll(void *opaque) > { > CharDriverState *chr = opaque; > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = opaque; > > s->read_bytes = qemu_chr_be_can_write(chr); > return s->read_bytes; > @@ -1536,7 +1535,7 @@ static int pty_chr_read_poll(void *opaque) > static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void > *opaque) > { > CharDriverState *chr = opaque; > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = opaque; > gsize len; > uint8_t buf[READ_BUF_LEN]; > ssize_t ret; > @@ -1561,7 +1560,7 @@ static gboolean pty_chr_read(QIOChannel *chan, > GIOCondition cond, void *opaque) > static gboolean qemu_chr_be_generic_open_func(gpointer opaque) > { > CharDriverState *chr = opaque; > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = opaque; > > s->open_tag = 0; > qemu_chr_be_generic_open(chr); > @@ -1571,7 +1570,7 @@ static gboolean qemu_chr_be_generic_open_func(gpointer > opaque) > /* Called with chr_write_lock held. */ > static void pty_chr_state(CharDriverState *chr, int connected) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > > if (!connected) { > if (s->open_tag) { > @@ -1605,7 +1604,7 @@ static void pty_chr_state(CharDriverState *chr, int > connected) > > static void pty_chr_free(struct CharDriverState *chr) > { > - PtyCharDriver *s = chr->opaque; > + PtyCharDriver *s = (PtyCharDriver *)chr; > > qemu_mutex_lock(&chr->chr_write_lock); > pty_chr_state(chr, 0); > @@ -1615,7 +1614,6 @@ static void pty_chr_free(struct CharDriverState *chr) > s->timer_tag = 0; > } > qemu_mutex_unlock(&chr->chr_write_lock); > - g_free(s); > qemu_chr_be_event(chr, CHR_EVENT_CLOSED); > } > > @@ -1654,18 +1652,17 @@ static CharDriverState *qemu_chr_open_pty(const > CharDriver *driver, > fprintf(stderr, "char device redirected to %s (label %s)\n", > pty_name, id); > > - s = g_new0(PtyCharDriver, 1); > - chr->opaque = s; > - *be_opened = false; > - > + s = (PtyCharDriver *)chr; > s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd)); > s->timer_tag = 0; > + *be_opened = false; > > return chr; > } > > static const CharDriver pty_driver = { > { "pty" }, CHARDEV_BACKEND_KIND_PTY, NULL, qemu_chr_open_pty, > + sizeof(PtyCharDriver), > .chr_write = pty_chr_write, > .chr_update_read_handler = pty_chr_update_read_handler, > .chr_add_watch = pty_chr_add_watch, > @@ -1789,7 +1786,7 @@ static void tty_serial_init(int fd, int speed, > > static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) > { > - FDCharDriver *s = chr->opaque; > + FDCharDriver *s = (FDCharDriver *)chr; > QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in); > > switch(cmd) { > @@ -1868,6 +1865,7 @@ static void qemu_chr_free_tty(CharDriverState *chr) > #define HAVE_CHARDEV_PARPORT 1 > > typedef struct { > + CharDriverState parent; > int fd; > int mode; > } ParallelCharDriver; > @@ -1885,7 +1883,7 @@ static int pp_hw_mode(ParallelCharDriver *s, uint16_t > mode) > > static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) > { > - ParallelCharDriver *drv = chr->opaque; > + ParallelCharDriver *drv = (ParallelCharDriver *)chr; > int fd = drv->fd; > uint8_t b; > > @@ -1966,13 +1964,12 @@ static int pp_ioctl(CharDriverState *chr, int cmd, > void *arg) > > static void pp_free(CharDriverState *chr) > { > - ParallelCharDriver *drv = chr->opaque; > + ParallelCharDriver *drv = (ParallelCharDriver *)chr; > int fd = drv->fd; > > pp_hw_mode(drv, IEEE1284_MODE_COMPAT); > ioctl(fd, PPRELEASE); > close(fd); > - g_free(drv); > qemu_chr_be_event(chr, CHR_EVENT_CLOSED); > } > > @@ -1996,9 +1993,7 @@ static CharDriverState *qemu_chr_open_pp_fd(const > CharDriver *driver, > return NULL; > } > > - drv = g_new0(ParallelCharDriver, 1); > - chr->opaque = drv; > - > + drv = (ParallelCharDriver *)chr; > drv->fd = fd; > drv->mode = IEEE1284_MODE_COMPAT; > > @@ -2010,35 +2005,45 @@ static CharDriverState *qemu_chr_open_pp_fd(const > CharDriver *driver, > > #define HAVE_CHARDEV_PARPORT 1 > > +typedef struct { > + CharDriverState parent; > + int fd; > +} ParallelCharDriver; > + > static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) > { > - int fd = (int)(intptr_t)chr->opaque; > + ParallelCharDriver *drv = (ParallelCharDriver *)chr; > uint8_t b; > > - switch(cmd) { > + switch (cmd) { > case CHR_IOCTL_PP_READ_DATA: > - if (ioctl(fd, PPIGDATA, &b) < 0) > + if (ioctl(drv->fd, PPIGDATA, &b) < 0) { > return -ENOTSUP; > + } > *(uint8_t *)arg = b; > break; > case CHR_IOCTL_PP_WRITE_DATA: > b = *(uint8_t *)arg; > - if (ioctl(fd, PPISDATA, &b) < 0) > + if (ioctl(drv->fd, PPISDATA, &b) < 0) { > return -ENOTSUP; > + } > break; > case CHR_IOCTL_PP_READ_CONTROL: > - if (ioctl(fd, PPIGCTRL, &b) < 0) > + if (ioctl(drv->fd, PPIGCTRL, &b) < 0) { > return -ENOTSUP; > + } > *(uint8_t *)arg = b; > break; > case CHR_IOCTL_PP_WRITE_CONTROL: > b = *(uint8_t *)arg; > - if (ioctl(fd, PPISCTRL, &b) < 0) > + if (ioctl(drv->fd, PPISCTRL, &b) < 0) { > return -ENOTSUP; > + } > break; > case CHR_IOCTL_PP_READ_STATUS: > - if (ioctl(fd, PPIGSTATUS, &b) < 0) > + if (ioctl(drv->fd, PPIGSTATUS, &b) < 0) { > return -ENOTSUP; > + } > *(uint8_t *)arg = b; > break; > default: > @@ -2054,12 +2059,14 @@ static CharDriverState *qemu_chr_open_pp_fd(const > CharDriver *driver, > Error **errp) > { > CharDriverState *chr; > + ParallelCharDriver *drv; > > chr = qemu_chr_alloc(driver, backend, errp); > if (!chr) { > return NULL; > } > - chr->opaque = (void *)(intptr_t)fd; > + drv = (ParallelCharDriver *)chr; > + drv->fd = fd; > *be_opened = false; > return chr; > } > @@ -2070,6 +2077,7 @@ static CharDriverState *qemu_chr_open_pp_fd(const > CharDriver *driver, > #define HAVE_CHARDEV_SERIAL 1 > > typedef struct { > + CharDriverState parent; > int max_size; > HANDLE hcom, hrecv, hsend; > OVERLAPPED orecv; > @@ -2081,6 +2089,7 @@ typedef struct { > } WinCharState; > > typedef struct { > + CharDriverState parent; > HANDLE hStdIn; > HANDLE hInputReadyEvent; > HANDLE hInputDoneEvent; > @@ -2098,7 +2107,7 @@ static int win_chr_pipe_poll(void *opaque); > > static void win_chr_free(CharDriverState *chr) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > > if (s->hsend) { > CloseHandle(s->hsend); > @@ -2122,7 +2131,7 @@ static void win_chr_free(CharDriverState *chr) > > static int win_chr_init(CharDriverState *chr, const char *filename, Error > **errp) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > COMMCONFIG comcfg; > COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; > COMSTAT comstat; > @@ -2190,7 +2199,7 @@ static int win_chr_init(CharDriverState *chr, const > char *filename, Error **errp > /* Called with chr_write_lock held. */ > static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > DWORD len, ret, size, err; > > len = len1; > @@ -2224,7 +2233,7 @@ static int win_chr_write(CharDriverState *chr, const > uint8_t *buf, int len1) > > static int win_chr_read_poll(CharDriverState *chr) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > > s->max_size = qemu_chr_be_can_write(chr); > return s->max_size; > @@ -2232,7 +2241,7 @@ static int win_chr_read_poll(CharDriverState *chr) > > static void win_chr_readfile(CharDriverState *chr) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > int ret, err; > uint8_t buf[READ_BUF_LEN]; > DWORD size; > @@ -2254,7 +2263,7 @@ static void win_chr_readfile(CharDriverState *chr) > > static void win_chr_read(CharDriverState *chr) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > > if (s->len > s->max_size) > s->len = s->max_size; > @@ -2267,7 +2276,7 @@ static void win_chr_read(CharDriverState *chr) > static int win_chr_poll(void *opaque) > { > CharDriverState *chr = opaque; > - WinCharState *s = chr->opaque; > + WinCharState *s = opaque; > COMSTAT status; > DWORD comerr; > > @@ -2284,7 +2293,7 @@ static int win_chr_poll(void *opaque) > static int win_chr_pipe_poll(void *opaque) > { > CharDriverState *chr = opaque; > - WinCharState *s = chr->opaque; > + WinCharState *s = opaque; > DWORD size; > > PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); > @@ -2300,7 +2309,7 @@ static int win_chr_pipe_poll(void *opaque) > static int win_chr_pipe_init(CharDriverState *chr, const char *filename, > Error **errp) > { > - WinCharState *s = chr->opaque; > + WinCharState *s = (WinCharState *)chr; > OVERLAPPED ov; > int ret; > DWORD size; > @@ -2372,18 +2381,14 @@ static CharDriverState *qemu_chr_open_pipe(const > CharDriver *driver, > ChardevHostdev *opts = backend->u.pipe.data; > const char *filename = opts->device; > CharDriverState *chr; > - WinCharState *s; > ChardevCommon *common = qapi_ChardevHostdev_base(opts); > > chr = qemu_chr_alloc(driver, common, errp); > if (!chr) { > return NULL; > } > - s = g_new0(WinCharState, 1); > - chr->opaque = s; > > if (win_chr_pipe_init(chr, filename, errp) < 0) { > - g_free(s); > qemu_chr_free_common(chr); > return NULL; > } > @@ -2402,9 +2407,8 @@ static CharDriverState *qemu_chr_open_win_file(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - s = g_new0(WinCharState, 1); > + s = (WinCharState *)chr; > s->hcom = fd_out; > - chr->opaque = s; > return chr; > } > > @@ -2423,6 +2427,7 @@ static CharDriverState *qemu_chr_open_win_con(const > CharDriver *driver, > > static const CharDriver console_driver = { > { "console" }, CHARDEV_BACKEND_KIND_CONSOLE, NULL, qemu_chr_open_win_con, > + sizeof(WinCharState), > .chr_write = win_chr_write, > }; > > @@ -2448,7 +2453,7 @@ static int win_stdio_write(CharDriverState *chr, const > uint8_t *buf, int len) > static void win_stdio_wait_func(void *opaque) > { > CharDriverState *chr = opaque; > - WinStdioCharState *stdio = chr->opaque; > + WinStdioCharState *stdio = opaque; > INPUT_RECORD buf[4]; > int ret; > DWORD dwSize; > @@ -2481,8 +2486,7 @@ static void win_stdio_wait_func(void *opaque) > > static DWORD WINAPI win_stdio_thread(LPVOID param) > { > - CharDriverState *chr = param; > - WinStdioCharState *stdio = chr->opaque; > + WinStdioCharState *stdio = param; > int ret; > DWORD dwSize; > > @@ -2521,7 +2525,7 @@ static DWORD WINAPI win_stdio_thread(LPVOID param) > static void win_stdio_thread_wait_func(void *opaque) > { > CharDriverState *chr = opaque; > - WinStdioCharState *stdio = chr->opaque; > + WinStdioCharState *stdio = opaque; > > if (qemu_chr_be_can_write(chr)) { > qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1); > @@ -2532,7 +2536,7 @@ static void win_stdio_thread_wait_func(void *opaque) > > static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo) > { > - WinStdioCharState *stdio = chr->opaque; > + WinStdioCharState *stdio = (WinStdioCharState *)chr; > DWORD dwMode = 0; > > GetConsoleMode(stdio->hStdIn, &dwMode); > @@ -2546,7 +2550,7 @@ static void qemu_chr_set_echo_win_stdio(CharDriverState > *chr, bool echo) > > static void win_stdio_free(CharDriverState *chr) > { > - WinStdioCharState *stdio = chr->opaque; > + WinStdioCharState *stdio = (WinStdioCharState *)chr; > > if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) { > CloseHandle(stdio->hInputReadyEvent); > @@ -2557,8 +2561,6 @@ static void win_stdio_free(CharDriverState *chr) > if (stdio->hInputThread != INVALID_HANDLE_VALUE) { > TerminateThread(stdio->hInputThread, 0); > } > - > - g_free(chr->opaque); > } > > static CharDriverState *qemu_chr_open_stdio(const CharDriver *driver, > @@ -2578,7 +2580,7 @@ static CharDriverState *qemu_chr_open_stdio(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - stdio = g_new0(WinStdioCharState, 1); > + stdio = (WinStdioCharState *)chr; > > stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE); > if (stdio->hStdIn == INVALID_HANDLE_VALUE) { > @@ -2588,8 +2590,6 @@ static CharDriverState *qemu_chr_open_stdio(const > CharDriver *driver, > > is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0; > > - chr->opaque = stdio; > - > if (is_console) { > if (qemu_add_wait_object(stdio->hStdIn, > win_stdio_wait_func, chr)) { > @@ -2649,6 +2649,7 @@ err1: > /* UDP Net console */ > > typedef struct { > + CharDriverState parent; > QIOChannel *ioc; > uint8_t buf[READ_BUF_LEN]; > int bufcnt; > @@ -2659,7 +2660,7 @@ typedef struct { > /* Called with chr_write_lock held. */ > static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - NetCharDriver *s = chr->opaque; > + NetCharDriver *s = (NetCharDriver *)chr; > > return qio_channel_write( > s->ioc, (const char *)buf, len, NULL); > @@ -2668,7 +2669,7 @@ static int udp_chr_write(CharDriverState *chr, const > uint8_t *buf, int len) > static int udp_chr_read_poll(void *opaque) > { > CharDriverState *chr = opaque; > - NetCharDriver *s = chr->opaque; > + NetCharDriver *s = opaque; > > s->max_size = qemu_chr_be_can_write(chr); > > @@ -2686,7 +2687,7 @@ static int udp_chr_read_poll(void *opaque) > static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void > *opaque) > { > CharDriverState *chr = opaque; > - NetCharDriver *s = chr->opaque; > + NetCharDriver *s = opaque; > ssize_t ret; > > if (s->max_size == 0) { > @@ -2713,7 +2714,7 @@ static gboolean udp_chr_read(QIOChannel *chan, > GIOCondition cond, void *opaque) > static void udp_chr_update_read_handler(CharDriverState *chr, > GMainContext *context) > { > - NetCharDriver *s = chr->opaque; > + NetCharDriver *s = (NetCharDriver *)chr; > > remove_fd_in_watch(chr); > if (s->ioc) { > @@ -2726,13 +2727,12 @@ static void > udp_chr_update_read_handler(CharDriverState *chr, > > static void udp_chr_free(CharDriverState *chr) > { > - NetCharDriver *s = chr->opaque; > + NetCharDriver *s = (NetCharDriver *)chr; > > remove_fd_in_watch(chr); > if (s->ioc) { > object_unref(OBJECT(s->ioc)); > } > - g_free(s); > qemu_chr_be_event(chr, CHR_EVENT_CLOSED); > } > > @@ -2740,6 +2740,7 @@ static void udp_chr_free(CharDriverState *chr) > /* TCP Net console */ > > typedef struct { > + CharDriverState parent; > QIOChannel *ioc; /* Client I/O channel */ > QIOChannelSocket *sioc; /* Client master channel */ > QIOChannelSocket *listen_ioc; > @@ -2768,7 +2769,7 @@ static gboolean socket_reconnect_timeout(gpointer > opaque); > > static void qemu_chr_socket_restart_timer(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > assert(s->connected == 0); > s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time, > socket_reconnect_timeout, > chr); > @@ -2777,7 +2778,7 @@ static void > qemu_chr_socket_restart_timer(CharDriverState *chr) > static void check_report_connect_error(CharDriverState *chr, > Error *err) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > if (!s->connect_err_reported) { > error_report("Unable to connect character device %s: %s", > @@ -2794,7 +2795,8 @@ static gboolean tcp_chr_accept(QIOChannel *chan, > /* Called with chr_write_lock held. */ > static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > + > if (s->connected) { > int ret = io_channel_send_full(s->ioc, buf, len, > s->write_msgfds, > @@ -2817,7 +2819,7 @@ static int tcp_chr_write(CharDriverState *chr, const > uint8_t *buf, int len) > static int tcp_chr_read_poll(void *opaque) > { > CharDriverState *chr = opaque; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = opaque; > if (!s->connected) > return 0; > s->max_size = qemu_chr_be_can_write(chr); > @@ -2876,7 +2878,8 @@ static void tcp_chr_process_IAC_bytes(CharDriverState > *chr, > > static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > + > int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num; > > assert(num <= TCP_MAX_FDS); > @@ -2901,7 +2904,7 @@ static int tcp_get_msgfds(CharDriverState *chr, int > *fds, int num) > > static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > /* clear old pending fd array */ > g_free(s->write_msgfds); > @@ -2926,7 +2929,7 @@ static int tcp_set_msgfds(CharDriverState *chr, int > *fds, int num) > > static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > struct iovec iov = { .iov_base = buf, .iov_len = len }; > int ret; > size_t i; > @@ -2983,13 +2986,13 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, > char *buf, size_t len) > > static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > return qio_channel_create_watch(s->ioc, cond); > } > > static void tcp_chr_free_connection(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > int i; > > if (!s->connected) { > @@ -3018,7 +3021,7 @@ static void tcp_chr_free_connection(CharDriverState > *chr) > > static void tcp_chr_disconnect(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > if (!s->connected) { > return; > @@ -3041,7 +3044,7 @@ static void tcp_chr_disconnect(CharDriverState *chr) > static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void > *opaque) > { > CharDriverState *chr = opaque; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = opaque; > uint8_t buf[READ_BUF_LEN]; > int len, size; > > @@ -3067,7 +3070,7 @@ static gboolean tcp_chr_read(QIOChannel *chan, > GIOCondition cond, void *opaque) > > static int tcp_chr_sync_read(CharDriverState *chr, const uint8_t *buf, int > len) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > int size; > > if (!s->connected) { > @@ -3086,7 +3089,7 @@ static int tcp_chr_sync_read(CharDriverState *chr, > const uint8_t *buf, int len) > static void tcp_chr_connect(void *opaque) > { > CharDriverState *chr = opaque; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = opaque; > > g_free(chr->filename); > chr->filename = sockaddr_to_str( > @@ -3107,7 +3110,7 @@ static void tcp_chr_connect(void *opaque) > static void tcp_chr_update_read_handler(CharDriverState *chr, > GMainContext *context) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > if (!s->connected) { > return; > @@ -3158,7 +3161,7 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, > > static void tcp_chr_telnet_init(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > TCPCharDriverTelnetInit *init = > g_new0(TCPCharDriverTelnetInit, 1); > size_t n = 0; > @@ -3194,7 +3197,7 @@ static void tcp_chr_tls_handshake(Object *source, > gpointer user_data) > { > CharDriverState *chr = user_data; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = user_data; > > if (err) { > tcp_chr_disconnect(chr); > @@ -3210,7 +3213,7 @@ static void tcp_chr_tls_handshake(Object *source, > > static void tcp_chr_tls_init(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > QIOChannelTLS *tioc; > Error *err = NULL; > > @@ -3242,7 +3245,8 @@ static void tcp_chr_tls_init(CharDriverState *chr) > > static int tcp_chr_new_client(CharDriverState *chr, QIOChannelSocket *sioc) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > + > if (s->ioc != NULL) { > return -1; > } > @@ -3312,7 +3316,7 @@ static gboolean tcp_chr_accept(QIOChannel *channel, > > static int tcp_chr_wait_connected(CharDriverState *chr, Error **errp) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > QIOChannelSocket *sioc; > > /* It can't wait on s->connected, since it is set asynchronously > @@ -3359,7 +3363,7 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error > **errp) > > static void tcp_chr_free(CharDriverState *chr) > { > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > tcp_chr_free_connection(chr); > > @@ -3378,7 +3382,7 @@ static void tcp_chr_free(CharDriverState *chr) > if (s->tls_creds) { > object_unref(OBJECT(s->tls_creds)); > } > - g_free(s); > + > qemu_chr_be_event(chr, CHR_EVENT_CLOSED); > } > > @@ -3387,7 +3391,7 @@ static void qemu_chr_socket_connected(Object *src, > Error *err, void *opaque) > { > QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(src); > CharDriverState *chr = opaque; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = (TCPCharDriver *)chr; > > if (err) { > check_report_connect_error(chr, err); > @@ -3405,6 +3409,7 @@ static void qemu_chr_socket_connected(Object *src, > Error *err, void *opaque) > /* Ring buffer chardev */ > > typedef struct { > + CharDriverState parent; > size_t size; > size_t prod; > size_t cons; > @@ -3413,7 +3418,7 @@ typedef struct { > > static size_t ringbuf_count(const CharDriverState *chr) > { > - const RingBufCharDriver *d = chr->opaque; > + const RingBufCharDriver *d = (RingBufCharDriver *)chr; > > return d->prod - d->cons; > } > @@ -3421,7 +3426,7 @@ static size_t ringbuf_count(const CharDriverState *chr) > /* Called with chr_write_lock held. */ > static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int > len) > { > - RingBufCharDriver *d = chr->opaque; > + RingBufCharDriver *d = (RingBufCharDriver *)chr; > int i; > > if (!buf || (len < 0)) { > @@ -3440,7 +3445,7 @@ static int ringbuf_chr_write(CharDriverState *chr, > const uint8_t *buf, int len) > > static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len) > { > - RingBufCharDriver *d = chr->opaque; > + RingBufCharDriver *d = (RingBufCharDriver *)chr; > int i; > > qemu_mutex_lock(&chr->chr_write_lock); > @@ -3454,11 +3459,9 @@ static int ringbuf_chr_read(CharDriverState *chr, > uint8_t *buf, int len) > > static void ringbuf_chr_free(struct CharDriverState *chr) > { > - RingBufCharDriver *d = chr->opaque; > + RingBufCharDriver *d = (RingBufCharDriver *)chr; > > g_free(d->cbuf); > - g_free(d); > - chr->opaque = NULL; > } > > static CharDriverState *qemu_chr_open_ringbuf(const CharDriver *driver, > @@ -3477,7 +3480,7 @@ static CharDriverState *qemu_chr_open_ringbuf(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - d = g_malloc(sizeof(*d)); > + d = (RingBufCharDriver *)chr; > > d->size = opts->has_size ? opts->size : 65536; > > @@ -3491,12 +3494,9 @@ static CharDriverState *qemu_chr_open_ringbuf(const > CharDriver *driver, > d->cons = 0; > d->cbuf = g_malloc0(d->size); > > - chr->opaque = d; > - > return chr; > > fail: > - g_free(d); > qemu_chr_free_common(chr); > return NULL; > } > @@ -3786,10 +3786,12 @@ static const CharDriver stdio_driver = { > { "stdio" }, CHARDEV_BACKEND_KIND_STDIO, > qemu_chr_parse_stdio, qemu_chr_open_stdio, > #ifdef _WIN32 > + sizeof(WinStdioCharState), > .chr_write = win_stdio_write, > .chr_set_echo = qemu_chr_set_echo_win_stdio, > .chr_free = win_stdio_free, > #else > + sizeof(FDCharDriver), > .chr_add_watch = fd_chr_add_watch, > .chr_write = fd_chr_write, > .chr_update_read_handler = fd_chr_update_read_handler, > @@ -3851,9 +3853,11 @@ static const CharDriver pipe_driver = { > { "pipe" }, CHARDEV_BACKEND_KIND_PIPE, > qemu_chr_parse_pipe, qemu_chr_open_pipe, > #ifdef _WIN32 > + sizeof(WinCharState), > .chr_write = win_chr_write, > .chr_free = win_chr_free, > #else > + sizeof(FDCharDriver), > .chr_add_watch = fd_chr_add_watch, > .chr_write = fd_chr_write, > .chr_update_read_handler = fd_chr_update_read_handler, > @@ -3880,6 +3884,7 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, > ChardevBackend *backend, > static const CharDriver ringbuf_driver = { > { "ringbuf" }, CHARDEV_BACKEND_KIND_RINGBUF, > qemu_chr_parse_ringbuf, qemu_chr_open_ringbuf, > + sizeof(RingBufCharDriver), > .chr_write = ringbuf_chr_write, > .chr_free = ringbuf_chr_free, > }; > @@ -3888,6 +3893,7 @@ static const CharDriver ringbuf_driver = { > static const CharDriver memory_driver = { > { "memory" }, CHARDEV_BACKEND_KIND_MEMORY, > qemu_chr_parse_ringbuf, qemu_chr_open_ringbuf, > + sizeof(RingBufCharDriver), > .chr_write = ringbuf_chr_write, > .chr_free = ringbuf_chr_free, > }; > @@ -3909,6 +3915,7 @@ static void qemu_chr_parse_mux(QemuOpts *opts, > ChardevBackend *backend, > > static const CharDriver mux_driver = { > { "mux" }, CHARDEV_BACKEND_KIND_MUX, qemu_chr_parse_mux, > qemu_chr_open_mux, > + sizeof(MuxDriver), > .chr_free = mux_chr_free, > .chr_write = mux_chr_write, > .chr_accept_input = mux_chr_accept_input, > @@ -4489,17 +4496,13 @@ static CharDriverState *qmp_chardev_open_serial(const > CharDriver *driver, > ChardevHostdev *serial = backend->u.serial.data; > ChardevCommon *common = qapi_ChardevHostdev_base(serial); > CharDriverState *chr; > - WinCharState *s; > > chr = qemu_chr_alloc(driver, common, errp); > if (!chr) { > return NULL; > } > > - s = g_new0(WinCharState, 1); > - chr->opaque = s; > if (win_chr_init(chr, serial->device, errp) < 0) { > - g_free(s); > qemu_chr_free_common(chr); > return NULL; > } > @@ -4601,6 +4604,7 @@ static CharDriverState *qmp_chardev_open_parallel(const > CharDriver *driver, > static const CharDriver parallel_driver = { > { "parallel", "parport" }, CHARDEV_BACKEND_KIND_PARALLEL, > qemu_chr_parse_parallel, qmp_chardev_open_parallel, > + sizeof(ParallelCharDriver), > #if defined(__linux__) > .chr_write = null_chr_write, > .chr_ioctl = pp_ioctl, > @@ -4618,8 +4622,10 @@ static const CharDriver file_driver = { > { "file" }, CHARDEV_BACKEND_KIND_FILE, > qemu_chr_parse_file_out, qmp_chardev_open_file, > #ifdef _WIN32 > + sizeof(WinCharState), > .chr_write = win_chr_write, > #else > + sizeof(FDCharDriver), > .chr_add_watch = fd_chr_add_watch, > .chr_write = fd_chr_write, > .chr_update_read_handler = fd_chr_update_read_handler, > @@ -4632,9 +4638,11 @@ static const CharDriver serial_driver = { > { "serial", "tty" }, CHARDEV_BACKEND_KIND_SERIAL, > qemu_chr_parse_serial, qmp_chardev_open_serial, > #ifdef _WIN32 > + sizeof(WinCharState), > .chr_write = win_chr_write, > .chr_free = win_chr_free, > #else > + sizeof(FDCharDriver), > .chr_add_watch = fd_chr_add_watch, > .chr_write = fd_chr_write, > .chr_update_read_handler = fd_chr_update_read_handler, > @@ -4647,7 +4655,7 @@ static const CharDriver serial_driver = { > static gboolean socket_reconnect_timeout(gpointer opaque) > { > CharDriverState *chr = opaque; > - TCPCharDriver *s = chr->opaque; > + TCPCharDriver *s = opaque; > QIOChannelSocket *sioc; > > s->reconnect_timer = 0; > @@ -4687,7 +4695,7 @@ static CharDriverState *qmp_chardev_open_socket(const > CharDriver *driver, > if (!chr) { > return NULL; > } > - s = g_new0(TCPCharDriver, 1); > + s = (TCPCharDriver *)chr; > > s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX; > s->is_listen = is_listen; > @@ -4733,7 +4741,6 @@ static CharDriverState *qmp_chardev_open_socket(const > CharDriver *driver, > qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); > } > > - chr->opaque = s; > /* be isn't opened until we get a connection */ > *be_opened = false; > > @@ -4783,7 +4790,6 @@ static CharDriverState *qmp_chardev_open_socket(const > CharDriver *driver, > if (s->tls_creds) { > object_unref(OBJECT(s->tls_creds)); > } > - g_free(s); > qemu_chr_free_common(chr); > return NULL; > } > @@ -4791,6 +4797,7 @@ static CharDriverState *qmp_chardev_open_socket(const > CharDriver *driver, > static const CharDriver socket_driver = { > { "socket" }, CHARDEV_BACKEND_KIND_SOCKET, > qemu_chr_parse_socket, qmp_chardev_open_socket, > + sizeof(TCPCharDriver), > .chr_wait_connected = tcp_chr_wait_connected, > .chr_write = tcp_chr_write, > .chr_sync_read = tcp_chr_sync_read, > @@ -4828,11 +4835,10 @@ static CharDriverState *qmp_chardev_open_udp(const > CharDriver *driver, > return NULL; > } > > - s = g_new0(NetCharDriver, 1); > + s = (NetCharDriver *)chr; > s->ioc = QIO_CHANNEL(sioc); > s->bufcnt = 0; > s->bufptr = 0; > - chr->opaque = s; > /* be isn't opened until we get a connection */ > *be_opened = false; > > @@ -4842,6 +4848,7 @@ static CharDriverState *qmp_chardev_open_udp(const > CharDriver *driver, > static const CharDriver udp_driver = { > { "udp" }, CHARDEV_BACKEND_KIND_UDP, > qemu_chr_parse_udp, qmp_chardev_open_udp, > + sizeof(NetCharDriver), > .chr_write = udp_chr_write, > .chr_update_read_handler = udp_chr_update_read_handler, > .chr_free = udp_chr_free, > diff --git a/spice-qemu-char.c b/spice-qemu-char.c > index 14afd4a..bd8b898 100644 > --- a/spice-qemu-char.c > +++ b/spice-qemu-char.c > @@ -7,7 +7,8 @@ > > > typedef struct SpiceCharDriver { > - CharDriverState* chr; > + CharDriverState parent; > + > SpiceCharDeviceInstance sin; > bool active; > bool blocked; > @@ -27,17 +28,18 @@ static QLIST_HEAD(, SpiceCharDriver) spice_chars = > static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int > len) > { > SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); > + CharDriverState *chr = (CharDriverState *)scd; > ssize_t out = 0; > ssize_t last_out; > uint8_t* p = (uint8_t*)buf; > > while (len > 0) { > - int can_write = qemu_chr_be_can_write(scd->chr); > + int can_write = qemu_chr_be_can_write(chr); > last_out = MIN(len, can_write); > if (last_out <= 0) { > break; > } > - qemu_chr_be_write(scd->chr, p, last_out); > + qemu_chr_be_write(chr, p, last_out); > out += last_out; > len -= last_out; > p += last_out; > @@ -70,6 +72,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t > *buf, int len) > static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event) > { > SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); > + CharDriverState *chr = (CharDriverState *)scd; > int chr_event; > > switch (event) { > @@ -81,20 +84,21 @@ static void vmc_event(SpiceCharDeviceInstance *sin, > uint8_t event) > } > > trace_spice_vmc_event(chr_event); > - qemu_chr_be_event(scd->chr, chr_event); > + qemu_chr_be_event(chr, chr_event); > } > #endif > > static void vmc_state(SpiceCharDeviceInstance *sin, int connected) > { > SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); > + CharDriverState *chr = (CharDriverState *)scd; > > - if ((scd->chr->be_open && connected) || > - (!scd->chr->be_open && !connected)) { > + if ((chr->be_open && connected) || > + (!chr->be_open && !connected)) { > return; > } > > - qemu_chr_be_event(scd->chr, > + qemu_chr_be_event(chr, > connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED); > } > > @@ -168,7 +172,7 @@ static GSourceFuncs SpiceCharSourceFuncs = { > > static GSource *spice_chr_add_watch(CharDriverState *chr, GIOCondition cond) > { > - SpiceCharDriver *scd = chr->opaque; > + SpiceCharDriver *scd = (SpiceCharDriver *)chr; > SpiceCharSource *src; > > assert(cond & G_IO_OUT); > @@ -182,7 +186,7 @@ static GSource *spice_chr_add_watch(CharDriverState *chr, > GIOCondition cond) > > static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - SpiceCharDriver *s = chr->opaque; > + SpiceCharDriver *s = (SpiceCharDriver *)chr; > int read_bytes; > > assert(s->datalen == 0); > @@ -201,7 +205,7 @@ static int spice_chr_write(CharDriverState *chr, const > uint8_t *buf, int len) > > static void spice_chr_free(struct CharDriverState *chr) > { > - SpiceCharDriver *s = chr->opaque; > + SpiceCharDriver *s = (SpiceCharDriver *)chr; > > vmc_unregister_interface(s); > QLIST_REMOVE(s, next); > @@ -210,12 +214,11 @@ static void spice_chr_free(struct CharDriverState *chr) > #if SPICE_SERVER_VERSION >= 0x000c02 > g_free((char *)s->sin.portname); > #endif > - g_free(s); > } > > static void spice_vmc_set_fe_open(struct CharDriverState *chr, int fe_open) > { > - SpiceCharDriver *s = chr->opaque; > + SpiceCharDriver *s = (SpiceCharDriver *)chr; > if (fe_open) { > vmc_register_interface(s); > } else { > @@ -226,7 +229,7 @@ static void spice_vmc_set_fe_open(struct CharDriverState > *chr, int fe_open) > static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open) > { > #if SPICE_SERVER_VERSION >= 0x000c02 > - SpiceCharDriver *s = chr->opaque; > + SpiceCharDriver *s = (SpiceCharDriver *)chr; > > if (fe_open) { > spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED); > @@ -255,7 +258,7 @@ static void print_allowed_subtypes(void) > > static void spice_chr_accept_input(struct CharDriverState *chr) > { > - SpiceCharDriver *s = chr->opaque; > + SpiceCharDriver *s = (SpiceCharDriver *)chr; > > spice_server_char_device_wakeup(&s->sin); > } > @@ -272,11 +275,9 @@ static CharDriverState *chr_open(const CharDriver > *driver, > if (!chr) { > return NULL; > } > - s = g_malloc0(sizeof(SpiceCharDriver)); > - s->chr = chr; > + s = (SpiceCharDriver *)chr; > s->active = false; > s->sin.subtype = g_strdup(subtype); > - chr->opaque = s; > > QLIST_INSERT_HEAD(&spice_chars, s, next); > > @@ -334,7 +335,7 @@ static CharDriverState *qemu_chr_open_spice_port(const > CharDriver *driver, > return NULL; > } > *be_opened = false; > - s = chr->opaque; > + s = (SpiceCharDriver *)chr; > s->sin.portname = g_strdup(name); > > return chr; > @@ -388,6 +389,7 @@ static void register_types(void) > static const CharDriver vmc_driver = { > { "spicevmc" }, CHARDEV_BACKEND_KIND_SPICEVMC, > qemu_chr_parse_spice_vmc, qemu_chr_open_spice_vmc, > + sizeof(SpiceCharDriver), > .chr_write = spice_chr_write, > .chr_add_watch = spice_chr_add_watch, > .chr_set_fe_open = spice_vmc_set_fe_open, > @@ -397,6 +399,7 @@ static void register_types(void) > static const CharDriver port_driver = { > { "spiceport" }, CHARDEV_BACKEND_KIND_SPICEPORT, > qemu_chr_parse_spice_port, qemu_chr_open_spice_port, > + sizeof(SpiceCharDriver), > .chr_write = spice_chr_write, > .chr_add_watch = spice_chr_add_watch, > .chr_set_fe_open = spice_port_set_fe_open, > diff --git a/ui/console.c b/ui/console.c > index 2944d22..b8c6328 100644 > --- a/ui/console.c > +++ b/ui/console.c > @@ -1035,9 +1035,15 @@ void console_select(unsigned int index) > } > } > > +typedef struct VCDriverState { > + CharDriverState parent; > + QemuConsole *console; > +} VCDriverState; > + > static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) > { > - QemuConsole *s = chr->opaque; > + VCDriverState *drv = (VCDriverState *)chr; > + QemuConsole *s = drv->console; > int i; > > s->update_x0 = s->width * FONT_WIDTH; > @@ -1943,7 +1949,8 @@ int qemu_console_get_height(QemuConsole *con, int > fallback) > > static void text_console_set_echo(CharDriverState *chr, bool echo) > { > - QemuConsole *s = chr->opaque; > + VCDriverState *drv = (VCDriverState *)chr; > + QemuConsole *s = drv->console; > > s->echo = echo; > } > @@ -1983,12 +1990,11 @@ static const GraphicHwOps text_console_ops = { > > static void text_console_do_init(CharDriverState *chr, DisplayState *ds) > { > - QemuConsole *s; > + VCDriverState *drv = (VCDriverState *)chr; > + QemuConsole *s = drv->console; > int g_width = 80 * FONT_WIDTH; > int g_height = 24 * FONT_HEIGHT; > > - s = chr->opaque; > - > s->out_fifo.buf = s->out_fifo_buf; > s->out_fifo.buf_size = sizeof(s->out_fifo_buf); > s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s); > @@ -2041,6 +2047,7 @@ static CharDriverState *text_console_init(ChardevVC > *vc, Error **errp) > { > ChardevCommon *common = qapi_ChardevVC_base(vc); > CharDriverState *chr; > + VCDriverState *drv; > QemuConsole *s; > unsigned width = 0; > unsigned height = 0; > @@ -2077,7 +2084,8 @@ static CharDriverState *text_console_init(ChardevVC > *vc, Error **errp) > } > > s->chr = chr; > - chr->opaque = s; > + drv = (VCDriverState *)chr; > + drv->console = s; > > if (display_state) { > text_console_do_init(chr, display_state); > @@ -2182,6 +2190,7 @@ static const TypeInfo qemu_console_info = { > > static const CharDriver vc_driver = { > { "vc" }, CHARDEV_BACKEND_KIND_VC, qemu_chr_parse_vc, vc_init, > + sizeof(VCDriverState), > .chr_write = console_puts, > .chr_set_echo = text_console_set_echo, > }; > diff --git a/ui/gtk.c b/ui/gtk.c > index 1566faa..03281da 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c > @@ -1653,7 +1653,7 @@ static void gd_vc_adjustment_changed(GtkAdjustment > *adjustment, void *opaque) > > static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len) > { > - VirtualConsole *vc = chr->opaque; > + VirtualConsole *vc = (VirtualConsole *)chr; > > vte_terminal_feed(VTE_TERMINAL(vc->vte.terminal), (const char *)buf, > len); > return len; > @@ -1661,7 +1661,7 @@ static int gd_vc_chr_write(CharDriverState *chr, const > uint8_t *buf, int len) > > static void gd_vc_chr_set_echo(CharDriverState *chr, bool echo) > { > - VirtualConsole *vc = chr->opaque; > + VirtualConsole *vc = (VirtualConsole *)chr; > > vc->vte.echo = echo; > } > @@ -1673,6 +1673,7 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, > Error **errp) > { > static const CharDriver gd_vc_driver = { > { "vc" }, CHARDEV_BACKEND_KIND_VC, > + .instance_size = sizeof(VirtualConsole), > .chr_write = gd_vc_chr_write, > .chr_set_echo = gd_vc_chr_set_echo, > }; > @@ -1685,9 +1686,6 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, > Error **errp) > return NULL; > } > > - /* Temporary, until gd_vc_vte_init runs. */ > - chr->opaque = g_new0(VirtualConsole, 1); > - > vcs[nb_vcs++] = chr; > > return chr; > @@ -1728,13 +1726,12 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, > VirtualConsole *vc, > GtkWidget *box; > GtkWidget *scrollbar; > GtkAdjustment *vadjustment; > - VirtualConsole *tmp_vc = chr->opaque; > + VirtualConsole *tmp_vc = (VirtualConsole *)chr; > > vc->s = s; > vc->vte.echo = tmp_vc->vte.echo; > > vc->vte.chr = chr; > - chr->opaque = vc; > g_free(tmp_vc); > > snprintf(buffer, sizeof(buffer), "vc%d", idx); > diff --git a/include/sysemu/char.h b/include/sysemu/char.h > index 96b464a..a072edc 100644 > --- a/include/sysemu/char.h > +++ b/include/sysemu/char.h > @@ -93,7 +93,6 @@ struct CharDriverState { > const CharDriver *driver; > QemuMutex chr_write_lock; > CharBackend *be; > - void *opaque; > char *label; > char *filename; > int logfd; > @@ -482,6 +481,7 @@ struct CharDriver { > ChardevBackend *backend, > ChardevReturn *ret, bool *be_opened, > Error **errp); > + size_t instance_size; > > int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); > int (*chr_sync_read)(struct CharDriverState *s, > diff --git a/include/ui/gtk.h b/include/ui/gtk.h > index 42ca0fe..6fec03f 100644 > --- a/include/ui/gtk.h > +++ b/include/ui/gtk.h > @@ -23,6 +23,8 @@ > #include "ui/egl-context.h" > #endif > > +#include "sysemu/char.h" > + > /* Compatibility define to let us build on both Gtk2 and Gtk3 */ > #if GTK_CHECK_VERSION(3, 0, 0) > static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh) > @@ -71,6 +73,7 @@ typedef enum VirtualConsoleType { > } VirtualConsoleType; > > typedef struct VirtualConsole { > + CharDriverState parent; > GtkDisplayState *s; > char *label; > GtkWidget *window; >