The goal of this module is to profile synchronization primitives (i.e. mutexes, recursive mutexes and condition variables) so that scalability issues can be quickly diagnosed. Sync primitives are profiled by QSP based on the vaddr of the object accessed as well as the call site (file:line_nr). That means the same object called from two different call sites will be tracked in separate entries, which might be reported together or separately (see subsequent commit on call site coalescing). Some perf numbers: Host: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz Command: taskset -c 0 tests/atomic_add-bench -d 5 -m - Before: 54.80 Mops/s - After: 54.75 Mops/s That is, a negligible slowdown due to the now indirect call to qemu_mutex_lock. Note that using a branch instead of an indirect call introduces a more severe slowdown (53.65 Mops/s, i.e. 2% slowdown). Enabling the profiler (with -p, added in this series) is more interesting: - No profiling: 54.75 Mops/s - W/ profiling: 12.53 Mops/s That is, a 4.36X slowdown. We can break down this slowdown by removing the get_clock calls or the entry lookup: - No profiling: 54.75 Mops/s - W/o get_clock: 25.37 Mops/s - W/o entry lookup: 19.30 Mops/s - W/ profiling: 12.53 Mops/s Signed-off-by: Emilio G. Cota <cota@braap.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
53 lines
1 KiB
C
53 lines
1 KiB
C
#ifndef QEMU_THREAD_WIN32_H
|
|
#define QEMU_THREAD_WIN32_H
|
|
|
|
#include <windows.h>
|
|
|
|
struct QemuMutex {
|
|
SRWLOCK lock;
|
|
#ifdef CONFIG_DEBUG_MUTEX
|
|
const char *file;
|
|
int line;
|
|
#endif
|
|
bool initialized;
|
|
};
|
|
|
|
typedef struct QemuRecMutex QemuRecMutex;
|
|
struct QemuRecMutex {
|
|
CRITICAL_SECTION lock;
|
|
bool initialized;
|
|
};
|
|
|
|
void qemu_rec_mutex_destroy(QemuRecMutex *mutex);
|
|
void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line);
|
|
int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file,
|
|
int line);
|
|
void qemu_rec_mutex_unlock(QemuRecMutex *mutex);
|
|
|
|
struct QemuCond {
|
|
CONDITION_VARIABLE var;
|
|
bool initialized;
|
|
};
|
|
|
|
struct QemuSemaphore {
|
|
HANDLE sema;
|
|
bool initialized;
|
|
};
|
|
|
|
struct QemuEvent {
|
|
int value;
|
|
HANDLE event;
|
|
bool initialized;
|
|
};
|
|
|
|
typedef struct QemuThreadData QemuThreadData;
|
|
struct QemuThread {
|
|
QemuThreadData *data;
|
|
unsigned tid;
|
|
};
|
|
|
|
/* Only valid for joinable threads. */
|
|
HANDLE qemu_thread_get_handle(QemuThread *thread);
|
|
|
|
#endif
|