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.peniaev@gmail.com>
Cc: "Marc-André Lureau" <marcandre.lureau@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);
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
On Mon, Oct 14, 2024 at 3:45 PM Roman Penyaev <r.peniaev@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.peniaev@gmail.com> > Cc: "Marc-André Lureau" <marcandre.lureau@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
On Mon, Oct 14, 2024 at 3:20 PM Marc-André Lureau <marcandre.lureau@gmail.com> wrote: > > > > On Mon, Oct 14, 2024 at 3:45 PM Roman Penyaev <r.peniaev@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.peniaev@gmail.com> >> Cc: "Marc-André Lureau" <marcandre.lureau@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
On Mon, Oct 14, 2024 at 5:58 PM Roman Penyaev <r.peniaev@gmail.com> wrote: > On Mon, Oct 14, 2024 at 3:20 PM Marc-André Lureau > <marcandre.lureau@gmail.com> wrote: > > > > > > > > On Mon, Oct 14, 2024 at 3:45 PM Roman Penyaev <r.peniaev@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.peniaev@gmail.com> > >> Cc: "Marc-André Lureau" <marcandre.lureau@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? > Yes, please send a v2 with the change and r-b. For the other series, use Based-on tag as necessary ( https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg01288.html) thanks -- Marc-André Lureau
© 2016 - 2024 Red Hat, Inc.