~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to util/qemu-thread-win32.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * See the COPYING file in the top-level directory.
11
11
 *
12
12
 */
 
13
 
 
14
#ifndef _WIN32_WINNT
 
15
#define _WIN32_WINNT 0x0600
 
16
#endif
 
17
 
13
18
#include "qemu/osdep.h"
14
19
#include "qemu-common.h"
15
20
#include "qemu/thread.h"
39
44
 
40
45
void qemu_mutex_init(QemuMutex *mutex)
41
46
{
42
 
    mutex->owner = 0;
43
 
    InitializeCriticalSection(&mutex->lock);
 
47
    InitializeSRWLock(&mutex->lock);
44
48
}
45
49
 
46
50
void qemu_mutex_destroy(QemuMutex *mutex)
47
51
{
48
 
    assert(mutex->owner == 0);
49
 
    DeleteCriticalSection(&mutex->lock);
 
52
    InitializeSRWLock(&mutex->lock);
50
53
}
51
54
 
52
55
void qemu_mutex_lock(QemuMutex *mutex)
53
56
{
54
 
    EnterCriticalSection(&mutex->lock);
55
 
 
56
 
    /* Win32 CRITICAL_SECTIONs are recursive.  Assert that we're not
57
 
     * using them as such.
58
 
     */
59
 
    assert(mutex->owner == 0);
60
 
    mutex->owner = GetCurrentThreadId();
 
57
    AcquireSRWLockExclusive(&mutex->lock);
61
58
}
62
59
 
63
60
int qemu_mutex_trylock(QemuMutex *mutex)
64
61
{
65
62
    int owned;
66
63
 
67
 
    owned = TryEnterCriticalSection(&mutex->lock);
68
 
    if (owned) {
69
 
        assert(mutex->owner == 0);
70
 
        mutex->owner = GetCurrentThreadId();
71
 
    }
 
64
    owned = TryAcquireSRWLockExclusive(&mutex->lock);
72
65
    return !owned;
73
66
}
74
67
 
75
68
void qemu_mutex_unlock(QemuMutex *mutex)
76
69
{
77
 
    assert(mutex->owner == GetCurrentThreadId());
78
 
    mutex->owner = 0;
79
 
    LeaveCriticalSection(&mutex->lock);
 
70
    ReleaseSRWLockExclusive(&mutex->lock);
80
71
}
81
72
 
82
73
void qemu_rec_mutex_init(QemuRecMutex *mutex)
107
98
void qemu_cond_init(QemuCond *cond)
108
99
{
109
100
    memset(cond, 0, sizeof(*cond));
110
 
 
111
 
    cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
112
 
    if (!cond->sema) {
113
 
        error_exit(GetLastError(), __func__);
114
 
    }
115
 
    cond->continue_event = CreateEvent(NULL,    /* security */
116
 
                                       FALSE,   /* auto-reset */
117
 
                                       FALSE,   /* not signaled */
118
 
                                       NULL);   /* name */
119
 
    if (!cond->continue_event) {
120
 
        error_exit(GetLastError(), __func__);
121
 
    }
 
101
    InitializeConditionVariable(&cond->var);
122
102
}
123
103
 
124
104
void qemu_cond_destroy(QemuCond *cond)
125
105
{
126
 
    BOOL result;
127
 
    result = CloseHandle(cond->continue_event);
128
 
    if (!result) {
129
 
        error_exit(GetLastError(), __func__);
130
 
    }
131
 
    cond->continue_event = 0;
132
 
    result = CloseHandle(cond->sema);
133
 
    if (!result) {
134
 
        error_exit(GetLastError(), __func__);
135
 
    }
136
 
    cond->sema = 0;
 
106
    InitializeConditionVariable(&cond->var);
137
107
}
138
108
 
