qsp: track BQL callers explicitly

The BQL is acquired via qemu_mutex_lock_iothread(), which makes
the profiler assign the associated wait time (i.e. most of
BQL wait time) entirely to that function. This loses the original
call site information, which does not help diagnose BQL contention.
Fix it by tracking the callers explicitly.

Signed-off-by: Emilio G. Cota <cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Emilio G. Cota 2017-10-28 02:16:41 -04:00 committed by Paolo Bonzini
parent d557de4a0e
commit cb764d0665
5 changed files with 19 additions and 4 deletions

10
cpus.c
View File

@ -1762,10 +1762,16 @@ bool qemu_mutex_iothread_locked(void)
return iothread_locked;
}
void qemu_mutex_lock_iothread(void)
/*
* 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 qemu_mutex_lock_iothread_impl(const char *file, int line)
{
QemuMutexLockFunc bql_lock = atomic_read(&qemu_bql_mutex_lock_func);
g_assert(!qemu_mutex_iothread_locked());
qemu_mutex_lock(&qemu_global_mutex);
bql_lock(&qemu_global_mutex, file, line);
iothread_locked = true;
}

View File

@ -276,7 +276,9 @@ bool qemu_mutex_iothread_locked(void);
* NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread
* is a no-op there.
*/
void qemu_mutex_lock_iothread(void);
#define qemu_mutex_lock_iothread() \
qemu_mutex_lock_iothread_impl(__FILE__, __LINE__)
void qemu_mutex_lock_iothread_impl(const char *file, int line);
/**
* qemu_mutex_unlock_iothread: Unlock the main loop mutex.

View File

@ -35,6 +35,7 @@ typedef int (*QemuRecMutexTrylockFunc)(QemuRecMutex *m, const char *f, int l);
typedef void (*QemuCondWaitFunc)(QemuCond *c, QemuMutex *m, const char *f,
int l);
extern QemuMutexLockFunc qemu_bql_mutex_lock_func;
extern QemuMutexLockFunc qemu_mutex_lock_func;
extern QemuMutexTrylockFunc qemu_mutex_trylock_func;
extern QemuRecMutexLockFunc qemu_rec_mutex_lock_func;

View File

@ -7,7 +7,7 @@ bool qemu_mutex_iothread_locked(void)
return true;
}
void qemu_mutex_lock_iothread(void)
void qemu_mutex_lock_iothread_impl(const char *file, int line)
{
}

View File

@ -65,6 +65,7 @@
enum QSPType {
QSP_MUTEX,
QSP_BQL_MUTEX,
QSP_REC_MUTEX,
QSP_CONDVAR,
};
@ -123,10 +124,12 @@ static bool qsp_initialized, qsp_initializing;
static const char * const qsp_typenames[] = {
[QSP_MUTEX] = "mutex",
[QSP_BQL_MUTEX] = "BQL mutex",
[QSP_REC_MUTEX] = "rec_mutex",
[QSP_CONDVAR] = "condvar",
};
QemuMutexLockFunc qemu_bql_mutex_lock_func = qemu_mutex_lock_impl;
QemuMutexLockFunc qemu_mutex_lock_func = qemu_mutex_lock_impl;
QemuMutexTrylockFunc qemu_mutex_trylock_func = qemu_mutex_trylock_impl;
QemuRecMutexLockFunc qemu_rec_mutex_lock_func = qemu_rec_mutex_lock_impl;
@ -419,6 +422,7 @@ static inline void qsp_entry_record(QSPEntry *e, int64_t delta)
return err; \
}
QSP_GEN_VOID(QemuMutex, QSP_BQL_MUTEX, qsp_bql_mutex_lock, qemu_mutex_lock_impl)
QSP_GEN_VOID(QemuMutex, QSP_MUTEX, qsp_mutex_lock, qemu_mutex_lock_impl)
QSP_GEN_RET1(QemuMutex, QSP_MUTEX, qsp_mutex_trylock, qemu_mutex_trylock_impl)
@ -453,6 +457,7 @@ void qsp_enable(void)
{
atomic_set(&qemu_mutex_lock_func, qsp_mutex_lock);
atomic_set(&qemu_mutex_trylock_func, qsp_mutex_trylock);
atomic_set(&qemu_bql_mutex_lock_func, qsp_bql_mutex_lock);
atomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock);
atomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock);
atomic_set(&qemu_cond_wait_func, qsp_cond_wait);
@ -462,6 +467,7 @@ void qsp_disable(void)
{
atomic_set(&qemu_mutex_lock_func, qemu_mutex_lock_impl);
atomic_set(&qemu_mutex_trylock_func, qemu_mutex_trylock_impl);
atomic_set(&qemu_bql_mutex_lock_func, qemu_mutex_lock_impl);
atomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl);
atomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl);
atomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl);