mirror of https://github.com/xemu-project/xemu.git
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: Richard Henderson <rth@twiddle.net> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
cf07da65f3
commit
758e1b2b62
|
@ -171,8 +171,7 @@ static inline void exclusive_idle(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start an exclusive operation.
|
/* Start an exclusive operation.
|
||||||
Must only be called from outside cpu_exec, takes
|
Must only be called from outside cpu_exec. */
|
||||||
qemu_cpu_list_lock. */
|
|
||||||
void start_exclusive(void)
|
void start_exclusive(void)
|
||||||
{
|
{
|
||||||
CPUState *other_cpu;
|
CPUState *other_cpu;
|
||||||
|
@ -191,11 +190,17 @@ void start_exclusive(void)
|
||||||
while (pending_cpus > 1) {
|
while (pending_cpus > 1) {
|
||||||
qemu_cond_wait(&exclusive_cond, &qemu_cpu_list_lock);
|
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)
|
void end_exclusive(void)
|
||||||
{
|
{
|
||||||
|
qemu_mutex_lock(&qemu_cpu_list_lock);
|
||||||
pending_cpus = 0;
|
pending_cpus = 0;
|
||||||
qemu_cond_broadcast(&exclusive_resume);
|
qemu_cond_broadcast(&exclusive_resume);
|
||||||
qemu_mutex_unlock(&qemu_cpu_list_lock);
|
qemu_mutex_unlock(&qemu_cpu_list_lock);
|
||||||
|
|
|
@ -98,9 +98,11 @@ byte has_waiter[N_CPUS];
|
||||||
do \
|
do \
|
||||||
:: pending_cpus > 1 -> COND_WAIT(exclusive_cond, mutex); \
|
:: pending_cpus > 1 -> COND_WAIT(exclusive_cond, mutex); \
|
||||||
:: else -> break; \
|
:: else -> break; \
|
||||||
od
|
od; \
|
||||||
|
MUTEX_UNLOCK(mutex);
|
||||||
|
|
||||||
#define end_exclusive() \
|
#define end_exclusive() \
|
||||||
|
MUTEX_LOCK(mutex); \
|
||||||
pending_cpus = 0; \
|
pending_cpus = 0; \
|
||||||
COND_BROADCAST(exclusive_resume); \
|
COND_BROADCAST(exclusive_resume); \
|
||||||
MUTEX_UNLOCK(mutex);
|
MUTEX_UNLOCK(mutex);
|
||||||
|
|
|
@ -846,9 +846,6 @@ void cpu_exec_end(CPUState *cpu);
|
||||||
* cpu_exec are exited immediately. CPUs that call cpu_exec_start
|
* cpu_exec are exited immediately. CPUs that call cpu_exec_start
|
||||||
* during the exclusive section go to sleep until this CPU calls
|
* during the exclusive section go to sleep until this CPU calls
|
||||||
* end_exclusive.
|
* end_exclusive.
|
||||||
*
|
|
||||||
* Returns with the CPU list lock taken (which nests outside all
|
|
||||||
* other locks except the BQL).
|
|
||||||
*/
|
*/
|
||||||
void start_exclusive(void);
|
void start_exclusive(void);
|
||||||
|
|
||||||
|
@ -856,7 +853,6 @@ void start_exclusive(void);
|
||||||
* end_exclusive:
|
* end_exclusive:
|
||||||
*
|
*
|
||||||
* Concludes an exclusive execution section started by start_exclusive.
|
* Concludes an exclusive execution section started by start_exclusive.
|
||||||
* Releases the CPU list lock.
|
|
||||||
*/
|
*/
|
||||||
void end_exclusive(void);
|
void end_exclusive(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue