Merge tag 'v2.8.0-rc4' into develop
[sdk/emulator/qemu.git] / util / qemu-thread-posix.c
index 0a1b87c..4c09902 100644 (file)
@@ -80,6 +80,20 @@ void qemu_mutex_unlock(QemuMutex *mutex)
         error_exit(err, __func__);
 }
 
+void qemu_rec_mutex_init(QemuRecMutex *mutex)
+{
+    int err;
+    pthread_mutexattr_t attr;
+
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    err = pthread_mutex_init(&mutex->lock, &attr);
+    pthread_mutexattr_destroy(&attr);
+    if (err) {
+        error_exit(err, __func__);
+    }
+}
+
 void qemu_cond_init(QemuCond *cond)
 {
     int err;
@@ -360,7 +374,11 @@ void qemu_event_destroy(QemuEvent *ev)
 
 void qemu_event_set(QemuEvent *ev)
 {
-    if (atomic_mb_read(&ev->value) != EV_SET) {
+    /* qemu_event_set has release semantics, but because it *loads*
+     * ev->value we need a full memory barrier here.
+     */
+    smp_mb();
+    if (atomic_read(&ev->value) != EV_SET) {
         if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
             /* There were waiters, wake them up.  */
             futex_wake(ev, INT_MAX);
@@ -370,7 +388,11 @@ void qemu_event_set(QemuEvent *ev)
 
 void qemu_event_reset(QemuEvent *ev)
 {
-    if (atomic_mb_read(&ev->value) == EV_SET) {
+    unsigned value;
+
+    value = atomic_read(&ev->value);
+    smp_mb_acquire();
+    if (value == EV_SET) {
         /*
          * If there was a concurrent reset (or even reset+wait),
          * do nothing.  Otherwise change EV_SET->EV_FREE.
@@ -383,7 +405,8 @@ void qemu_event_wait(QemuEvent *ev)
 {
     unsigned value;
 
-    value = atomic_mb_read(&ev->value);
+    value = atomic_read(&ev->value);
+    smp_mb_acquire();
     if (value != EV_SET) {
         if (value == EV_FREE) {
             /*