]> git.proxmox.com Git - mirror_qemu.git/blame - replay/replay-internal.c
replay: don't destroy mutex at exit
[mirror_qemu.git] / replay / replay-internal.c
CommitLineData
c92079f4
PD
1/*
2 * replay-internal.c
3 *
4 * Copyright (c) 2010-2015 Institute for System Programming
5 * of the Russian Academy of Sciences.
6 *
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.
9 *
10 */
11
d38ea87a 12#include "qemu/osdep.h"
c92079f4 13#include "qemu-common.h"
26bc60ac 14#include "sysemu/replay.h"
c92079f4
PD
15#include "replay-internal.h"
16#include "qemu/error-report.h"
17#include "sysemu/sysemu.h"
18
c16861ef 19/* Mutex to protect reading and writing events to the log.
f186d64d 20 data_kind and has_unread_data are also protected
c16861ef
PD
21 by this mutex.
22 It also protects replay events queue which stores events to be
23 written or read to the log. */
24static QemuMutex lock;
25
c92079f4
PD
26/* File for replay writing */
27FILE *replay_file;
28
29void replay_put_byte(uint8_t byte)
30{
31 if (replay_file) {
32 putc(byte, replay_file);
33 }
34}
35
36void replay_put_event(uint8_t event)
37{
26bc60ac 38 assert(event < EVENT_COUNT);
c92079f4
PD
39 replay_put_byte(event);
40}
41
42
43void replay_put_word(uint16_t word)
44{
45 replay_put_byte(word >> 8);
46 replay_put_byte(word);
47}
48
49void replay_put_dword(uint32_t dword)
50{
51 replay_put_word(dword >> 16);
52 replay_put_word(dword);
53}
54
55void replay_put_qword(int64_t qword)
56{
57 replay_put_dword(qword >> 32);
58 replay_put_dword(qword);
59}
60
61void replay_put_array(const uint8_t *buf, size_t size)
62{
63 if (replay_file) {
64 replay_put_dword(size);
65 fwrite(buf, 1, size, replay_file);
66 }
67}
68
69uint8_t replay_get_byte(void)
70{
71 uint8_t byte = 0;
72 if (replay_file) {
73 byte = getc(replay_file);
74 }
75 return byte;
76}
77
78uint16_t replay_get_word(void)
79{
80 uint16_t word = 0;
81 if (replay_file) {
82 word = replay_get_byte();
83 word = (word << 8) + replay_get_byte();
84 }
85
86 return word;
87}
88
89uint32_t replay_get_dword(void)
90{
91 uint32_t dword = 0;
92 if (replay_file) {
93 dword = replay_get_word();
94 dword = (dword << 16) + replay_get_word();
95 }
96
97 return dword;
98}
99
100int64_t replay_get_qword(void)
101{
102 int64_t qword = 0;
103 if (replay_file) {
104 qword = replay_get_dword();
105 qword = (qword << 32) + replay_get_dword();
106 }
107
108 return qword;
109}
110
111void replay_get_array(uint8_t *buf, size_t *size)
112{
113 if (replay_file) {
114 *size = replay_get_dword();
115 if (fread(buf, 1, *size, replay_file) != *size) {
116 error_report("replay read error");
117 }
118 }
119}
120
121void replay_get_array_alloc(uint8_t **buf, size_t *size)
122{
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");
128 }
129 }
130}
131
132void replay_check_error(void)
133{
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);
143 }
144 }
145}
146
147void replay_fetch_data_kind(void)
148{
149 if (replay_file) {
f186d64d
PD
150 if (!replay_state.has_unread_data) {
151 replay_state.data_kind = replay_get_byte();
152 if (replay_state.data_kind == EVENT_INSTRUCTION) {
26bc60ac
PD
153 replay_state.instructions_count = replay_get_dword();
154 }
c92079f4 155 replay_check_error();
f186d64d
PD
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);
26bc60ac
PD
160 exit(1);
161 }
c92079f4
PD
162 }
163 }
164}
165
166void replay_finish_event(void)
167{
f186d64d 168 replay_state.has_unread_data = 0;
c92079f4
PD
169 replay_fetch_data_kind();
170}
c16861ef 171
180d30be
AB
172static __thread bool replay_locked;
173
c16861ef
PD
174void replay_mutex_init(void)
175{
176 qemu_mutex_init(&lock);
177}
178
a36544d3 179bool replay_mutex_locked(void)
180d30be
AB
180{
181 return replay_locked;
182}
183
c16861ef
PD
184void replay_mutex_lock(void)
185{
180d30be 186 g_assert(!replay_mutex_locked());
c16861ef 187 qemu_mutex_lock(&lock);
180d30be 188 replay_locked = true;
c16861ef
PD
189}
190
191void replay_mutex_unlock(void)
192{
180d30be
AB
193 g_assert(replay_mutex_locked());
194 replay_locked = false;
c16861ef
PD
195 qemu_mutex_unlock(&lock);
196}
26bc60ac
PD
197
198/*! Saves cached instructions. */
199void replay_save_instructions(void)
200{
201 if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
202 replay_mutex_lock();
203 int diff = (int)(replay_get_current_step() - replay_state.current_step);
982263ce
AB
204
205 /* Time can only go forward */
206 assert(diff >= 0);
207
26bc60ac
PD
208 if (diff > 0) {
209 replay_put_event(EVENT_INSTRUCTION);
210 replay_put_dword(diff);
211 replay_state.current_step += diff;
212 }
213 replay_mutex_unlock();
214 }
215}