mux: split mux_chr_update_read_handler()

Make qemu_chr_add_handlers_full() aware of mux handling. This allows
introduction of a tag associated with the fe handlers and a
qemu_chr_set_handlers() function to set the handler for a particular
tag. That will allow to get rid of qemu_chr_add_handlers*() in later
changes, in favor of qemu_chr_fe_set_handler().

To this end, chr_update_read_handler callback is enhanced with a tag
argument, and mux_chr_update_read_handler() is splitted in new
functions: mux_chr_new_handler_tag(), mux_chr_set_handlers(),
mux_set_focus().

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20161022095318.17775-9-marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Marc-André Lureau 2016-10-22 12:52:48 +03:00 committed by Paolo Bonzini
parent c8cccba312
commit 6dfa8298fa
2 changed files with 99 additions and 42 deletions

View File

@ -80,7 +80,7 @@ struct CharDriverState {
const uint8_t *buf, int len); const uint8_t *buf, int len);
GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond); GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
void (*chr_update_read_handler)(struct CharDriverState *s, void (*chr_update_read_handler)(struct CharDriverState *s,
GMainContext *context); GMainContext *context, int tag);
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
int (*get_msgfds)(struct CharDriverState *s, int* fds, int num); int (*get_msgfds)(struct CharDriverState *s, int* fds, int num);
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num); int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);

View File

