qemu: qemu_cond_wait: Operation not permitted

来源:互联网 发布:java 解压jar包命令 编辑:程序博客网 时间:2024/06/08 09:49

qemu源码编程:在子线程中调用vm_stop会出现qemu: qemu_cond_wait: Operation not permitted错误,分析源码如下:

int vm_stop(RunState state)

{
    if (qemu_in_vcpu_thread()) {
        qemu_system_vmstop_request(state);
        /*
         * FIXME: should not return to device code in case
         * vm_stop() has been requested.
         */
        cpu_stop_current();
        return 0;
    }

    return do_vm_stop(state);
}

在vm_stop函数中调用do_vm_stop

static int do_vm_stop(RunState state)
{
    int ret = 0;

    if (runstate_is_running()) {
        cpu_disable_ticks();
        pause_all_vcpus();
        runstate_set(state);
        vm_state_notify(0, state);
        monitor_protocol_event(QEVENT_STOP, NULL);
    }

    bdrv_drain_all();
    ret = bdrv_flush_all();

    return ret;
}

do_vm_stop中调用pause_all_vcpus();

void pause_all_vcpus(void)
{
    CPUArchState *penv = first_cpu;

    qemu_clock_enable(vm_clock, false);
    while (penv) {
        CPUState *pcpu = ENV_GET_CPU(penv);
        pcpu->stop = true;
        qemu_cpu_kick(pcpu);
        penv = penv->next_cpu;
    }

    if (qemu_in_vcpu_thread()) {
        cpu_stop_current();
        if (!kvm_enabled()) {
            penv = first_cpu;
            while (penv) {
                CPUState *pcpu = ENV_GET_CPU(penv);
                pcpu->stop = false;
                pcpu->stopped = true;
                penv = penv->next_cpu;
            }
            return;
        }
    }

    while (!all_vcpus_paused()) {
        qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
        penv = first_cpu;
        while (penv) {
            qemu_cpu_kick(ENV_GET_CPU(penv));
            penv = penv->next_cpu;
        }
    }
}
pause_all_vcpus()中调用 qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);时候因为我们之前并未得到qemu_global_mutex锁导致出错,因此需要在vm_stop前后加锁和释放锁:

    qemu_mutex_lock_iothread();
    vm_stop(RUN_STATE_SAVE_VM);
    qemu_mutex_unlock_iothread();


原创粉丝点击