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