@ -89,6 +89,8 @@
#define READ_RETRIES 10 #define READ_RETRIES 10
#define TCP_MAX_FDS 16 #define TCP_MAX_FDS 16
typedef struct MuxDriver MuxDriver;
/***********************************************************/ /***********************************************************/
/* Socket address helpers */ /* Socket address helpers */
@ -449,12 +451,14 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
static void remove_fd_in_watch(CharDriverState *chr); static void remove_fd_in_watch(CharDriverState *chr);
void qemu_chr_add_handlers_full(CharDriverState *s, static void
IOCanReadHandler *fd_can_read, qemu_chr_set_handlers(CharDriverState *s,
IOReadHandler *fd_read, IOCanReadHandler *fd_can_read,
IOEventHandler *fd_event, IOReadHandler *fd_read,
void *opaque, IOEventHandler *fd_event,
GMainContext *context) void *opaque,
GMainContext *context,
int tag)
{ {
int fe_open; int fe_open;
@ -469,7 +473,7 @@ void qemu_chr_add_handlers_full(CharDriverState *s,
s->chr_event = fd_event; s->chr_event = fd_event;
s->handler_opaque = opaque; s->handler_opaque = opaque;
if (s->chr_update_read_handler) { if (s->chr_update_read_handler) {
s->chr_update_read_handler(s, context); s->chr_update_read_handler(s, context, tag);
} }
if (!s->explicit_fe_open) { if (!s->explicit_fe_open) {
@ -483,6 +487,34 @@ void qemu_chr_add_handlers_full(CharDriverState *s,
} }
} }
static int mux_chr_new_handler_tag(CharDriverState *chr, Error **errp);
static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context);
static void mux_set_focus(MuxDriver *d, int focus);
void qemu_chr_add_handlers_full(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque,
GMainContext *context)
{
int tag = 0;
if (s->is_mux) {
tag = mux_chr_new_handler_tag(s, &error_abort);
if (tag == 0) {
mux_chr_set_handlers(s, context);
}
}
qemu_chr_set_handlers(s, fd_can_read, fd_read,
fd_event, opaque, context, tag);
if (s->is_mux) {
mux_set_focus(s->opaque, tag);
}
}
void qemu_chr_add_handlers(CharDriverState *s, void qemu_chr_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read, IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read, IOReadHandler *fd_read,
@ -519,7 +551,7 @@ static CharDriverState *qemu_chr_open_null(const char *id,
#define MAX_MUX 4 #define MAX_MUX 4
#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ #define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
typedef struct { struct MuxDriver {
IOCanReadHandler *chr_can_read[MAX_MUX]; IOCanReadHandler *chr_can_read[MAX_MUX];
IOReadHandler *chr_read[MAX_MUX]; IOReadHandler *chr_read[MAX_MUX];
IOEventHandler *chr_event[MAX_MUX]; IOEventHandler *chr_event[MAX_MUX];
@ -540,8 +572,7 @@ typedef struct {
/* Protected by the CharDriverState chr_write_lock. */ /* Protected by the CharDriverState chr_write_lock. */
int linestart; int linestart;
int64_t timestamps_start; int64_t timestamps_start;
} MuxDriver; };
/* Called with chr_write_lock held. */ /* Called with chr_write_lock held. */
static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@ -655,12 +686,9 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
qemu_chr_be_event(chr, CHR_EVENT_BREAK); qemu_chr_be_event(chr, CHR_EVENT_BREAK);
break; break;
case 'c': case 'c':
assert(d->mux_cnt > 0); /* handler registered with first fe */
/* Switch to the next registered device */ /* Switch to the next registered device */
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); mux_set_focus(d, (d->focus + 1) % d->mux_cnt);
d->focus++;
if (d->focus >= d->mux_cnt)
d->focus = 0;
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
break; break;
case 't': case 't':
d->timestamps = !d->timestamps; d->timestamps = !d->timestamps;
@ -735,31 +763,18 @@ static void mux_chr_event(void *opaque, int event)
} }
static void mux_chr_update_read_handler(CharDriverState *chr, static void mux_chr_update_read_handler(CharDriverState *chr,
GMainContext *context) GMainContext *context,
int tag)
{ {
MuxDriver *d = chr->opaque; MuxDriver *d = chr->opaque;
if (d->mux_cnt >= MAX_MUX) { assert(tag >= 0);
fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n"); assert(tag < d->mux_cnt);
return;
} d->ext_opaque[tag] = chr->handler_opaque;
d->ext_opaque[d->mux_cnt] = chr->handler_opaque; d->chr_can_read[tag] = chr->chr_can_read;
d->chr_can_read[d->mux_cnt] = chr->chr_can_read; d->chr_read[tag] = chr->chr_read;
d->chr_read[d->mux_cnt] = chr->chr_read; d->chr_event[tag] = chr->chr_event;
d->chr_event[d->mux_cnt] = chr->chr_event;
/* Fix up the real driver with mux routines */
if (d->mux_cnt == 0) {
qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
mux_chr_read,
mux_chr_event,
chr, context);
}
if (d->focus != -1) {
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
}
d->focus = d->mux_cnt;
d->mux_cnt++;
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
} }
static bool muxes_realized; static bool muxes_realized;
@ -815,6 +830,44 @@ static void mux_chr_close(struct CharDriverState *chr)
g_free(d); g_free(d);
} }
static int mux_chr_new_handler_tag(CharDriverState *chr, Error **errp)
{
MuxDriver *d = chr->opaque;
if (d->mux_cnt >= MAX_MUX) {
fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
return -1;
}
return d->mux_cnt++;
}
static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context)
{
MuxDriver *d = chr->opaque;
/* Fix up the real driver with mux routines */
qemu_chr_add_handlers_full(d->drv,
mux_chr_can_read,
mux_chr_read,
mux_chr_event,
chr,
context);
}
static void mux_set_focus(MuxDriver *d, int focus)
{
assert(focus >= 0);
assert(focus < d->mux_cnt);
if (d->focus != -1) {
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
}
d->focus = focus;
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
}
static CharDriverState *qemu_chr_open_mux(const char *id, static CharDriverState *qemu_chr_open_mux(const char *id,
ChardevBackend *backend, ChardevBackend *backend,
ChardevReturn *ret, Error **errp) ChardevReturn *ret, Error **errp)
@ -1085,7 +1138,8 @@ static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond)
} }
static void fd_chr_update_read_handler(CharDriverState *chr, static void fd_chr_update_read_handler(CharDriverState *chr,
GMainContext *context) GMainContext *context,
int tag)
{ {
FDCharDriver *s = chr->opaque; FDCharDriver *s = chr->opaque;
@ -1342,7 +1396,8 @@ static void pty_chr_update_read_handler_locked(CharDriverState *chr)
} }
static void pty_chr_update_read_handler(CharDriverState *chr, static void pty_chr_update_read_handler(CharDriverState *chr,
GMainContext *context) GMainContext *context,
int tag)
{ {
qemu_mutex_lock(&chr->chr_write_lock); qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_update_read_handler_locked(chr); pty_chr_update_read_handler_locked(chr);
@ -2589,7 +2644,8 @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
} }
static void udp_chr_update_read_handler(CharDriverState *chr, static void udp_chr_update_read_handler(CharDriverState *chr,
GMainContext *context) GMainContext *context,
int tag)
{ {
NetCharDriver *s = chr->opaque; NetCharDriver *s = chr->opaque;
@ -3008,7 +3064,8 @@ static void tcp_chr_connect(void *opaque)
} }
static void tcp_chr_update_read_handler(CharDriverState *chr, static void tcp_chr_update_read_handler(CharDriverState *chr,
GMainContext *context) GMainContext *context,
int tag)
{ {
TCPCharDriver *s = chr->opaque; TCPCharDriver *s = chr->opaque;