Message ID | 20200529132341.755-8-robert.foley@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add Thread Sanitizer support to QEMU | expand |
Robert Foley <robert.foley@linaro.org> writes: > From: "Emilio G. Cota" <cota@braap.org> > > Signed-off-by: Emilio G. Cota <cota@braap.org> > Signed-off-by: Robert Foley <robert.foley@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> > --- > include/qemu/thread.h | 39 ++++++++++++++++++++++++++++++++++++--- > 1 file changed, 36 insertions(+), 3 deletions(-) > > diff --git a/include/qemu/thread.h b/include/qemu/thread.h > index e50a073889..43fc094b96 100644 > --- a/include/qemu/thread.h > +++ b/include/qemu/thread.h > @@ -206,6 +206,10 @@ void qemu_thread_atexit_add(struct Notifier *notifier); > */ > void qemu_thread_atexit_remove(struct Notifier *notifier); > > +#ifdef CONFIG_TSAN > +#include <sanitizer/tsan_interface.h> > +#endif > + > struct QemuSpin { > int value; > }; > @@ -213,23 +217,46 @@ struct QemuSpin { > static inline void qemu_spin_init(QemuSpin *spin) > { > __sync_lock_release(&spin->value); > +#ifdef CONFIG_TSAN > + __tsan_mutex_create(spin, __tsan_mutex_not_static); > +#endif > } > > -static inline void qemu_spin_destroy(QemuSpin *spin) > -{ } > +/* const parameter because the only purpose here is the TSAN annotation */ > +static inline void qemu_spin_destroy(const QemuSpin *spin) > +{ > +#ifdef CONFIG_TSAN > + __tsan_mutex_destroy((void *)spin, __tsan_mutex_not_static); > +#endif > +} > > static inline void qemu_spin_lock(QemuSpin *spin) > { > +#ifdef CONFIG_TSAN > + __tsan_mutex_pre_lock(spin, 0); > +#endif > while (unlikely(__sync_lock_test_and_set(&spin->value, true))) { > while (atomic_read(&spin->value)) { > cpu_relax(); > } > } > +#ifdef CONFIG_TSAN > + __tsan_mutex_post_lock(spin, 0, 0); > +#endif > } > > static inline bool qemu_spin_trylock(QemuSpin *spin) > { > - return __sync_lock_test_and_set(&spin->value, true); > +#ifdef CONFIG_TSAN > + __tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock); > +#endif > + bool busy = __sync_lock_test_and_set(&spin->value, true); > +#ifdef CONFIG_TSAN > + unsigned flags = __tsan_mutex_try_lock; > + flags |= busy ? __tsan_mutex_try_lock_failed : 0; > + __tsan_mutex_post_lock(spin, flags, 0); > +#endif > + return busy; > } > > static inline bool qemu_spin_locked(QemuSpin *spin) > @@ -239,7 +266,13 @@ static inline bool qemu_spin_locked(QemuSpin *spin) > > static inline void qemu_spin_unlock(QemuSpin *spin) > { > +#ifdef CONFIG_TSAN > + __tsan_mutex_pre_unlock(spin, 0); > +#endif > __sync_lock_release(&spin->value); > +#ifdef CONFIG_TSAN > + __tsan_mutex_post_unlock(spin, 0); > +#endif > } > > struct QemuLockCnt {
diff --git a/include/qemu/thread.h b/include/qemu/thread.h index e50a073889..43fc094b96 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -206,6 +206,10 @@ void qemu_thread_atexit_add(struct Notifier *notifier); */ void qemu_thread_atexit_remove(struct Notifier *notifier); +#ifdef CONFIG_TSAN +#include <sanitizer/tsan_interface.h> +#endif + struct QemuSpin { int value; }; @@ -213,23 +217,46 @@ struct QemuSpin { static inline void qemu_spin_init(QemuSpin *spin) { __sync_lock_release(&spin->value); +#ifdef CONFIG_TSAN + __tsan_mutex_create(spin, __tsan_mutex_not_static); +#endif } -static inline void qemu_spin_destroy(QemuSpin *spin) -{ } +/* const parameter because the only purpose here is the TSAN annotation */ +static inline void qemu_spin_destroy(const QemuSpin *spin) +{ +#ifdef CONFIG_TSAN + __tsan_mutex_destroy((void *)spin, __tsan_mutex_not_static); +#endif +} static inline void qemu_spin_lock(QemuSpin *spin) { +#ifdef CONFIG_TSAN + __tsan_mutex_pre_lock(spin, 0); +#endif while (unlikely(__sync_lock_test_and_set(&spin->value, true))) { while (atomic_read(&spin->value)) { cpu_relax(); } } +#ifdef CONFIG_TSAN + __tsan_mutex_post_lock(spin, 0, 0); +#endif } static inline bool qemu_spin_trylock(QemuSpin *spin) { - return __sync_lock_test_and_set(&spin->value, true); +#ifdef CONFIG_TSAN + __tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock); +#endif + bool busy = __sync_lock_test_and_set(&spin->value, true); +#ifdef CONFIG_TSAN + unsigned flags = __tsan_mutex_try_lock; + flags |= busy ? __tsan_mutex_try_lock_failed : 0; + __tsan_mutex_post_lock(spin, flags, 0); +#endif + return busy; } static inline bool qemu_spin_locked(QemuSpin *spin) @@ -239,7 +266,13 @@ static inline bool qemu_spin_locked(QemuSpin *spin) static inline void qemu_spin_unlock(QemuSpin *spin) { +#ifdef CONFIG_TSAN + __tsan_mutex_pre_unlock(spin, 0); +#endif __sync_lock_release(&spin->value); +#ifdef CONFIG_TSAN + __tsan_mutex_post_unlock(spin, 0); +#endif } struct QemuLockCnt {