]> Git Repo - qemu.git/commit - cpus.c
cpus: avoid pause_all_vcpus getting stuck due to race
authorLongpeng <[email protected]>
Mon, 16 Mar 2020 08:37:32 +0000 (16:37 +0800)
committerPaolo Bonzini <[email protected]>
Mon, 16 Mar 2020 22:02:26 +0000 (23:02 +0100)
commitf962cac4c24157aeceff59cbf9dac8b5e30c55da
tree4516763c219a4aebeb6f5e1fe9a93ce44dab8c1d
parent5073b5d3ea303d37f4a8e2ea451d7a2eb1817448
cpus: avoid pause_all_vcpus getting stuck due to race

We found an issue when repeat reboot in guest during migration, it cause the
migration thread never be waken up again.

<main loop>                        |<migration_thread>
                                   |
LOCK BQL                           |
...                                |
main_loop_should_exit              |
 pause_all_vcpus                   |
  1. set all cpus ->stop=true      |
     and then kick                 |
  2. return if all cpus is paused  |
     (by '->stopped == true'), else|
  3. qemu_cond_wait [BQL UNLOCK]   |
                                   |LOCK BQL
                                   |...
                                   |do_vm_stop
                                   | pause_all_vcpus
                                   |  (A)set all cpus ->stop=true
                                   |     and then kick
                                   |  (B)return if all cpus is paused
                                   |     (by '->stopped == true'), else
                                   |  (C)qemu_cond_wait [BQL UNLOCK]
  4. be waken up and LOCK BQL      |  (D)be waken up BUT wait for  BQL
  5. goto 2.                       |
 (BQL is still LOCKed)             |
 resume_all_vcpus                  |
  1. set all cpus ->stop=false     |
     and ->stopped=false           |
...                                |
BQL UNLOCK                         |  (E)LOCK BQL
                                   |  (F)goto B. [but stopped is false now!]
                                   |Finally, sleep at step 3 forever.

resume_all_vcpus should notice this race, so we need to move the change
of runstate before pause_all_vcpus in do_vm_stop() and ignore the resume
request if runstate is not running.

Cc: Dr. David Alan Gilbert <[email protected]>
Cc: Richard Henderson <[email protected]>
Signed-off-by: Longpeng <[email protected]>
Suggested-by: Paolo Bonzini <[email protected]>
Message-Id: <20200316083732[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
cpus.c
This page took 0.026194 seconds and 4 git commands to generate.