1 #ifndef QEMU_THREAD_H 2 #define QEMU_THREAD_H 3 4 #include "qemu/processor.h" 5 #include "qemu/atomic.h" 6 7 typedef struct QemuCond QemuCond; 8 typedef struct QemuSemaphore QemuSemaphore; 9 typedef struct QemuEvent QemuEvent; 10 typedef struct QemuLockCnt QemuLockCnt; 11 typedef struct QemuThread QemuThread; 12 13 #ifdef _WIN32 14 #include "qemu/thread-win32.h" 15 #else 16 #include "qemu/thread-posix.h" 17 #endif 18 19 /* include QSP header once QemuMutex, QemuCond etc. are defined */ 20 #include "qemu/qsp.h" 21 22 #define QEMU_THREAD_JOINABLE 0 23 #define QEMU_THREAD_DETACHED 1 24 25 void qemu_mutex_init(QemuMutex *mutex); 26 void qemu_mutex_destroy(QemuMutex *mutex); 27 int TSA_NO_TSA qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, 28 const int line); 29 void TSA_NO_TSA qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, 30 const int line); 31 void TSA_NO_TSA qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, 32 const int line); 33 34 void qemu_rec_mutex_init(QemuRecMutex *mutex); 35 void qemu_rec_mutex_destroy(QemuRecMutex *mutex); 36 void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line); 37 int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line); 38 void qemu_rec_mutex_unlock_impl(QemuRecMutex *mutex, const char *file, int line); 39 40 typedef void (*QemuMutexLockFunc)(QemuMutex *m, const char *f, int l); 41 typedef int (*QemuMutexTrylockFunc)(QemuMutex *m, const char *f, int l); 42 typedef void (*QemuRecMutexLockFunc)(QemuRecMutex *m, const char *f, int l); 43 typedef int (*QemuRecMutexTrylockFunc)(QemuRecMutex *m, const char *f, int l); 44 typedef void (*QemuCondWaitFunc)(QemuCond *c, QemuMutex *m, const char *f, 45 int l); 46 typedef bool (*QemuCondTimedWaitFunc)(QemuCond *c, QemuMutex *m, int ms, 47 const char *f, int l); 48 49 extern QemuMutexLockFunc bql_mutex_lock_func; 50 extern QemuMutexLockFunc qemu_mutex_lock_func; 51 extern QemuMutexTrylockFunc qemu_mutex_trylock_func; 52 extern QemuRecMutexLockFunc qemu_rec_mutex_lock_func; 53 extern QemuRecMutexTrylockFunc qemu_rec_mutex_trylock_func; 54 extern QemuCondWaitFunc qemu_cond_wait_func; 55 extern QemuCondTimedWaitFunc qemu_cond_timedwait_func; 56 57 /* convenience macros to bypass the profiler */ 58 #define qemu_mutex_lock__raw(m) \ 59 qemu_mutex_lock_impl(m, __FILE__, __LINE__) 60 #define qemu_mutex_trylock__raw(m) \ 61 qemu_mutex_trylock_impl(m, __FILE__, __LINE__) 62 63 #ifdef __COVERITY__ 64 /* 65 * Coverity is severely confused by the indirect function calls, 66 * hide them. 67 */ 68 #define qemu_mutex_lock(m) \ 69 qemu_mutex_lock_impl(m, __FILE__, __LINE__) 70 #define qemu_mutex_trylock(m) \ 71 qemu_mutex_trylock_impl(m, __FILE__, __LINE__) 72 #define qemu_rec_mutex_lock(m) \ 73 qemu_rec_mutex_lock_impl(m, __FILE__, __LINE__) 74 #define qemu_rec_mutex_trylock(m) \ 75 qemu_rec_mutex_trylock_impl(m, __FILE__, __LINE__) 76 #define qemu_cond_wait(c, m) \ 77 qemu_cond_wait_impl(c, m, __FILE__, __LINE__) 78 #define qemu_cond_timedwait(c, m, ms) \ 79 qemu_cond_timedwait_impl(c, m, ms, __FILE__, __LINE__) 80 #else 81 #define qemu_mutex_lock(m) ({ \ 82 QemuMutexLockFunc _f = qatomic_read(&qemu_mutex_lock_func); \ 83 _f(m, __FILE__, __LINE__); \ 84 }) 85 86 #define qemu_mutex_trylock(m) ({ \ 87 QemuMutexTrylockFunc _f = qatomic_read(&qemu_mutex_trylock_func); \ 88 _f(m, __FILE__, __LINE__); \ 89 }) 90 91 #define qemu_rec_mutex_lock(m) ({ \ 92 QemuRecMutexLockFunc _f = qatomic_read(&qemu_rec_mutex_lock_func);\ 93 _f(m, __FILE__, __LINE__); \ 94 }) 95 96 #define qemu_rec_mutex_trylock(m) ({ \ 97 QemuRecMutexTrylockFunc _f; \ 98 _f = qatomic_read(&qemu_rec_mutex_trylock_func); \ 99 _f(m, __FILE__, __LINE__); \ 100 }) 101 102 #define qemu_cond_wait(c, m) ({ \ 103 QemuCondWaitFunc _f = qatomic_read(&qemu_cond_wait_func); \ 104 _f(c, m, __FILE__, __LINE__); \ 105 }) 106 107 #define qemu_cond_timedwait(c, m, ms) ({ \ 108 QemuCondTimedWaitFunc _f = qatomic_read(&qemu_cond_timedwait_func);\ 109 _f(c, m, ms, __FILE__, __LINE__); \ 110 }) 111 #endif 112 113 #define qemu_mutex_unlock(mutex) \ 114 qemu_mutex_unlock_impl(mutex, __FILE__, __LINE__) 115 116 #define qemu_rec_mutex_unlock(mutex) \ 117 qemu_rec_mutex_unlock_impl(mutex, __FILE__, __LINE__) 118 119 static inline void (qemu_mutex_lock)(QemuMutex *mutex) 120 { 121 qemu_mutex_lock(mutex); 122 } 123 124 static inline int (qemu_mutex_trylock)(QemuMutex *mutex) 125 { 126 return qemu_mutex_trylock(mutex); 127 } 128 129 static inline void (qemu_mutex_unlock)(QemuMutex *mutex) 130 { 131 qemu_mutex_unlock(mutex); 132 } 133 134 static inline void (qemu_rec_mutex_lock)(QemuRecMutex *mutex) 135 { 136 qemu_rec_mutex_lock(mutex); 137 } 138 139 static inline int (qemu_rec_mutex_trylock)(QemuRecMutex *mutex) 140 { 141 return qemu_rec_mutex_trylock(mutex); 142 } 143 144 static inline void (qemu_rec_mutex_unlock)(QemuRecMutex *mutex) 145 { 146 qemu_rec_mutex_unlock(mutex); 147 } 148 149 void qemu_cond_init(QemuCond *cond); 150 void qemu_cond_destroy(QemuCond *cond); 151 152 /* 153 * IMPORTANT: The implementation does not guarantee that pthread_cond_signal 154 * and pthread_cond_broadcast can be called except while the same mutex is 155 * held as in the corresponding pthread_cond_wait calls! 156 */ 157 void qemu_cond_signal(QemuCond *cond); 158 void qemu_cond_broadcast(QemuCond *cond); 159 void TSA_NO_TSA qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, 160 const char *file, const int line); 161 bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, 162 const char *file, const int line); 163 164 static inline void (qemu_cond_wait)(QemuCond *cond, QemuMutex *mutex) 165 { 166 qemu_cond_wait(cond, mutex); 167 } 168 169 /* Returns true if timeout has not expired, and false otherwise */ 170 static inline bool (qemu_cond_timedwait)(QemuCond *cond, QemuMutex *mutex, 171 int ms) 172 { 173 return qemu_cond_timedwait(cond, mutex, ms); 174 } 175 176 void qemu_sem_init(QemuSemaphore *sem, int init); 177 void qemu_sem_post(QemuSemaphore *sem); 178 void qemu_sem_wait(QemuSemaphore *sem); 179 int qemu_sem_timedwait(QemuSemaphore *sem, int ms); 180 void qemu_sem_destroy(QemuSemaphore *sem); 181 182 void qemu_event_init(QemuEvent *ev, bool init); 183 void qemu_event_set(QemuEvent *ev); 184 void qemu_event_reset(QemuEvent *ev); 185 void qemu_event_wait(QemuEvent *ev); 186 void qemu_event_destroy(QemuEvent *ev); 187 188 void qemu_thread_create(QemuThread *thread, const char *name, 189 void *(*start_routine)(void *), 190 void *arg, int mode); 191 int qemu_thread_set_affinity(QemuThread *thread, unsigned long *host_cpus, 192 unsigned long nbits); 193 int qemu_thread_get_affinity(QemuThread *thread, unsigned long **host_cpus, 194 unsigned long *nbits); 195 void *qemu_thread_join(QemuThread *thread); 196 void qemu_thread_get_self(QemuThread *thread); 197 bool qemu_thread_is_self(QemuThread *thread); 198 G_NORETURN void qemu_thread_exit(void *retval); 199 void qemu_thread_naming(bool enable); 200 201 struct Notifier; 202 /** 203 * qemu_thread_atexit_add: 204 * @notifier: Notifier to add 205 * 206 * Add the specified notifier to a list which will be run via 207 * notifier_list_notify() when this thread exits (either by calling 208 * qemu_thread_exit() or by returning from its start_routine). 209 * The usual usage is that the caller passes a Notifier which is 210 * a per-thread variable; it can then use the callback to free 211 * other per-thread data. 212 * 213 * If the thread exits as part of the entire process exiting, 214 * it is unspecified whether notifiers are called or not. 215 */ 216 void qemu_thread_atexit_add(struct Notifier *notifier); 217 /** 218 * qemu_thread_atexit_remove: 219 * @notifier: Notifier to remove 220 * 221 * Remove the specified notifier from the thread-exit notification 222 * list. It is not valid to try to remove a notifier which is not 223 * on the list. 224 */ 225 void qemu_thread_atexit_remove(struct Notifier *notifier); 226 227 #ifdef CONFIG_TSAN 228 #include <sanitizer/tsan_interface.h> 229 #endif 230 231 struct QemuSpin { 232 int value; 233 }; 234 235 static inline void qemu_spin_init(QemuSpin *spin) 236 { 237 qatomic_set(&spin->value, 0); 238 #ifdef CONFIG_TSAN 239 __tsan_mutex_create(spin, __tsan_mutex_not_static); 240 #endif 241 } 242 243 static inline void qemu_spin_destroy(QemuSpin *spin) 244 { 245 #ifdef CONFIG_TSAN 246 __tsan_mutex_destroy(spin, __tsan_mutex_not_static); 247 #endif 248 } 249 250 static inline void qemu_spin_lock(QemuSpin *spin) 251 { 252 #ifdef CONFIG_TSAN 253 __tsan_mutex_pre_lock(spin, 0); 254 #endif 255 while (unlikely(qatomic_xchg(&spin->value, 1))) { 256 while (qatomic_read(&spin->value)) { 257 cpu_relax(); 258 } 259 } 260 #ifdef CONFIG_TSAN 261 __tsan_mutex_post_lock(spin, 0, 0); 262 #endif 263 } 264 265 static inline bool qemu_spin_trylock(QemuSpin *spin) 266 { 267 #ifdef CONFIG_TSAN 268 __tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock); 269 #endif 270 bool busy = qatomic_xchg(&spin->value, true); 271 #ifdef CONFIG_TSAN 272 unsigned flags = __tsan_mutex_try_lock; 273 flags |= busy ? __tsan_mutex_try_lock_failed : 0; 274 __tsan_mutex_post_lock(spin, flags, 0); 275 #endif 276 return busy; 277 } 278 279 static inline bool qemu_spin_locked(QemuSpin *spin) 280 { 281 return qatomic_read(&spin->value); 282 } 283 284 static inline void qemu_spin_unlock(QemuSpin *spin) 285 { 286 #ifdef CONFIG_TSAN 287 __tsan_mutex_pre_unlock(spin, 0); 288 #endif 289 qatomic_store_release(&spin->value, 0); 290 #ifdef CONFIG_TSAN 291 __tsan_mutex_post_unlock(spin, 0); 292 #endif 293 } 294 295 #endif 296