 80818e9ecb
			
		
	
	
		80818e9ecb
		
	
	
	
	
		
			
			Current GCC has an optimization bug when compiling with ASAN. See also GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84307 Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20180215212552.26997-3-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Polymorphic locking functions (aka poor man templates)
 | |
|  *
 | |
|  * Copyright Red Hat, Inc. 2017, 2018
 | |
|  *
 | |
|  * Author: Paolo Bonzini <pbonzini@redhat.com>
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 | |
|  * See the COPYING.LIB file in the top-level directory.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef QEMU_LOCKABLE_H
 | |
| #define QEMU_LOCKABLE_H
 | |
| 
 | |
| #include "qemu/coroutine.h"
 | |
| #include "qemu/thread.h"
 | |
| 
 | |
| typedef void QemuLockUnlockFunc(void *);
 | |
| 
 | |
| struct QemuLockable {
 | |
|     void *object;
 | |
|     QemuLockUnlockFunc *lock;
 | |
|     QemuLockUnlockFunc *unlock;
 | |
| };
 | |
| 
 | |
| /* This function gives an error if an invalid, non-NULL pointer type is passed
 | |
|  * to QEMU_MAKE_LOCKABLE.  For optimized builds, we can rely on dead-code elimination
 | |
|  * from the compiler, and give the errors already at link time.
 | |
|  */
 | |
| #if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
 | |
| void unknown_lock_type(void *);
 | |
| #else
 | |
| static inline void unknown_lock_type(void *unused)
 | |
| {
 | |
|     abort();
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static inline __attribute__((__always_inline__)) QemuLockable *
 | |
| qemu_make_lockable(void *x, QemuLockable *lockable)
 | |
| {
 | |
|     /* We cannot test this in a macro, otherwise we get compiler
 | |
|      * warnings like "the address of 'm' will always evaluate as 'true'".
 | |
|      */
 | |
|     return x ? lockable : NULL;
 | |
| }
 | |
| 
 | |
| /* Auxiliary macros to simplify QEMU_MAKE_LOCABLE.  */
 | |
| #define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *)    \
 | |
|     QEMU_GENERIC(x,                                  \
 | |
|                  (QemuMutex *, qemu_mutex_lock),     \
 | |
|                  (CoMutex *, qemu_co_mutex_lock),    \
 | |
|                  (QemuSpin *, qemu_spin_lock),       \
 | |
|                  unknown_lock_type))
 | |
| 
 | |
| #define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *)  \
 | |
|     QEMU_GENERIC(x,                                  \
 | |
|                  (QemuMutex *, qemu_mutex_unlock),   \
 | |
|                  (CoMutex *, qemu_co_mutex_unlock),  \
 | |
|                  (QemuSpin *, qemu_spin_unlock),     \
 | |
|                  unknown_lock_type))
 | |
| 
 | |
| /* In C, compound literals have the lifetime of an automatic variable.
 | |
|  * In C++ it would be different, but then C++ wouldn't need QemuLockable
 | |
|  * either...
 | |
|  */
 | |
| #define QEMU_MAKE_LOCKABLE_(x) qemu_make_lockable((x), &(QemuLockable) {    \
 | |
|         .object = (x),                               \
 | |
|         .lock = QEMU_LOCK_FUNC(x),                   \
 | |
|         .unlock = QEMU_UNLOCK_FUNC(x),               \
 | |
|     })
 | |
| 
 | |
| /* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable
 | |
|  *
 | |
|  * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin).
 | |
|  *
 | |
|  * Returns a QemuLockable object that can be passed around
 | |
|  * to a function that can operate with locks of any kind.
 | |
|  */
 | |
| #define QEMU_MAKE_LOCKABLE(x)                        \
 | |
|     QEMU_GENERIC(x,                                  \
 | |
|                  (QemuLockable *, (x)),              \
 | |
|                  QEMU_MAKE_LOCKABLE_(x))
 | |
| 
 | |
| static inline void qemu_lockable_lock(QemuLockable *x)
 | |
| {
 | |
|     x->lock(x->object);
 | |
| }
 | |
| 
 | |
| static inline void qemu_lockable_unlock(QemuLockable *x)
 | |
| {
 | |
|     x->unlock(x->object);
 | |
| }
 | |
| 
 | |
| #endif
 |