]> git.proxmox.com Git - mirror_qemu.git/blob - replay/replay.c
replay: shutdown event
[mirror_qemu.git] / replay / replay.c
1 /*
2 * replay.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
12 #include "qemu-common.h"
13 #include "sysemu/replay.h"
14 #include "replay-internal.h"
15 #include "qemu/timer.h"
16 #include "qemu/main-loop.h"
17 #include "sysemu/sysemu.h"
18
19 ReplayMode replay_mode = REPLAY_MODE_NONE;
20
21 ReplayState replay_state;
22
23 bool replay_next_event_is(int event)
24 {
25 bool res = false;
26
27 /* nothing to skip - not all instructions used */
28 if (replay_state.instructions_count != 0) {
29 assert(replay_data_kind == EVENT_INSTRUCTION);
30 return event == EVENT_INSTRUCTION;
31 }
32
33 while (true) {
34 if (event == replay_data_kind) {
35 res = true;
36 }
37 switch (replay_data_kind) {
38 case EVENT_SHUTDOWN:
39 replay_finish_event();
40 qemu_system_shutdown_request();
41 break;
42 default:
43 /* clock, time_t, checkpoint and other events */
44 return res;
45 }
46 }
47 return res;
48 }
49
50 uint64_t replay_get_current_step(void)
51 {
52 return cpu_get_icount_raw();
53 }
54
55 int replay_get_instructions(void)
56 {
57 int res = 0;
58 replay_mutex_lock();
59 if (replay_next_event_is(EVENT_INSTRUCTION)) {
60 res = replay_state.instructions_count;
61 }
62 replay_mutex_unlock();
63 return res;
64 }
65
66 void replay_account_executed_instructions(void)
67 {
68 if (replay_mode == REPLAY_MODE_PLAY) {
69 replay_mutex_lock();
70 if (replay_state.instructions_count > 0) {
71 int count = (int)(replay_get_current_step()
72 - replay_state.current_step);
73 replay_state.instructions_count -= count;
74 replay_state.current_step += count;
75 if (replay_state.instructions_count == 0) {
76 assert(replay_data_kind == EVENT_INSTRUCTION);
77 replay_finish_event();
78 /* Wake up iothread. This is required because
79 timers will not expire until clock counters
80 will be read from the log. */
81 qemu_notify_event();
82 }
83 }
84 replay_mutex_unlock();
85 }
86 }
87
88 bool replay_exception(void)
89 {
90 if (replay_mode == REPLAY_MODE_RECORD) {
91 replay_save_instructions();
92 replay_mutex_lock();
93 replay_put_event(EVENT_EXCEPTION);
94 replay_mutex_unlock();
95 return true;
96 } else if (replay_mode == REPLAY_MODE_PLAY) {
97 bool res = replay_has_exception();
98 if (res) {
99 replay_mutex_lock();
100 replay_finish_event();
101 replay_mutex_unlock();
102 }
103 return res;
104 }
105
106 return true;
107 }
108
109 bool replay_has_exception(void)
110 {
111 bool res = false;
112 if (replay_mode == REPLAY_MODE_PLAY) {
113 replay_account_executed_instructions();
114 replay_mutex_lock();
115 res = replay_next_event_is(EVENT_EXCEPTION);
116 replay_mutex_unlock();
117 }
118
119 return res;
120 }
121
122 bool replay_interrupt(void)
123 {
124 if (replay_mode == REPLAY_MODE_RECORD) {
125 replay_save_instructions();
126 replay_mutex_lock();
127 replay_put_event(EVENT_INTERRUPT);
128 replay_mutex_unlock();
129 return true;
130 } else if (replay_mode == REPLAY_MODE_PLAY) {
131 bool res = replay_has_interrupt();
132 if (res) {
133 replay_mutex_lock();
134 replay_finish_event();
135 replay_mutex_unlock();
136 }
137 return res;
138 }
139
140 return true;
141 }
142
143 bool replay_has_interrupt(void)
144 {
145 bool res = false;
146 if (replay_mode == REPLAY_MODE_PLAY) {
147 replay_account_executed_instructions();
148 replay_mutex_lock();
149 res = replay_next_event_is(EVENT_INTERRUPT);
150 replay_mutex_unlock();
151 }
152 return res;
153 }
154
155 void replay_shutdown_request(void)
156 {
157 if (replay_mode == REPLAY_MODE_RECORD) {
158 replay_mutex_lock();
159 replay_put_event(EVENT_SHUTDOWN);
160 replay_mutex_unlock();
161 }
162 }