block: Require .bdrv_child_perm() with child nodes
[qemu/ar7.git] / replay / replay-internal.c
blobbea7b4aa6b18a2875f413ab9292b248aa723a093
1 /*
2 * replay-internal.c
4 * Copyright (c) 2010-2015 Institute for System Programming
5 * of the Russian Academy of Sciences.
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "qemu-common.h"
14 #include "sysemu/replay.h"
15 #include "replay-internal.h"
16 #include "qemu/error-report.h"
17 #include "sysemu/sysemu.h"
19 /* Mutex to protect reading and writing events to the log.
20 data_kind and has_unread_data are also protected
21 by this mutex.
22 It also protects replay events queue which stores events to be
23 written or read to the log. */
24 static QemuMutex lock;
26 /* File for replay writing */
27 FILE *replay_file;
29 void replay_put_byte(uint8_t byte)
31 if (replay_file) {
32 putc(byte, replay_file);
36 void replay_put_event(uint8_t event)
38 assert(event < EVENT_COUNT);
39 replay_put_byte(event);
43 void replay_put_word(uint16_t word)
45 replay_put_byte(word >> 8);
46 replay_put_byte(word);
49 void replay_put_dword(uint32_t dword)
51 replay_put_word(dword >> 16);
52 replay_put_word(dword);
55 void replay_put_qword(int64_t qword)
57 replay_put_dword(qword >> 32);
58 replay_put_dword(qword);
61 void replay_put_array(const uint8_t *buf, size_t size)
63 if (replay_file) {
64 replay_put_dword(size);
65 fwrite(buf, 1, size, replay_file);
69 uint8_t replay_get_byte(void)
71 uint8_t byte = 0;
72 if (replay_file) {
73 byte = getc(replay_file);
75 return byte;
78 uint16_t replay_get_word(void)
80 uint16_t word = 0;
81 if (replay_file) {
82 word = replay_get_byte();
83 word = (word << 8) + replay_get_byte();
86 return word;
89 uint32_t replay_get_dword(void)
91 uint32_t dword = 0;
92 if (replay_file) {
93 dword = replay_get_word();
94 dword = (dword << 16) + replay_get_word();
97 return dword;
100 int64_t replay_get_qword(void)
102 int64_t qword = 0;
103 if (replay_file) {
104 qword = replay_get_dword();
105 qword = (qword << 32) + replay_get_dword();
108 return qword;
111 void replay_get_array(uint8_t *buf, size_t *size)
113 if (replay_file) {
114 *size = replay_get_dword();
115 if (fread(buf, 1, *size, replay_file) != *size) {
116 error_report("replay read error");
121 void replay_get_array_alloc(uint8_t **buf, size_t *size)
123 if (replay_file) {
124 *size = replay_get_dword();
125 *buf = g_malloc(*size);
126 if (fread(*buf, 1, *size, replay_file) != *size) {
127 error_report("replay read error");
132 void replay_check_error(void)
134 if (replay_file) {
135 if (feof(replay_file)) {
136 error_report("replay file is over");
137 qemu_system_vmstop_request_prepare();
138 qemu_system_vmstop_request(RUN_STATE_PAUSED);
139 } else if (ferror(replay_file)) {
140 error_report("replay file is over or something goes wrong");
141 qemu_system_vmstop_request_prepare();
142 qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR);
147 void replay_fetch_data_kind(void)
149 if (replay_file) {
150 if (!replay_state.has_unread_data) {
151 replay_state.data_kind = replay_get_byte();
152 if (replay_state.data_kind == EVENT_INSTRUCTION) {
153 replay_state.instructions_count = replay_get_dword();
155 replay_check_error();
156 replay_state.has_unread_data = 1;
157 if (replay_state.data_kind >= EVENT_COUNT) {
158 error_report("Replay: unknown event kind %d",
159 replay_state.data_kind);
160 exit(1);
166 void replay_finish_event(void)
168 replay_state.has_unread_data = 0;
169 replay_fetch_data_kind();
172 void replay_mutex_init(void)
174 qemu_mutex_init(&lock);
177 void replay_mutex_destroy(void)
179 qemu_mutex_destroy(&lock);
182 void replay_mutex_lock(void)
184 qemu_mutex_lock(&lock);
187 void replay_mutex_unlock(void)
189 qemu_mutex_unlock(&lock);
192 /*! Saves cached instructions. */
193 void replay_save_instructions(void)
195 if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
196 replay_mutex_lock();
197 int diff = (int)(replay_get_current_step() - replay_state.current_step);
198 if (diff > 0) {
199 replay_put_event(EVENT_INSTRUCTION);
200 replay_put_dword(diff);
201 replay_state.current_step += diff;
203 replay_mutex_unlock();