On May 12, 2015, at 3:45 AM, Paolo Bonzini wrote:

> On 12/05/2015 00:43, Programmingkid wrote:
>> 
>> On May 10, 2015, at 10:54 AM, Paolo Bonzini wrote:
>> 
>>> 
>>> 
>>> On 06/05/2015 18:40, Programmingkid wrote:
>>>> When I try to use the pcspk sound hardware, QEMU freezes and uses
>>>> 100% of the cpu time. This is the command I use:
>>>> 
>>>> qemu-system-i386 -cdrom <anything you wan here> -soundhw pcspk
>>>> 
>>>> This looks like a deadlock situation because some unknown code called
>>>> qemu_mutex_lock(). Here is the stack trace at the freeze:
>>>> 
>>>> (gdb) bt #0  0x00007fff824e2db6 in semaphore_wait_trap () #1
>>>> 0x00007fff824e8417 in pthread_mutex_lock () #2  0x0000000100267199 in
>>>> qemu_mutex_lock (mutex=<value temporarily unavailable, due to
>>>> optimizations>) at util/qemu-thread-posix.c:73 #3  0x003c44016e95153b
>>>> in ?? ()
>>>> 
>>>> My host is Mac OS 10.6.8. My guest isn't really anything. I have used
>>>> Windows XP before but it isn't necessary to reproduce the problem.
>>>> 
>>>> The ?? is what appears to be the problem. I can't even print
>>>> instructions at that address. Any ideas as to what is calling the
>>>> qemu_mutex_lock() function could help.
> 
> The unknown code here is probably some place where gdb cannot find the
> frame pointer.  Not a surprise if you are using a 5 year old debugger
> with (presumably) a newer compiler.
> 
>>> Reproduced with a FreeDOS image from QEMU Advent Calendar.  It locks up
>>> as soon as you type "beep".
>>> 
>>> It works with the PulseAudio and ALSA backends, but it doesn't with the
>>> SDL backend, even on Linux.
>>> 
>>> Also, it deadlocks even with KVM enabled.
>>> 
>>> Paolo
>> 
>> OK, I see a pattern. SDL and CoreAudio both don't support audio input. Both 
>> of them have this code:
>> .voice_size_in  = 0
>> 
>> Alsa and PulseAudio do support audio input and work. Coincidence?
> 
> Yes.  Locking in SDL is completely broken.  sdl_callback runs with the
> SDL audio lock taken, but then it waits on a semaphore so you cannot
> call any other SDL audio function from the main thread.  As soon as you
> do that, you get a deadlock.  I'm strongly tempted to just remove the
> driver.
> 
> On the other hand, CoreAudio seems to be okay.  Can you try "thread
> apply all bt full" from gdb?
> 
> Paolo


Found out why QEMU is deadlocking. It is because a mutex that has been unlocked 
over 20 times in a row is being locked. 

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_lock.html

According to the above link, if pthread_mutex_unlock() is called on a mutex 
that isn't locked, undefined behavior results. This means the mutex that has 
been unlocked so many times in a row cannot be trusted. There isn't a way to 
find out who owns a mutex on Mac OS X, so I made my own logging code to help 
find out what was going on. If you have access to Mac OS 10.6, you could try 
out this code by just pasting it in qemu-thread-posix.c:

// Debugging code

#define MAX_SIZE 100
int thread_dict[MAX_SIZE] = {0};
int mutex_dict[MAX_SIZE] = {0};

int addToDict(int id, int * a_dict)
{
    static int index = 0;
    if(index > 99) {
        printf("ERROR: too many threads to keep track of!\n");
        return -1;
    }
    a_dict[index] = id;
    index++;
    return index;
}

int getID(int origID, int* a_dict)
{
    int index;
    for (index = 0; index < MAX_SIZE; index++) {
        if(a_dict[index] == origID) {
            return index;
        }
    }
    return addToDict(origID, a_dict);
}

#include <sys/syscall.h>
void qemu_mutex_lock(QemuMutex *mutex)
{
    int err;
    static int count = 0;
    printf("Lock\tThread = %d\tMutex = %d\n", getID(syscall(SYS_thread_selfid), 
thread_dict), getID(&mutex, mutex_dict));
    
    err = pthread_mutex_lock(&mutex->lock);
    if (err)
        error_exit(err, __func__);
}

int qemu_mutex_trylock(QemuMutex *mutex)
{
    printf("Trying lock\tThread = %d\tMutex = %d\n", 
getID(syscall(SYS_thread_selfid), thread_dict), getID(&mutex, mutex_dict));
    return pthread_mutex_trylock(&mutex->lock);
}

void qemu_mutex_unlock(QemuMutex *mutex)
{
    int err;

    static int count = 0;
    printf("Unlock\tThread = %d\tMutex = %d\n", 
getID(syscall(SYS_thread_selfid), thread_dict), getID(&mutex, mutex_dict));

    err = pthread_mutex_unlock(&mutex->lock);
    if (err)
        error_exit(err, __func__);
}

Locking mutex 38 is where qemu-system-i386 seems to fail the most. 

To test the code, I just ran qemu with -soundhw pcspk. 

Reply via email to