From: Paolo Bonzini <pbonzini@redhat.com>
To: Blue Swirl <blauwirbel@gmail.com>
Cc: jan.kiszka@siemens.com, qemu-devel@nongnu.org, aurelien@aurel32.net
Subject: [Qemu-devel] Re: [PATCH v2 upstream 05/22] add win32 qemu-thread implementation
Date: Sat, 26 Feb 2011 18:42:50 +0100 [thread overview]
Message-ID: <4D693B9A.2060705@redhat.com> (raw)
In-Reply-To: <AANLkTik9vPW9qYE=Ru226b-JbxrPMtxGMyAsvTp27uFP@mail.gmail.com>
On 02/26/2011 05:47 PM, Blue Swirl wrote:
> On Sat, Feb 26, 2011 at 5:40 PM, Paolo Bonzini<pbonzini@redhat.com> wrote:
>> For now, qemu_cond_timedwait and qemu_mutex_timedlock are left as
>> POSIX-only functions. They can be removed later, once the patches
>> that remove their uses are in.
>>
>> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
>> ---
>> Makefile.objs | 4 +-
>> qemu-thread.c => qemu-thread-posix.c | 0
>> qemu-thread-posix.h | 18 +++
>> qemu-thread-win32.c | 260 ++++++++++++++++++++++++++++++++++
>> qemu-thread-win32.h | 21 +++
>> qemu-thread.h | 27 ++--
>> 6 files changed, 313 insertions(+), 17 deletions(-)
>> rename qemu-thread.c => qemu-thread-posix.c (100%)
>> create mode 100644 qemu-thread-posix.h
>> create mode 100644 qemu-thread-win32.c
>> create mode 100644 qemu-thread-win32.h
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 9e98a66..a52f42f 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -142,8 +142,8 @@ endif
>> common-obj-y += $(addprefix ui/, $(ui-obj-y))
>>
>> common-obj-y += iov.o acl.o
>> -common-obj-$(CONFIG_THREAD) += qemu-thread.o
>> -common-obj-$(CONFIG_POSIX) += compatfd.o
>> +common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
>> +common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
>> common-obj-y += notify.o event_notifier.o
>> common-obj-y += qemu-timer.o qemu-timer-common.o
>>
>> diff --git a/qemu-thread.c b/qemu-thread-posix.c
>> similarity index 100%
>> rename from qemu-thread.c
>> rename to qemu-thread-posix.c
>> diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
>> new file mode 100644
>> index 0000000..7af371c
>> --- /dev/null
>> +++ b/qemu-thread-posix.h
>> @@ -0,0 +1,18 @@
>> +#ifndef __QEMU_THREAD_POSIX_H
>> +#define __QEMU_THREAD_POSIX_H 1
>> +#include "pthread.h"
>> +
>> +struct QemuMutex {
>> + pthread_mutex_t lock;
>> +};
>> +
>> +struct QemuCond {
>> + pthread_cond_t cond;
>> +};
>> +
>> +struct QemuThread {
>> + pthread_t thread;
>> +};
>> +
>> +void qemu_thread_signal(QemuThread *thread, int sig);
>> +#endif
>> diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
>> new file mode 100644
>> index 0000000..89422ce
>> --- /dev/null
>> +++ b/qemu-thread-win32.c
>> @@ -0,0 +1,260 @@
>> +/*
>> + * Win32 implementation for mutex/cond/thread functions
>> + *
>> + * Copyright Red Hat, Inc. 2010
>> + *
>> + * Author:
>> + * Paolo Bonzini<pbonzini@redhat.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + *
>> + */
>> +#include "qemu-common.h"
>> +#include "qemu-thread.h"
>> +#include<process.h>
>> +#include<assert.h>
>> +#include<limits.h>
>> +
>> +static void error_exit(int err, const char *msg)
>> +{
>> + char *pstr;
>> +
>> + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
>> + NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
>> + fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
>> + LocalFree(pstr);
>> + exit(1);
>> +}
>> +
>> +void qemu_mutex_init(QemuMutex *mutex)
>> +{
>> + mutex->owner = 0;
>> + InitializeCriticalSection(&mutex->lock);
>> +}
>> +
>> +void qemu_mutex_lock(QemuMutex *mutex)
>> +{
>> + EnterCriticalSection(&mutex->lock);
>> +
>> + /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
>> + * using them as such.
>> + */
>> + assert(mutex->owner == 0);
>> + mutex->owner = GetCurrentThreadId();
>> +}
>> +
>> +int qemu_mutex_trylock(QemuMutex *mutex)
>> +{
>> + int owned;
>> +
>> + owned = TryEnterCriticalSection(&mutex->lock);
>> + if (owned) {
>> + assert(mutex->owner == 0);
>> + mutex->owner = GetCurrentThreadId();
>> + }
>> + return !owned;
>> +}
>> +
>> +void qemu_mutex_unlock(QemuMutex *mutex)
>> +{
>> + assert(mutex->owner == GetCurrentThreadId());
>> + mutex->owner = 0;
>> + 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_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);
>> +}
>> +
>> +void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
>> +{
>> + /*
>> + * This access is protected under the mutex.
>> + */
>> + cond->waiters++;
>> +
>> + /*
>> + * Unlock external mutex and wait for signal.
>> + * NOTE: we've held mutex locked long enough to increment
>> + * waiters count above, so there's no problem with
>> + * leaving mutex unlocked before we wait on semaphore.
>> + */
>> + qemu_mutex_unlock(mutex);
>> + WaitForSingleObject(cond->sema, INFINITE);
>> +
>> + /* Now waiters must rendez-vous with the signaling thread and
>> + * let it continue. For cond_broadcast this has heavy contention
>> + * and triggers thundering herd. So goes life.
>> + *
>> + * Decrease waiters count. The mutex is not taken, so we have
>> + * to do this atomically.
>> + *
>> + * All waiters contend for the mutex at the end of this function
>> + * until the signaling thread relinquishes it. To ensure
>> + * each waiter consumes exactly one slice of the semaphore,
>> + * the signaling thread stops until it is told by the last
>> + * waiter that it can go on.
>> + */
>> + if (InterlockedDecrement(&cond->waiters) == cond->target) {
>> + SetEvent(cond->continue_event);
>> + }
>> +
>> + qemu_mutex_lock(mutex);
>> +}
>> +
>> +struct qemu_thread_data {
>
> QemuThreadData?
Ok, will resubmit asap. Can you add this convention to checkpatch?
Paolo
next prev parent reply other threads:[~2011-02-26 17:43 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 01/22] unlock iothread during WaitForMultipleObjects Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 02/22] implement win32 dynticks timer Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 03/22] use win32 timer queues Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 04/22] Refactor thread retrieval and check Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation Paolo Bonzini
2011-02-26 16:47 ` Blue Swirl
2011-02-26 17:42 ` Paolo Bonzini [this message]
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 06/22] include qemu-thread.h early Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex Paolo Bonzini
2011-02-27 9:33 ` [Qemu-devel] " Jan Kiszka
2011-02-27 15:06 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 08/22] remove CONFIG_THREAD Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 09/22] target-sh4: move intr_at_halt out of cpu_halted() Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 10/22] inline cpu_halted into sole caller Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 11/22] always qemu_cpu_kick after unhalting a cpu Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 12/22] exit round-robin vcpu loop if cpu->stopped is true Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 13/22] always signal pause_cond after stopping a VCPU Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 14/22] do not use timedwait on qemu_halt_cond Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 15/22] do not use timedwait on qemu_system_cond Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 16/22] do not use timedwait on qemu_pause_cond Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 17/22] do not use timedwait on qemu_cpu_cond Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 18/22] iothread stops the vcpu thread via IPI Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init Paolo Bonzini
2011-02-27 9:41 ` [Qemu-devel] " Jan Kiszka
2011-02-27 15:07 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 20/22] provide dummy signal init functions for win32 Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 21/22] protect qemu_cpu_kick_self for Win32 Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 22/22] add Win32 IPI service Paolo Bonzini
2011-02-26 16:49 ` [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Blue Swirl
2011-02-27 9:47 ` [Qemu-devel] " Jan Kiszka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D693B9A.2060705@redhat.com \
--to=pbonzini@redhat.com \
--cc=aurelien@aurel32.net \
--cc=blauwirbel@gmail.com \
--cc=jan.kiszka@siemens.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).