summaryrefslogtreecommitdiffstats
path: root/include/exec
diff options
context:
space:
mode:
authorRobert Foley2019-11-18 22:15:27 +0100
committerAlex Bennée2019-12-18 21:18:02 +0100
commit7606488c0efa8f631d31ab9ff8d33b7cf3e2a4c9 (patch)
tree7d8c50f162c7cf51b14ddf02377e426e6dae7b83 /include/exec
parentqemu_log_lock/unlock now preserves the qemu_logfile handle. (diff)
downloadqemu-7606488c0efa8f631d31ab9ff8d33b7cf3e2a4c9.tar.gz
qemu-7606488c0efa8f631d31ab9ff8d33b7cf3e2a4c9.tar.xz
qemu-7606488c0efa8f631d31ab9ff8d33b7cf3e2a4c9.zip
Add use of RCU for qemu_logfile.
This now allows changing the logfile while logging is active, and also solves the issue of a seg fault while changing the logfile. Any read access to the qemu_logfile handle will use the rcu_read_lock()/unlock() around the use of the handle. To fetch the handle we will use atomic_rcu_read(). We also in many cases do a check for validity of the logfile handle before using it to deal with the case where the file is closed and set to NULL. The cases where we write to the qemu_logfile will use atomic_rcu_set(). Writers will also use call_rcu() with a newly added qemu_logfile_free function for freeing/closing when readers have finished. Signed-off-by: Robert Foley <robert.foley@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20191118211528.3221-6-robert.foley@linaro.org>
Diffstat (limited to 'include/exec')
-rw-r--r--include/exec/log.h33
1 files changed, 29 insertions, 4 deletions
diff --git a/include/exec/log.h b/include/exec/log.h
index e2cfd436e6..9bd1e4aa20 100644
--- a/include/exec/log.h
+++ b/include/exec/log.h
@@ -15,8 +15,15 @@
*/
static inline void log_cpu_state(CPUState *cpu, int flags)
{
+ QemuLogFile *logfile;
+
if (qemu_log_enabled()) {
- cpu_dump_state(cpu, qemu_logfile, flags);
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ cpu_dump_state(cpu, logfile->fd, flags);
+ }
+ rcu_read_unlock();
}
}
@@ -40,19 +47,37 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
static inline void log_target_disas(CPUState *cpu, target_ulong start,
target_ulong len)
{
- target_disas(qemu_logfile, cpu, start, len);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ target_disas(logfile->fd, cpu, start, len);
+ }
+ rcu_read_unlock();
}
static inline void log_disas(void *code, unsigned long size)
{
- disas(qemu_logfile, code, size);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ disas(logfile->fd, code, size);
+ }
+ rcu_read_unlock();
}
#if defined(CONFIG_USER_ONLY)
/* page_dump() output to the log file: */
static inline void log_page_dump(void)
{
- page_dump(qemu_logfile);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ page_dump(logfile->fd);
+ }
+ rcu_read_unlock();
}
#endif
#endif