Skip to content

Commit

Permalink
cpus-common: simplify locking for start_exclusive/end_exclusive
Browse files Browse the repository at this point in the history
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: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
bonzini committed Sep 27, 2016
1 parent cf07da6 commit 758e1b2
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 8 deletions.
11 changes: 8 additions & 3 deletions cpus-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion docs/tcg-exclusive.promela
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 0 additions & 4 deletions include/qom/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -846,17 +846,13 @@ 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);

/**
* end_exclusive:
*
* Concludes an exclusive execution section started by start_exclusive.
* Releases the CPU list lock.
*/
void end_exclusive(void);

Expand Down

0 comments on commit 758e1b2

Please sign in to comment.