Commit 758e1b2b authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

cpus-common: simplify locking for start_exclusive/end_exclusive



It is not necessary to hold qemu_cpu_list_mutex throughout the
exclusive section, because no other exclusive section can run
while pending_cpus != 0.

exclusive_idle() is called in cpu_exec_start(), and that prevents
any CPUs created after start_exclusive() from entering cpu_exec()
during an exclusive section.

Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Reviewed-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent cf07da65
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -171,8 +171,7 @@ static inline void exclusive_idle(void)
}

/* Start an exclusive operation.
   Must only be called from outside cpu_exec, takes
   qemu_cpu_list_lock.   */
   Must only be called from outside cpu_exec.  */
void start_exclusive(void)
{
    CPUState *other_cpu;
@@ -191,11 +190,17 @@ void start_exclusive(void)
    while (pending_cpus > 1) {
        qemu_cond_wait(&exclusive_cond, &qemu_cpu_list_lock);
    }

    /* Can release mutex, no one will enter another exclusive
     * section until end_exclusive resets pending_cpus to 0.
     */
    qemu_mutex_unlock(&qemu_cpu_list_lock);
}

/* Finish an exclusive operation.  Releases qemu_cpu_list_lock.  */
/* Finish an exclusive operation.  */
void end_exclusive(void)
{
    qemu_mutex_lock(&qemu_cpu_list_lock);
    pending_cpus = 0;
    qemu_cond_broadcast(&exclusive_resume);
    qemu_mutex_unlock(&qemu_cpu_list_lock);
+3 −1
Original line number Diff line number Diff line
@@ -98,9 +98,11 @@ byte has_waiter[N_CPUS];
    do                                                            \
      :: pending_cpus > 1 -> COND_WAIT(exclusive_cond, mutex);    \
      :: else             -> break;                               \
    od
    od;                                                           \
    MUTEX_UNLOCK(mutex);

#define end_exclusive()                                           \
    MUTEX_LOCK(mutex);                                            \
    pending_cpus = 0;                                             \
    COND_BROADCAST(exclusive_resume);                             \
    MUTEX_UNLOCK(mutex);
+0 −4
Original line number Diff line number Diff line
@@ -846,9 +846,6 @@ void cpu_exec_end(CPUState *cpu);
 * cpu_exec are exited immediately.  CPUs that call cpu_exec_start
 * during the exclusive section go to sleep until this CPU calls
 * end_exclusive.
 *
 * Returns with the CPU list lock taken (which nests outside all
 * other locks except the BQL).
 */
void start_exclusive(void);

@@ -856,7 +853,6 @@ void start_exclusive(void);
 * end_exclusive:
 *
 * Concludes an exclusive execution section started by start_exclusive.
 * Releases the CPU list lock.
 */
void end_exclusive(void);