summaryrefslogtreecommitdiffstats
path: root/include/qemu/log.h
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/qemu/log.h
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/qemu/log.h')
-rw-r--r--include/qemu/log.h41
1 files changed, 35 insertions, 6 deletions
diff --git a/include/qemu/log.h b/include/qemu/log.h
index a7c5b01571..e0f4e40628 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -3,9 +3,16 @@
/* A small part of this API is split into its own header */
#include "qemu/log-for-trace.h"
+#include "qemu/rcu.h"
+
+typedef struct QemuLogFile {
+ struct rcu_head rcu;
+ FILE *fd;
+} QemuLogFile;
/* Private global variable, don't use */
-extern FILE *qemu_logfile;
+extern QemuLogFile *qemu_logfile;
+
/*
* The new API:
@@ -25,7 +32,16 @@ static inline bool qemu_log_enabled(void)
*/
static inline bool qemu_log_separate(void)
{
- return qemu_logfile != NULL && qemu_logfile != stderr;
+ QemuLogFile *logfile;
+ bool res = false;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile && logfile->fd != stderr) {
+ res = true;
+ }
+ rcu_read_unlock();
+ return res;
}
#define CPU_LOG_TB_OUT_ASM (1 << 0)
@@ -55,8 +71,15 @@ static inline bool qemu_log_separate(void)
static inline FILE *qemu_log_lock(void)
{
- qemu_flockfile(qemu_logfile);
- return logfile->fd;
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ qemu_flockfile(logfile->fd);
+ return logfile->fd;
+ } else {
+ return NULL;
+ }
}
static inline void qemu_log_unlock(FILE *fd)
@@ -64,6 +87,7 @@ static inline void qemu_log_unlock(FILE *fd)
if (fd) {
qemu_funlockfile(fd);
}
+ rcu_read_unlock();
}
/* Logging functions: */
@@ -73,9 +97,14 @@ static inline void qemu_log_unlock(FILE *fd)
static inline void GCC_FMT_ATTR(1, 0)
qemu_log_vprintf(const char *fmt, va_list va)
{
- if (qemu_logfile) {
- vfprintf(qemu_logfile, fmt, va);
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ vfprintf(logfile->fd, fmt, va);
}
+ rcu_read_unlock();
}
/* log only if a bit is set on the current loglevel mask: