* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
return max_cpu_index;
}
+CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
+
void cpu_list_add(CPUState *cpu)
{
QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
}
+CPUState *qemu_get_cpu(int index)
+{
+ CPUState *cpu;
+
+ CPU_FOREACH(cpu) {
+ if (cpu->cpu_index == index) {
+ return cpu;
+ }
+ }
+
+ return NULL;
+}
+
+/* current CPU in the current thread. It is only valid inside cpu_exec() */
+__thread CPUState *current_cpu;
+
struct qemu_work_item {
QSIMPLEQ_ENTRY(qemu_work_item) node;
run_on_cpu_func func;
wi.exclusive = false;
queue_work_on_cpu(cpu, &wi);
- while (!atomic_mb_read(&wi.done)) {
+ while (!qatomic_mb_read(&wi.done)) {
CPUState *self_cpu = current_cpu;
qemu_cond_wait(&qemu_work_cond, mutex);
exclusive_idle();
/* Make all other cpus stop executing. */
- atomic_set(&pending_cpus, 1);
+ qatomic_set(&pending_cpus, 1);
/* Write pending_cpus before reading other_cpu->running. */
smp_mb();
running_cpus = 0;
CPU_FOREACH(other_cpu) {
- if (atomic_read(&other_cpu->running)) {
+ if (qatomic_read(&other_cpu->running)) {
other_cpu->has_waiter = true;
running_cpus++;
qemu_cpu_kick(other_cpu);
}
}
- atomic_set(&pending_cpus, running_cpus + 1);
+ qatomic_set(&pending_cpus, running_cpus + 1);
while (pending_cpus > 1) {
qemu_cond_wait(&exclusive_cond, &qemu_cpu_list_lock);
}
current_cpu->in_exclusive_context = false;
qemu_mutex_lock(&qemu_cpu_list_lock);
- atomic_set(&pending_cpus, 0);
+ qatomic_set(&pending_cpus, 0);
qemu_cond_broadcast(&exclusive_resume);
qemu_mutex_unlock(&qemu_cpu_list_lock);
}
/* Wait for exclusive ops to finish, and begin cpu execution. */
void cpu_exec_start(CPUState *cpu)
{
- atomic_set(&cpu->running, true);
+ qatomic_set(&cpu->running, true);
/* Write cpu->running before reading pending_cpus. */
smp_mb();
* 3. pending_cpus == 0. Then start_exclusive is definitely going to
* see cpu->running == true, and it will kick the CPU.
*/
- if (unlikely(atomic_read(&pending_cpus))) {
+ if (unlikely(qatomic_read(&pending_cpus))) {
QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
if (!cpu->has_waiter) {
/* Not counted in pending_cpus, let the exclusive item
* run. Since we have the lock, just set cpu->running to true
* while holding it; no need to check pending_cpus again.
*/
- atomic_set(&cpu->running, false);
+ qatomic_set(&cpu->running, false);
exclusive_idle();
/* Now pending_cpus is zero. */
- atomic_set(&cpu->running, true);
+ qatomic_set(&cpu->running, true);
} else {
/* Counted in pending_cpus, go ahead and release the
* waiter at cpu_exec_end.
/* Mark cpu as not executing, and release pending exclusive ops. */
void cpu_exec_end(CPUState *cpu)
{
- atomic_set(&cpu->running, false);
+ qatomic_set(&cpu->running, false);
/* Write cpu->running before reading pending_cpus. */
smp_mb();
* see cpu->running == false, and it can ignore this CPU until the
* next cpu_exec_start.
*/
- if (unlikely(atomic_read(&pending_cpus))) {
+ if (unlikely(qatomic_read(&pending_cpus))) {
QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
if (cpu->has_waiter) {
cpu->has_waiter = false;
- atomic_set(&pending_cpus, pending_cpus - 1);
+ qatomic_set(&pending_cpus, pending_cpus - 1);
if (pending_cpus == 1) {
qemu_cond_signal(&exclusive_cond);
}
if (wi->free) {
g_free(wi);
} else {
- atomic_mb_set(&wi->done, true);
+ qatomic_mb_set(&wi->done, true);
}
}
qemu_mutex_unlock(&cpu->work_mutex);