[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 37/38] char: allocate CharDriverState as a singl
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH 37/38] char: allocate CharDriverState as a single object |
Date: |
Sun, 23 Oct 2016 14:28:56 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 |
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 <address@hidden>
> ---
> 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;
>
- [Qemu-devel] [PATCH 31/38] char: use a const CharDriver, (continued)
- [Qemu-devel] [PATCH 31/38] char: use a const CharDriver, Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 32/38] char: use a static array for backends, Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 33/38] char: move callbacks in CharDriver, Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 34/38] char: fold single-user functions in caller, Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 35/38] char: introduce generic qemu_chr_get_kind(), Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 36/38] char: use a feature bit for replay, Marc-André Lureau, 2016/10/22
- [Qemu-devel] [PATCH 37/38] char: allocate CharDriverState as a single object, Marc-André Lureau, 2016/10/22
- Re: [Qemu-devel] [PATCH 00/38] char: fixes and improvements (was "[PATCH 0/9] Fix mux regression"), Paolo Bonzini, 2016/10/23