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