> > +/* ------------------------------------------------------------------ */ > > +/* send messages */ > > + > > +static void vdagent_send_buf(VDAgentChardev *vd, void *ptr, uint32_t > > msgsize) > > +{ > > + uint8_t *msgbuf = ptr; > > + uint32_t len, pos = 0; > > + > > + while (pos < msgsize) { > > + len = qemu_chr_be_can_write(CHARDEV(vd)); > > + if (len > msgsize - pos) { > > + len = msgsize - pos; > > + } > > + qemu_chr_be_write(CHARDEV(vd), msgbuf + pos, len); > > + pos += len; > > + } > > > > This looks like it could easily busy loop. Have you thought about fixing > this?
Incremental fix [ to be squashed ] take care, Gerd diff --git a/ui/vdagent.c b/ui/vdagent.c index 64213aa25a06..efa98725fb22 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -3,7 +3,9 @@ #include "include/qemu-common.h" #include "chardev/char.h" #include "hw/qdev-core.h" +#include "qemu/buffer.h" #include "qemu/option.h" +#include "qemu/units.h" #include "ui/clipboard.h" #include "ui/console.h" #include "ui/input.h" @@ -16,6 +18,7 @@ #define VDAGENT_MOUSE_DEFAULT true #define VDAGENT_CLIPBOARD_DEFAULT false +#define VDAGENT_BUFFER_LIMIT (1 * MiB) struct VDAgentChardev { Chardev parent; @@ -32,6 +35,7 @@ struct VDAgentChardev { uint32_t msgsize; uint8_t *xbuf; uint32_t xoff, xsize; + Buffer outbuf; /* mouse */ DeviceState mouse_dev; @@ -124,18 +128,20 @@ static const char *type_name[] = { /* ------------------------------------------------------------------ */ /* send messages */ -static void vdagent_send_buf(VDAgentChardev *vd, void *ptr, uint32_t msgsize) +static void vdagent_send_buf(VDAgentChardev *vd) { - uint8_t *msgbuf = ptr; - uint32_t len, pos = 0; + uint32_t len; - while (pos < msgsize) { + while (!buffer_empty(&vd->outbuf)) { len = qemu_chr_be_can_write(CHARDEV(vd)); - if (len > msgsize - pos) { - len = msgsize - pos; + if (len == 0) { + return; } - qemu_chr_be_write(CHARDEV(vd), msgbuf + pos, len); - pos += len; + if (len > vd->outbuf.offset) { + len = vd->outbuf.offset; + } + qemu_chr_be_write(CHARDEV(vd), vd->outbuf.buffer, len); + buffer_advance(&vd->outbuf, len); } } @@ -150,16 +156,22 @@ static void vdagent_send_msg(VDAgentChardev *vd, VDAgentMessage *msg) msg->protocol = VD_AGENT_PROTOCOL; + if (vd->outbuf.offset + msgsize > VDAGENT_BUFFER_LIMIT) { + return; + } + while (msgoff < msgsize) { chunk.port = VDP_CLIENT_PORT; chunk.size = msgsize - msgoff; if (chunk.size > 1024) { chunk.size = 1024; } - vdagent_send_buf(vd, &chunk, sizeof(chunk)); - vdagent_send_buf(vd, msgbuf + msgoff, chunk.size); + buffer_reserve(&vd->outbuf, sizeof(chunk) + chunk.size); + buffer_append(&vd->outbuf, &chunk, sizeof(chunk)); + buffer_append(&vd->outbuf, msgbuf + msgoff, chunk.size); msgoff += chunk.size; } + vdagent_send_buf(vd); } static void vdagent_send_caps(VDAgentChardev *vd) @@ -550,6 +562,7 @@ static void vdagent_chr_open(Chardev *chr, &vdagent_mouse_handler); } + buffer_init(&vd->outbuf, "vdagent-outbuf"); *be_opened = true; } @@ -702,6 +715,13 @@ static int vdagent_chr_write(Chardev *chr, const uint8_t *buf, int len) return ret; } +static void vdagent_chr_accept_input(Chardev *chr) +{ + VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(chr); + + vdagent_send_buf(vd); +} + static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) { VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(chr); @@ -748,6 +768,7 @@ static void vdagent_chr_class_init(ObjectClass *oc, void *data) cc->open = vdagent_chr_open; cc->chr_write = vdagent_chr_write; cc->chr_set_fe_open = vdagent_chr_set_fe_open; + cc->chr_accept_input = vdagent_chr_accept_input; } static const TypeInfo vdagent_chr_type_info = { -- 2.31.1