On Mon, Oct 14, 2024 at 3:20 PM Marc-André Lureau <marcandre.lur...@gmail.com> wrote: > > > > On Mon, Oct 14, 2024 at 3:45 PM Roman Penyaev <r.peni...@gmail.com> wrote: >> >> Frontends can be attached and detached during run-time (although detach >> is not implemented, but will follow). Counter variable of muxes is not >> enough for proper attach/detach management, so this patch implements >> bitset: if bit is set for the `mux_bitset` variable, then frontend >> device can be found in the `backend` array (yes, huge confusion with >> backend and frontends names). >> >> Signed-off-by: Roman Penyaev <r.peni...@gmail.com> >> Cc: "Marc-André Lureau" <marcandre.lur...@redhat.com> >> Cc: qemu-devel@nongnu.org >> --- >> chardev/char-mux.c | 41 +++++++++++++++++++++++++------------- >> chardev/char.c | 2 +- >> chardev/chardev-internal.h | 2 +- >> 3 files changed, 29 insertions(+), 16 deletions(-) >> >> diff --git a/chardev/char-mux.c b/chardev/char-mux.c >> index 9294f955462e..9c3cacb2fecd 100644 >> --- a/chardev/char-mux.c >> +++ b/chardev/char-mux.c >> @@ -26,6 +26,7 @@ >> #include "qapi/error.h" >> #include "qemu/module.h" >> #include "qemu/option.h" >> +#include "qemu/bitops.h" >> #include "chardev/char.h" >> #include "sysemu/block-backend.h" >> #include "qapi/qapi-commands-control.h" >> @@ -168,12 +169,19 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, >> int ch) >> case 'b': >> qemu_chr_be_event(chr, CHR_EVENT_BREAK); >> break; >> - case 'c': >> - assert(d->mux_cnt > 0); /* handler registered with first fe */ >> + case 'c': { >> + unsigned int bit; >> + >> + /* Handler registered with first fe */ >> + assert(d->mux_bitset != 0); >> /* Switch to the next registered device */ >> - mux_set_focus(chr, (d->focus + 1) % d->mux_cnt); >> + bit = find_next_bit(&d->mux_bitset, MAX_MUX, d->focus + 1); >> + if (bit >= MAX_MUX) { >> + bit = find_next_bit(&d->mux_bitset, MAX_MUX, 0); >> + } >> + mux_set_focus(chr, bit); >> break; >> - case 't': >> + } case 't': >> d->timestamps = !d->timestamps; >> d->timestamps_start = -1; >> d->linestart = false; >> @@ -243,15 +250,16 @@ static void mux_chr_read(void *opaque, const uint8_t >> *buf, int size) >> void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) >> { >> MuxChardev *d = MUX_CHARDEV(chr); >> - unsigned int i; >> + int bit; >> >> if (!muxes_opened) { >> return; >> } >> >> /* Send the event to all registered listeners */ >> - for (i = 0; i < d->mux_cnt; i++) { >> - mux_chr_send_event(d, i, event); >> + bit = -1; >> + while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < >> MAX_MUX) { >> + mux_chr_send_event(d, bit, event); >> } >> } >> >> @@ -276,10 +284,11 @@ static GSource *mux_chr_add_watch(Chardev *s, >> GIOCondition cond) >> static void char_mux_finalize(Object *obj) >> { >> MuxChardev *d = MUX_CHARDEV(obj); >> - unsigned int i; >> + int bit; >> >> - for (i = 0; i < d->mux_cnt; i++) { >> - CharBackend *be = d->backends[i]; >> + bit = -1; >> + while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < >> MAX_MUX) { >> + CharBackend *be = d->backends[bit]; >> if (be) { >> be->chr = NULL; >> } >> @@ -304,7 +313,10 @@ static void mux_chr_update_read_handlers(Chardev *chr) >> bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, >> unsigned int *tag, Error **errp) >> { >> - if (d->mux_cnt >= MAX_MUX) { >> + unsigned int bit; >> + >> + bit = find_next_zero_bit(&d->mux_bitset, MAX_MUX, 0); >> + if (bit >= MAX_MUX) { >> error_setg(errp, >> "too many uses of multiplexed chardev '%s'" >> " (maximum is " stringify(MAX_MUX) ")", >> @@ -312,8 +324,9 @@ bool mux_chr_attach_frontend(MuxChardev *d, CharBackend >> *b, >> return false; >> } >> >> - d->backends[d->mux_cnt] = b; >> - *tag = d->mux_cnt++; >> + d->mux_bitset |= (1 << bit); >> + d->backends[bit] = b; >> + *tag = bit; >> >> return true; >> } >> @@ -322,7 +335,7 @@ void mux_set_focus(Chardev *chr, unsigned int focus) >> { >> MuxChardev *d = MUX_CHARDEV(chr); >> >> - assert(focus < d->mux_cnt); >> + assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) < MAX_MUX); > > > Wouldn't this be more correct? > > + assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) == focus); >
Yes, makes sense. Thanks. Do you want the whole patchset to be resend, or only changed patches with "v2" prefix in subject? -- Roman