qemu/replay/replay-char.c
Markus Armbruster d5938f29fe Clean up inclusion of sysemu/sysemu.h
In my "build everything" tree, changing sysemu/sysemu.h triggers a
recompile of some 5400 out of 6600 objects (not counting tests and
objects that don't depend on qemu/osdep.h).

Almost a third of its inclusions are actually superfluous.  Delete
them.  Downgrade two more to qapi/qapi-types-run-state.h, and move one
from char/serial.h to char/serial.c.

hw/semihosting/config.c, monitor/monitor.c, qdev-monitor.c, and
stubs/semihost.c define variables declared in sysemu/sysemu.h without
including it.  The compiler is cool with that, but include it anyway.

This doesn't reduce actual use much, as it's still included into
widely included headers.  The next commit will tackle that.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20190812052359.30071-27-armbru@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2019-08-16 13:31:53 +02:00

159 lines
3.8 KiB
C

/*
* replay-char.c
*
* Copyright (c) 2010-2016 Institute for System Programming
* of the Russian Academy of Sciences.
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "sysemu/replay.h"
#include "replay-internal.h"
#include "chardev/char.h"
/* Char drivers that generate qemu_chr_be_write events
that should be saved into the log. */
static Chardev **char_drivers;
static int drivers_count;
/* Char event attributes. */
typedef struct CharEvent {
int id;
uint8_t *buf;
size_t len;
} CharEvent;
static int find_char_driver(Chardev *chr)
{
int i = 0;
for ( ; i < drivers_count ; ++i) {
if (char_drivers[i] == chr) {
return i;
}
}
return -1;
}
void replay_register_char_driver(Chardev *chr)
{
if (replay_mode == REPLAY_MODE_NONE) {
return;
}
char_drivers = g_realloc(char_drivers,
sizeof(*char_drivers) * (drivers_count + 1));
char_drivers[drivers_count++] = chr;
}
void replay_chr_be_write(Chardev *s, uint8_t *buf, int len)
{
CharEvent *event = g_malloc0(sizeof(CharEvent));
event->id = find_char_driver(s);
if (event->id < 0) {
fprintf(stderr, "Replay: cannot find char driver\n");
exit(1);
}
event->buf = g_malloc(len);
memcpy(event->buf, buf, len);
event->len = len;
replay_add_event(REPLAY_ASYNC_EVENT_CHAR_READ, event, NULL, 0);
}
void replay_event_char_read_run(void *opaque)
{
CharEvent *event = (CharEvent *)opaque;
qemu_chr_be_write_impl(char_drivers[event->id], event->buf,
(int)event->len);
g_free(event->buf);
g_free(event);
}
void replay_event_char_read_save(void *opaque)
{
CharEvent *event = (CharEvent *)opaque;
replay_put_byte(event->id);
replay_put_array(event->buf, event->len);
}
void *replay_event_char_read_load(void)
{
CharEvent *event = g_malloc0(sizeof(CharEvent));
event->id = replay_get_byte();
replay_get_array_alloc(&event->buf, &event->len);
return event;
}
void replay_char_write_event_save(int res, int offset)
{
g_assert(replay_mutex_locked());
replay_save_instructions();
replay_put_event(EVENT_CHAR_WRITE);
replay_put_dword(res);
replay_put_dword(offset);
}
void replay_char_write_event_load(int *res, int *offset)
{
g_assert(replay_mutex_locked());
replay_account_executed_instructions();
if (replay_next_event_is(EVENT_CHAR_WRITE)) {
*res = replay_get_dword();
*offset = replay_get_dword();
replay_finish_event();
} else {
error_report("Missing character write event in the replay log");
exit(1);
}
}
int replay_char_read_all_load(uint8_t *buf)
{
g_assert(replay_mutex_locked());
if (replay_next_event_is(EVENT_CHAR_READ_ALL)) {
size_t size;
int res;
replay_get_array(buf, &size);
replay_finish_event();
res = (int)size;
assert(res >= 0);
return res;
} else if (replay_next_event_is(EVENT_CHAR_READ_ALL_ERROR)) {
int res = replay_get_dword();
replay_finish_event();
return res;
} else {
error_report("Missing character read all event in the replay log");
exit(1);
}
}
void replay_char_read_all_save_error(int res)
{
g_assert(replay_mutex_locked());
assert(res < 0);
replay_save_instructions();
replay_put_event(EVENT_CHAR_READ_ALL_ERROR);
replay_put_dword(res);
}
void replay_char_read_all_save_buf(uint8_t *buf, int offset)
{
g_assert(replay_mutex_locked());
replay_save_instructions();
replay_put_event(EVENT_CHAR_READ_ALL);
replay_put_array(buf, offset);
}