@@ -1293,9 +1293,11 @@ int cpu_exec_user(CPUState *cs)
{
int trapnr;
+ bql_unlock();
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
+ bql_lock();
process_queued_cpu_work(cs);
return trapnr;
@@ -32,6 +32,7 @@
#include "qemu.h"
#include "signal-common.h"
#include "user/syscall-trace.h"
+#include "qemu/main-loop.h"
/* BSD independent syscall shims */
#include "bsd-file.h"
@@ -935,16 +936,21 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
{
abi_long ret;
+ bql_unlock();
+
if (do_strace) {
print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
}
ret = freebsd_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6,
arg7, arg8);
+
if (do_strace) {
print_freebsd_syscall_ret(num, ret);
}
+ bql_lock();
+
return ret;
}
@@ -48,6 +48,7 @@
#include "qemu/guest-random.h"
#include "gdbstub/user.h"
#include "exec/page-vary.h"
+#include "qemu/main-loop.h"
#include "host-os.h"
#include "target_arch_cpu.h"
@@ -616,6 +617,7 @@ int main(int argc, char **argv)
target_cpu_init(env, regs);
+ bql_lock();
if (gdbstub) {
gdbserver_start(gdbstub);
gdb_handlesig(cpu, 0, NULL, NULL, 0);
@@ -452,3 +452,48 @@ void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
}
}
}
+
+/* The Big QEMU Lock (BQL) */
+static QemuMutex bql = QEMU_MUTEX_INITIALIZER;
+
+QEMU_DEFINE_STATIC_CO_TLS(bool, bql_locked)
+
+bool bql_locked(void)
+{
+ return get_bql_locked();
+}
+
+/*
+ * The BQL is taken from so many places that it is worth profiling the
+ * callers directly, instead of funneling them all through a single function.
+ */
+void bql_lock_impl(const char *file, int line)
+{
+ QemuMutexLockFunc bql_lock_fn = qatomic_read(&bql_mutex_lock_func);
+
+ g_assert(!bql_locked());
+ bql_lock_fn(&bql, file, line);
+ set_bql_locked(true);
+}
+
+void bql_unlock(void)
+{
+ g_assert(bql_locked());
+ set_bql_locked(false);
+ qemu_mutex_unlock(&bql);
+}
+
+void qemu_cond_wait_bql(QemuCond *cond)
+{
+ qemu_cond_wait(cond, &bql);
+}
+
+void qemu_cond_timedwait_bql(QemuCond *cond, int ms)
+{
+ qemu_cond_timedwait(cond, &bql, ms);
+}
+
+void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
+{
+ do_run_on_cpu(cpu, func, data, &bql);
+}
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/cutils.h"
+#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "exec/hwaddr.h"
#include "exec/tb-flush.h"
@@ -169,6 +170,8 @@ void gdb_exit(int code)
{
char buf[4];
+ BQL_LOCK_GUARD();
+
if (!gdbserver_state.init) {
return;
}
@@ -464,6 +467,8 @@ void gdbserver_fork_end(CPUState *cpu, pid_t pid)
char b;
int fd;
+ BQL_LOCK_GUARD();
+
if (!gdbserver_state.init || gdbserver_user_state.fd < 0) {
return;
}
@@ -57,6 +57,7 @@
#include "user-mmap.h"
#include "tcg/perf.h"
#include "exec/page-vary.h"
+#include "qemu/main-loop.h"
#ifdef CONFIG_SEMIHOSTING
#include "semihosting/semihost.h"
@@ -1011,6 +1012,8 @@ int main(int argc, char **argv, char **envp)
target_cpu_copy_regs(env, regs);
+ bql_lock();
+
if (gdbstub) {
if (gdbserver_start(gdbstub) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on %s\n",
@@ -144,6 +144,7 @@
#include "qapi/error.h"
#include "fd-trans.h"
#include "cpu_loop-common.h"
+#include "qemu/main-loop.h"
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
@@ -6529,6 +6530,7 @@ static void *clone_func(void *arg)
/* Wait until the parent has finished initializing the tls state. */
pthread_mutex_lock(&clone_lock);
pthread_mutex_unlock(&clone_lock);
+ bql_lock();
cpu_loop(env);
/* never exits */
return NULL;
@@ -13772,6 +13774,8 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
record_syscall_start(cpu, num, arg1,
arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ bql_unlock();
+
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
}
@@ -13784,6 +13788,8 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
arg3, arg4, arg5, arg6);
}
+ bql_lock();
+
record_syscall_return(cpu, num, ret);
return ret;
}
@@ -65,9 +65,6 @@
#endif /* CONFIG_LINUX */
-/* The Big QEMU Lock (BQL) */
-static QemuMutex bql;
-
/*
* The chosen accelerator is supposed to register this.
*/
@@ -420,16 +417,10 @@ void qemu_init_cpu_loop(void)
qemu_init_sigbus();
qemu_cond_init(&qemu_cpu_cond);
qemu_cond_init(&qemu_pause_cond);
- qemu_mutex_init(&bql);
qemu_thread_get_self(&io_thread);
}
-void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
-{
- do_run_on_cpu(cpu, func, data, &bql);
-}
-
static void qemu_cpu_stop(CPUState *cpu, bool exit)
{
g_assert(qemu_cpu_is_self(cpu));
@@ -459,7 +450,7 @@ void qemu_wait_io_event(CPUState *cpu)
slept = true;
qemu_plugin_vcpu_idle_cb(cpu);
}
- qemu_cond_wait(cpu->halt_cond, &bql);
+ qemu_cond_wait_bql(cpu->halt_cond);
}
if (slept) {
qemu_plugin_vcpu_resume_cb(cpu);
@@ -512,48 +503,11 @@ bool qemu_in_vcpu_thread(void)
return current_cpu && qemu_cpu_is_self(current_cpu);
}
-QEMU_DEFINE_STATIC_CO_TLS(bool, bql_locked)
-
-bool bql_locked(void)
-{
- return get_bql_locked();
-}
-
bool qemu_in_main_thread(void)
{
return bql_locked();
}
-/*
- * The BQL is taken from so many places that it is worth profiling the
- * callers directly, instead of funneling them all through a single function.
- */
-void bql_lock_impl(const char *file, int line)
-{
- QemuMutexLockFunc bql_lock_fn = qatomic_read(&bql_mutex_lock_func);
-
- g_assert(!bql_locked());
- bql_lock_fn(&bql, file, line);
- set_bql_locked(true);
-}
-
-void bql_unlock(void)
-{
- g_assert(bql_locked());
- set_bql_locked(false);
- qemu_mutex_unlock(&bql);
-}
-
-void qemu_cond_wait_bql(QemuCond *cond)
-{
- qemu_cond_wait(cond, &bql);
-}
-
-void qemu_cond_timedwait_bql(QemuCond *cond, int ms)
-{
- qemu_cond_timedwait(cond, &bql, ms);
-}
-
/* signal CPU creation */
void cpu_thread_signal_created(CPUState *cpu)
{
@@ -613,7 +567,7 @@ void pause_all_vcpus(void)
replay_mutex_unlock();
while (!all_vcpus_paused()) {
- qemu_cond_wait(&qemu_pause_cond, &bql);
+ qemu_cond_wait_bql(&qemu_pause_cond);
CPU_FOREACH(cpu) {
qemu_cpu_kick(cpu);
}
@@ -684,7 +638,7 @@ void qemu_init_vcpu(CPUState *cpu)
cpus_accel->create_vcpu_thread(cpu);
while (!cpu->created) {
- qemu_cond_wait(&qemu_cpu_cond, &bql);
+ qemu_cond_wait_bql(&qemu_cpu_cond);
}
}
Currently BQL is stubbed out in qemu-user. However, enabling the ability to pause and resume CPUs requires BQL, so introduce it. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- accel/tcg/user-exec.c | 2 ++ bsd-user/freebsd/os-syscall.c | 6 ++++ bsd-user/main.c | 2 ++ cpu-common.c | 45 ++++++++++++++++++++++++++++++ gdbstub/user.c | 5 ++++ linux-user/main.c | 3 ++ linux-user/syscall.c | 6 ++++ system/cpus.c | 52 ++--------------------------------- 8 files changed, 72 insertions(+), 49 deletions(-)