cleanup more synchronization code
This commit is contained in:
@ -60,93 +60,6 @@ void qemu_mutex_unlock(QemuMutex *mutex)
|
||||
LeaveCriticalSection(&mutex->lock);
|
||||
}
|
||||
|
||||
void qemu_cond_init(QemuCond *cond)
|
||||
{
|
||||
memset(cond, 0, sizeof(*cond));
|
||||
|
||||
cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
|
||||
if (!cond->sema) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
cond->continue_event = CreateEvent(NULL, /* security */
|
||||
FALSE, /* auto-reset */
|
||||
FALSE, /* not signaled */
|
||||
NULL); /* name */
|
||||
if (!cond->continue_event) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_cond_destroy(QemuCond *cond)
|
||||
{
|
||||
BOOL result;
|
||||
result = CloseHandle(cond->continue_event);
|
||||
if (!result) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
cond->continue_event = 0;
|
||||
result = CloseHandle(cond->sema);
|
||||
if (!result) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
cond->sema = 0;
|
||||
}
|
||||
|
||||
void qemu_cond_signal(QemuCond *cond)
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
/*
|
||||
* Signal only when there are waiters. cond->waiters is
|
||||
* incremented by pthread_cond_wait under the external lock,
|
||||
* so we are safe about that.
|
||||
*/
|
||||
if (cond->waiters == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Waiting threads decrement it outside the external lock, but
|
||||
* only if another thread is executing pthread_cond_broadcast and
|
||||
* has the mutex. So, it also cannot be decremented concurrently
|
||||
* with this particular access.
|
||||
*/
|
||||
cond->target = cond->waiters - 1;
|
||||
result = SignalObjectAndWait(cond->sema, cond->continue_event,
|
||||
INFINITE, FALSE);
|
||||
if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_cond_broadcast(QemuCond *cond)
|
||||
{
|
||||
BOOLEAN result;
|
||||
/*
|
||||
* As in pthread_cond_signal, access to cond->waiters and
|
||||
* cond->target is locked via the external mutex.
|
||||
*/
|
||||
if (cond->waiters == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cond->target = 0;
|
||||
result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
|
||||
if (!result) {
|
||||
error_exit(GetLastError(), __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point all waiters continue. Each one takes its
|
||||
* slice of the semaphore. Now it's our turn to wait: Since
|
||||
* the external mutex is held, no thread can leave cond_wait,
|
||||
* yet. For this reason, we can be sure that no thread gets
|
||||
* a chance to eat *more* than one slice. OTOH, it means
|
||||
* that the last waiter must send us a wake-up.
|
||||
*/
|
||||
WaitForSingleObject(cond->continue_event, INFINITE);
|
||||
}
|
||||
|
||||
struct QemuThreadData {
|
||||
/* Passed to win32_start_routine. */
|
||||
void *(*start_routine)(void *);
|
||||
|
Reference in New Issue
Block a user