console: use linked list for QemuConsoles

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20180507095424.16220-1-kraxel@redhat.com
This commit is contained in:
Gerd Hoffmann 2018-05-07 11:54:24 +02:00
parent 7a61f43859
commit cd6cd8fa0d
1 changed files with 58 additions and 47 deletions

View File

@ -165,6 +165,8 @@ struct QemuConsole {
QEMUFIFO out_fifo; QEMUFIFO out_fifo;
uint8_t out_fifo_buf[16]; uint8_t out_fifo_buf[16];
QEMUTimer *kbd_timer; QEMUTimer *kbd_timer;
QTAILQ_ENTRY(QemuConsole) next;
}; };
struct DisplayState { struct DisplayState {
@ -180,8 +182,8 @@ struct DisplayState {
static DisplayState *display_state; static DisplayState *display_state;
static QemuConsole *active_console; static QemuConsole *active_console;
static QemuConsole **consoles; static QTAILQ_HEAD(consoles_head, QemuConsole) consoles =
static int nb_consoles = 0; QTAILQ_HEAD_INITIALIZER(consoles);
static bool cursor_visible_phase; static bool cursor_visible_phase;
static QEMUTimer *cursor_timer; static QEMUTimer *cursor_timer;
@ -197,7 +199,7 @@ static void gui_update(void *opaque)
uint64_t dcl_interval; uint64_t dcl_interval;
DisplayState *ds = opaque; DisplayState *ds = opaque;
DisplayChangeListener *dcl; DisplayChangeListener *dcl;
int i; QemuConsole *con;
ds->refreshing = true; ds->refreshing = true;
dpy_refresh(ds); dpy_refresh(ds);
@ -212,9 +214,9 @@ static void gui_update(void *opaque)
} }
if (ds->update_interval != interval) { if (ds->update_interval != interval) {
ds->update_interval = interval; ds->update_interval = interval;
for (i = 0; i < nb_consoles; i++) { QTAILQ_FOREACH(con, &consoles, next) {
if (consoles[i]->hw_ops->update_interval) { if (con->hw_ops->update_interval) {
consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval); con->hw_ops->update_interval(con->hw, interval);
} }
} }
trace_console_refresh(interval); trace_console_refresh(interval);
@ -1292,10 +1294,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
s->ds = ds; s->ds = ds;
s->console_type = console_type; s->console_type = console_type;
consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1)); if (QTAILQ_EMPTY(&consoles)) {
if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { s->index = 0;
s->index = nb_consoles; QTAILQ_INSERT_TAIL(&consoles, s, next);
consoles[nb_consoles++] = s; } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
QemuConsole *last = QTAILQ_LAST(&consoles, consoles_head);
s->index = last->index + 1;
QTAILQ_INSERT_TAIL(&consoles, s, next);
} else { } else {
/* /*
* HACK: Put graphical consoles before text consoles. * HACK: Put graphical consoles before text consoles.
@ -1303,15 +1308,24 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
* Only do that for coldplugged devices. After initial device * Only do that for coldplugged devices. After initial device
* initialization we will not renumber the consoles any more. * initialization we will not renumber the consoles any more.
*/ */
for (i = nb_consoles; i > 0; i--) { QemuConsole *c = QTAILQ_FIRST(&consoles);
if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
break; while (QTAILQ_NEXT(c, next) != NULL &&
consoles[i] = consoles[i - 1]; c->console_type == GRAPHIC_CONSOLE) {
consoles[i]->index = i; c = QTAILQ_NEXT(c, next);
}
if (c->console_type == GRAPHIC_CONSOLE) {
/* have no text consoles */
s->index = c->index + 1;
QTAILQ_INSERT_AFTER(&consoles, c, s, next);
} else {
s->index = c->index;
QTAILQ_INSERT_BEFORE(c, s, next);
/* renumber text consoles */
for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) {
c->index = i;
}
} }
s->index = i;
consoles[i] = s;
nb_consoles++;
} }
return s; return s;
} }
@ -1861,21 +1875,21 @@ static DisplayState *get_alloc_displaystate(void)
DisplayState *init_displaystate(void) DisplayState *init_displaystate(void)
{ {
gchar *name; gchar *name;
int i; QemuConsole *con;
get_alloc_displaystate(); get_alloc_displaystate();
for (i = 0; i < nb_consoles; i++) { QTAILQ_FOREACH(con, &consoles, next) {
if (consoles[i]->console_type != GRAPHIC_CONSOLE && if (con->console_type != GRAPHIC_CONSOLE &&
consoles[i]->ds == NULL) { con->ds == NULL) {
text_console_do_init(consoles[i]->chr, display_state); text_console_do_init(con->chr, display_state);
} }
/* Hook up into the qom tree here (not in new_console()), once /* Hook up into the qom tree here (not in new_console()), once
* all QemuConsoles are created and the order / numbering * all QemuConsoles are created and the order / numbering
* doesn't change any more */ * doesn't change any more */
name = g_strdup_printf("console[%d]", i); name = g_strdup_printf("console[%d]", con->index);
object_property_add_child(container_get(object_get_root(), "/backend"), object_property_add_child(container_get(object_get_root(), "/backend"),
name, OBJECT(consoles[i]), &error_abort); name, OBJECT(con), &error_abort);
g_free(name); g_free(name);
} }
@ -1957,33 +1971,34 @@ void graphic_console_close(QemuConsole *con)
QemuConsole *qemu_console_lookup_by_index(unsigned int index) QemuConsole *qemu_console_lookup_by_index(unsigned int index)
{ {
if (index >= nb_consoles) { QemuConsole *con;
return NULL;
QTAILQ_FOREACH(con, &consoles, next) {
if (con->index == index) {
return con;
}
} }
return consoles[index]; return NULL;
} }
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head) QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
{ {
QemuConsole *con;
Object *obj; Object *obj;
uint32_t h; uint32_t h;
int i;
for (i = 0; i < nb_consoles; i++) { QTAILQ_FOREACH(con, &consoles, next) {
if (!consoles[i]) { obj = object_property_get_link(OBJECT(con),
continue;
}
obj = object_property_get_link(OBJECT(consoles[i]),
"device", &error_abort); "device", &error_abort);
if (DEVICE(obj) != dev) { if (DEVICE(obj) != dev) {
continue; continue;
} }
h = object_property_get_uint(OBJECT(consoles[i]), h = object_property_get_uint(OBJECT(con),
"head", &error_abort); "head", &error_abort);
if (h != head) { if (h != head) {
continue; continue;
} }
return consoles[i]; return con;
} }
return NULL; return NULL;
} }
@ -2013,22 +2028,19 @@ QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,
QemuConsole *qemu_console_lookup_unused(void) QemuConsole *qemu_console_lookup_unused(void)
{ {
QemuConsole *con;
Object *obj; Object *obj;
int i;
for (i = 0; i < nb_consoles; i++) { QTAILQ_FOREACH(con, &consoles, next) {
if (!consoles[i]) { if (con->hw_ops != &unused_ops) {
continue; continue;
} }
if (consoles[i]->hw_ops != &unused_ops) { obj = object_property_get_link(OBJECT(con),
continue;
}
obj = object_property_get_link(OBJECT(consoles[i]),
"device", &error_abort); "device", &error_abort);
if (obj != NULL) { if (obj != NULL) {
continue; continue;
} }
return consoles[i]; return con;
} }
return NULL; return NULL;
} }
@ -2130,12 +2142,11 @@ static void text_console_update_cursor_timer(void)
static void text_console_update_cursor(void *opaque) static void text_console_update_cursor(void *opaque)
{ {
QemuConsole *s; QemuConsole *s;
int i, count = 0; int count = 0;
cursor_visible_phase = !cursor_visible_phase; cursor_visible_phase = !cursor_visible_phase;
for (i = 0; i < nb_consoles; i++) { QTAILQ_FOREACH(s, &consoles, next) {
s = consoles[i];
if (qemu_console_is_graphic(s) || if (qemu_console_is_graphic(s) ||
!qemu_console_is_visible(s)) { !qemu_console_is_visible(s)) {
continue; continue;