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 #define QEMU_THREAD_JOINABLE 0 20 #define QEMU_THREAD_DETACHED 1 21 22 void qemu_mutex_init(QemuMutex *mutex); 23 void qemu_mutex_destroy(QemuMutex *mutex); 24 int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line); 25 void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line); 26 void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line); 27 28 #define qemu_mutex_lock(mutex) \ 29 qemu_mutex_lock_impl(mutex, __FILE__, __LINE__) 30 #define qemu_mutex_trylock(mutex) \ 31 qemu_mutex_trylock_impl(mutex, __FILE__, __LINE__) 32 #define qemu_mutex_unlock(mutex) \ 33 qemu_mutex_unlock_impl(mutex, __FILE__, __LINE__) 34 35 static inline void (qemu_mutex_lock)(QemuMutex *mutex) 36 { 37 qemu_mutex_lock(mutex); 38 } 39 40 static inline int (qemu_mutex_trylock)(QemuMutex *mutex) 41 { 42 return qemu_mutex_trylock(mutex); 43 } 44 45 static inline void (qemu_mutex_unlock)(QemuMutex *mutex) 46 { 47 qemu_mutex_unlock(mutex); 48 } 49 50 /* Prototypes for other functions are in thread-posix.h/thread-win32.h. */ 51 void qemu_rec_mutex_init(QemuRecMutex *mutex); 52 53 void qemu_cond_init(QemuCond *cond); 54 void qemu_cond_destroy(QemuCond *cond); 55 56 /* 57 * IMPORTANT: The implementation does not guarantee that pthread_cond_signal 58 * and pthread_cond_broadcast can be called except while the same mutex is 59 * held as in the corresponding pthread_cond_wait calls! 60 */ 61 void qemu_cond_signal(QemuCond *cond); 62 void qemu_cond_broadcast(QemuCond *cond); 63 void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, 64 const char *file, const int line); 65 66 #define qemu_cond_wait(cond, mutex) \ 67 qemu_cond_wait_impl(cond, mutex, __FILE__, __LINE__) 68 69 static inline void (qemu_cond_wait)(QemuCond *cond, QemuMutex *mutex) 70 { 71 qemu_cond_wait(cond, mutex); 72 } 73 74 void qemu_sem_init(QemuSemaphore *sem, int init); 75 void qemu_sem_post(QemuSemaphore *sem); 76 void qemu_sem_wait(QemuSemaphore *sem); 77 int qemu_sem_timedwait(QemuSemaphore *sem, int ms); 78 void qemu_sem_destroy(QemuSemaphore *sem); 79 80 void qemu_event_init(QemuEvent *ev, bool init); 81 void qemu_event_set(QemuEvent *ev); 82 void qemu_event_reset(QemuEvent *ev); 83 void qemu_event_wait(QemuEvent *ev); 84 void qemu_event_destroy(QemuEvent *ev); 85 86 void qemu_thread_create(QemuThread *thread, const char *name, 87 void *(*start_routine)(void *), 88 void *arg, int mode); 89 void *qemu_thread_join(QemuThread *thread); 90 void qemu_thread_get_self(QemuThread *thread); 91 bool qemu_thread_is_self(QemuThread *thread); 92 void qemu_thread_exit(void *retval); 93 void qemu_thread_naming(bool enable); 94 95 struct Notifier; 96 void qemu_thread_atexit_add(struct Notifier *notifier); 97 void qemu_thread_atexit_remove(struct Notifier *notifier); 98 99 struct QemuSpin { 100 int value; 101 }; 102 103 static inline void qemu_spin_init(QemuSpin *spin) 104 { 105 __sync_lock_release(&spin->value); 106 } 107 108 static inline void qemu_spin_lock(QemuSpin *spin) 109 { 110 while (unlikely(__sync_lock_test_and_set(&spin->value, true))) { 111 while (atomic_read(&spin->value)) { 112 cpu_relax(); 113 } 114 } 115 } 116 117 static inline bool qemu_spin_trylock(QemuSpin *spin) 118 { 119 return __sync_lock_test_and_set(&spin->value, true); 120 } 121 122 static inline bool qemu_spin_locked(QemuSpin *spin) 123 { 124 return atomic_read(&spin->value); 125 } 126 127 static inline void qemu_spin_unlock(QemuSpin *spin) 128 { 129 __sync_lock_release(&spin->value); 130 } 131 132 struct QemuLockCnt { 133 #ifndef CONFIG_LINUX 134 QemuMutex mutex; 135 #endif 136 unsigned count; 137 }; 138 139 /** 140 * qemu_lockcnt_init: initialize a QemuLockcnt 141 * @lockcnt: the lockcnt to initialize 142 * 143 * Initialize lockcnt's counter to zero and prepare its mutex 144 * for usage. 145 */ 146 void qemu_lockcnt_init(QemuLockCnt *lockcnt); 147 148 /** 149 * qemu_lockcnt_destroy: destroy a QemuLockcnt 150 * @lockcnt: the lockcnt to destruct 151 * 152 * Destroy lockcnt's mutex. 153 */ 154 void qemu_lockcnt_destroy(QemuLockCnt *lockcnt); 155 156 /** 157 * qemu_lockcnt_inc: increment a QemuLockCnt's counter 158 * @lockcnt: the lockcnt to operate on 159 * 160 * If the lockcnt's count is zero, wait for critical sections 161 * to finish and increment lockcnt's count to 1. If the count 162 * is not zero, just increment it. 163 * 164 * Because this function can wait on the mutex, it must not be 165 * called while the lockcnt's mutex is held by the current thread. 166 * For the same reason, qemu_lockcnt_inc can also contribute to 167 * AB-BA deadlocks. This is a sample deadlock scenario: 168 * 169 * thread 1 thread 2 170 * ------------------------------------------------------- 171 * qemu_lockcnt_lock(&lc1); 172 * qemu_lockcnt_lock(&lc2); 173 * qemu_lockcnt_inc(&lc2); 174 * qemu_lockcnt_inc(&lc1); 175 */ 176 void qemu_lockcnt_inc(QemuLockCnt *lockcnt); 177 178 /** 179 * qemu_lockcnt_dec: decrement a QemuLockCnt's counter 180 * @lockcnt: the lockcnt to operate on 181 */ 182 void qemu_lockcnt_dec(QemuLockCnt *lockcnt); 183 184 /** 185 * qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and 186 * possibly lock it. 187 * @lockcnt: the lockcnt to operate on 188 * 189 * Decrement lockcnt's count. If the new count is zero, lock 190 * the mutex and return true. Otherwise, return false. 191 */ 192 bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt); 193 194 /** 195 * qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and 196 * lock it. 197 * @lockcnt: the lockcnt to operate on 198 * 199 * If the count is 1, decrement the count to zero, lock 200 * the mutex and return true. Otherwise, return false. 201 */ 202 bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt); 203 204 /** 205 * qemu_lockcnt_lock: lock a QemuLockCnt's mutex. 206 * @lockcnt: the lockcnt to operate on 207 * 208 * Remember that concurrent visits are not blocked unless the count is 209 * also zero. You can use qemu_lockcnt_count to check for this inside a 210 * critical section. 211 */ 212 void qemu_lockcnt_lock(QemuLockCnt *lockcnt); 213 214 /** 215 * qemu_lockcnt_unlock: release a QemuLockCnt's mutex. 216 * @lockcnt: the lockcnt to operate on. 217 */ 218 void qemu_lockcnt_unlock(QemuLockCnt *lockcnt); 219 220 /** 221 * qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt. 222 * @lockcnt: the lockcnt to operate on. 223 * 224 * This is the same as 225 * 226 * qemu_lockcnt_unlock(lockcnt); 227 * qemu_lockcnt_inc(lockcnt); 228 * 229 * but more efficient. 230 */ 231 void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt); 232 233 /** 234 * qemu_lockcnt_count: query a LockCnt's count. 235 * @lockcnt: the lockcnt to query. 236 * 237 * Note that the count can change at any time. Still, while the 238 * lockcnt is locked, one can usefully check whether the count 239 * is non-zero. 240 */ 241 unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt); 242 243 #endif 244