|
@@ -26,6 +26,7 @@
|
|
#include "qapi/error.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu/module.h"
|
|
#include "qemu/module.h"
|
|
#include "qemu/option.h"
|
|
#include "qemu/option.h"
|
|
|
|
+#include "qemu/bitops.h"
|
|
#include "chardev/char.h"
|
|
#include "chardev/char.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "qapi/qapi-commands-control.h"
|
|
#include "qapi/qapi-commands-control.h"
|
|
@@ -168,12 +169,19 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
|
|
case 'b':
|
|
case 'b':
|
|
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
|
|
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
|
|
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 */
|
|
/* 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;
|
|
break;
|
|
- case 't':
|
|
|
|
|
|
+ } case 't':
|
|
d->timestamps = !d->timestamps;
|
|
d->timestamps = !d->timestamps;
|
|
d->timestamps_start = -1;
|
|
d->timestamps_start = -1;
|
|
d->linestart = false;
|
|
d->linestart = false;
|
|
@@ -243,15 +251,16 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
|
|
void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
|
|
void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
|
|
{
|
|
{
|
|
MuxChardev *d = MUX_CHARDEV(chr);
|
|
MuxChardev *d = MUX_CHARDEV(chr);
|
|
- unsigned int i;
|
|
|
|
|
|
+ int bit;
|
|
|
|
|
|
if (!muxes_opened) {
|
|
if (!muxes_opened) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* Send the event to all registered listeners */
|
|
/* 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 +285,11 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
|
|
static void char_mux_finalize(Object *obj)
|
|
static void char_mux_finalize(Object *obj)
|
|
{
|
|
{
|
|
MuxChardev *d = MUX_CHARDEV(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) {
|
|
if (be) {
|
|
be->chr = NULL;
|
|
be->chr = NULL;
|
|
}
|
|
}
|
|
@@ -304,7 +314,10 @@ static void mux_chr_update_read_handlers(Chardev *chr)
|
|
bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b,
|
|
bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b,
|
|
unsigned int *tag, Error **errp)
|
|
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,
|
|
error_setg(errp,
|
|
"too many uses of multiplexed chardev '%s'"
|
|
"too many uses of multiplexed chardev '%s'"
|
|
" (maximum is " stringify(MAX_MUX) ")",
|
|
" (maximum is " stringify(MAX_MUX) ")",
|
|
@@ -312,8 +325,9 @@ bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b,
|
|
return false;
|
|
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;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -322,7 +336,7 @@ void mux_set_focus(Chardev *chr, unsigned int focus)
|
|
{
|
|
{
|
|
MuxChardev *d = MUX_CHARDEV(chr);
|
|
MuxChardev *d = MUX_CHARDEV(chr);
|
|
|
|
|
|
- assert(focus < d->mux_cnt);
|
|
|
|
|
|
+ assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) == focus);
|
|
|
|
|
|
if (d->focus != -1) {
|
|
if (d->focus != -1) {
|
|
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
|
|
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
|