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); > > if (d->focus != -1) { > mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); > diff --git a/chardev/char.c b/chardev/char.c > index f54dc3a86286..a1722aa076d9 100644 > --- a/chardev/char.c > +++ b/chardev/char.c > @@ -333,7 +333,7 @@ static bool qemu_chr_is_busy(Chardev *s) > { > if (CHARDEV_IS_MUX(s)) { > MuxChardev *d = MUX_CHARDEV(s); > - return d->mux_cnt > 0; > + return d->mux_bitset != 0; > } else { > return s->be != NULL; > } > diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h > index 8126ce180690..b89aada5413b 100644 > --- a/chardev/chardev-internal.h > +++ b/chardev/chardev-internal.h > @@ -37,8 +37,8 @@ struct MuxChardev { > Chardev parent; > CharBackend *backends[MAX_MUX]; > CharBackend chr; > + unsigned long mux_bitset; > int focus; > - unsigned int mux_cnt; > bool term_got_escape; > /* Intermediate input buffer catches escape sequences even if the > currently active device is not accepting any input - but only > until it > -- > 2.34.1 > > > -- Marc-André Lureau