qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] qemu-char: eliminate busy waiting on can_rea


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH v2] qemu-char: eliminate busy waiting on can_read returning zero
Date: Sun, 07 Apr 2013 20:49:16 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130311 Thunderbird/17.0.4

Il 06/04/2013 21:00, Amit Shah ha scritto:
> On (Fri) 05 Apr 2013 [17:59:33], Paolo Bonzini wrote:
>> The character backend refactoring introduced an undesirable busy wait.
>> The busy wait happens if can_read returns zero and there is data available
>> on the character device's file descriptor.  Then, the I/O watch will
>> fire continuously and, with TCG, the CPU thread will never run.
>>
>>     1) Char backend asks front end if it can write
>>     2) Front end says no
>>     3) poll() finds the char backend's descriptor is available
>>     4) Goto (1)
>>
>> What we really want is this (note that step 3 avoids the busy wait):
>>
>>     1) Char backend asks front end if it can write
>>     2) Front end says no
>>     3) poll() goes on without char backend's descriptor
>>     4) Goto (1) until qemu_chr_accept_input() called
>>
>>     5) Char backend asks front end if it can write
>>     6) Front end says yes
>>     7) poll() finds the char backend's descriptor is available
>>     8) Backend handler called
>>
>> After this patch, the IOWatchPoll source and the watch source are
>> separated.  The IOWatchPoll is simply a hook that runs during the prepare
>> phase on each main loop iteration.  The hook adds/removes the actual
>> source depending on the return value from can_read.
>>
>> A simple reproducer is
>>
>>     qemu-system-i386 -serial mon:stdio
>>
>> ... followed by banging on the terminal as much as you can. :)  Without
>> this patch, emulation will hang.
>>
>> Signed-off-by: Paolo Bonzini <address@hidden>
>> ---
>>         v1->v2: use g_source_get_context to find if the watch was active
> 
>>  static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
>>  {
>>      IOWatchPoll *iwp = io_watch_poll_from_source(source);
>> -
>> -    iwp->max_size = iwp->fd_can_read(iwp->opaque);
>> -    if (iwp->max_size == 0) {
>> +    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
>> +    bool was_active = g_source_get_context(iwp->src) != NULL;
> 
> This gives me a bunch of
> 
> (process:30075): GLib-CRITICAL **: g_source_get_context: assertion 
> `!SOURCE_DESTROYED (source)' failed
> 
> messages

This should fix it, but unfortunately Peter reports it is not enough:

diff --git a/qemu-char.c b/qemu-char.c
index 85ebcf9..c2fb985 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -610,8 +610,14 @@ static IOWatchPoll
*io_watch_poll_from_source(GSource *source)
 static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
 {
     IOWatchPoll *iwp = io_watch_poll_from_source(source);
-    bool was_active = g_source_get_context(iwp->src) != NULL;
-    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
+    bool was_active, now_active;
+
+    if (g_source_is_destroyed(iwp->src)) {
+        return FALSE;
+    }
+
+    was_active = g_source_get_context(iwp->src) != NULL;
+    now_active = iwp->fd_can_read(iwp->opaque) > 0;
     if (was_active == now_active) {
         return FALSE;
     }


I'm not sure what is different between the microblaze and x86 cases.
Peter, please send us reproduction instructions.

Paolo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]