139
109
void qemu_cond_signal(QemuCond *cond)
140
110
{
141
 
    DWORD result;
142
 
 
143
 
    /*
144
 
     * Signal only when there are waiters.  cond->waiters is
145
 
     * incremented by pthread_cond_wait under the external lock,
146
 
     * so we are safe about that.
147
 
     */
148
 
    if (cond->waiters == 0) {
149
 
        return;
150
 
    }
151
 
 
152
 
    /*
153
 
     * Waiting threads decrement it outside the external lock, but
154
 
     * only if another thread is executing pthread_cond_broadcast and
155
 
     * has the mutex.  So, it also cannot be decremented concurrently
156
 
     * with this particular access.
157
 
     */
158
 
    cond->target = cond->waiters - 1;
159
 
    result = SignalObjectAndWait(cond->sema, cond->continue_event,
160
 
                                 INFINITE, FALSE);
161
 
    if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
162
 
        error_exit(GetLastError(), __func__);
163
 
    }
 
111
    WakeConditionVariable(&cond->var);
164
112
}
165
113
 
166
114
void qemu_cond_broadcast(QemuCond *cond)
167
115
{
168
 
    BOOLEAN result;
169
 
    /*
170
 
     * As in pthread_cond_signal, access to cond->waiters and
171
 
     * cond->target is locked via the external mutex.
172
 
     */
173
 
    if (cond->waiters == 0) {
174
 
        return;
175
 
    }
176
 
 
177
 
    cond->target = 0;
178
 
    result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
179
 
    if (!result) {
180
 
        error_exit(GetLastError(), __func__);
181
 
    }
182
 
 
183
 
    /*
184
 
     * At this point all waiters continue. Each one takes its
185
 
     * slice of the semaphore. Now it's our turn to wait: Since
186
 
     * the external mutex is held, no thread can leave cond_wait,
187
 
     * yet. For this reason, we can be sure that no thread gets
188
 
     * a chance to eat *more* than one slice. OTOH, it means
189
 
     * that the last waiter must send us a wake-up.
190
 
     */
191
 
    WaitForSingleObject(cond->continue_event, INFINITE);
 
116
    WakeAllConditionVariable(&cond->var);
192
117
}
193
118
 
194
119
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
195
120
{
196
 
    /*
197
 
     * This access is protected under the mutex.
198
 
     */
199
 
    cond->waiters++;
200
 
 
201
 
    /*
202
 
     * Unlock external mutex and wait for signal.
203
 
     * NOTE: we've held mutex locked long enough to increment
204
 
     * waiters count above, so there's no problem with
205
 
     * leaving mutex unlocked before we wait on semaphore.
206
 
     */
207
 
    qemu_mutex_unlock(mutex);
208
 
    WaitForSingleObject(cond->sema, INFINITE);
209
 
 
210
 
    /* Now waiters must rendez-vous with the signaling thread and
211
 
     * let it continue.  For cond_broadcast this has heavy contention
212
 
     * and triggers thundering herd.  So goes life.
213
 
     *
214
 
     * Decrease waiters count.  The mutex is not taken, so we have
215
 
     * to do this atomically.
216
 
     *
217
 
     * All waiters contend for the mutex at the end of this function
218
 
     * until the signaling thread relinquishes it.  To ensure
219
 
     * each waiter consumes exactly one slice of the semaphore,
220
 
     * the signaling thread stops until it is told by the last
221
 
     * waiter that it can go on.
222
 
     */
223
 
    if (InterlockedDecrement(&cond->waiters) == cond->target) {
224
 
        SetEvent(cond->continue_event);
225
 
    }
226
 
 
227
 
    qemu_mutex_lock(mutex);
 
121
    SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0);
228
122
}
229
123
 
230
124
void qemu_sem_init(QemuSemaphore *sem, int init)
269
163
 *
270
164
 * Valid transitions:
271
165
 * - free->set, when setting the event
272
 
 * - busy->set, when setting the event, followed by futex_wake
 
166
 * - busy->set, when setting the event, followed by SetEvent
273
167
 * - set->free, when resetting the event
274
168
 * - free->busy, when waiting
275
169
 *
497
391
 
498
392
    EnterCriticalSection(&data->cs);
499
393
    if (!data->exited) {
500
 
        handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
501
 
                            thread->tid);
 
394
        handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME |
 
395
                            THREAD_SET_CONTEXT, FALSE, thread->tid);
502
396
    } else {
503
397
        handle = NULL;
504
398
    }