Message ID | 20241014114135.389766-7-r.peniaev@gmail.com |
---|---|
State | New |
Headers | show |
Series | chardev/mux: implement frontend detach | expand |
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 > > >
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
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
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(-)