aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2014-03-24 11:29:53 +0100
committerDavid 'Digit' Turner <digit@google.com>2014-04-09 19:43:25 +0200
commit4ab1225535dfc5fbcbde37a171b39224ea34e30b (patch)
treec0348e130e3aee6a3d9b1997ed24b84666ada361 /include
parenta49711e9c9b502d186114e600a045d33b5b61c4c (diff)
downloadqemu-4ab1225535dfc5fbcbde37a171b39224ea34e30b.tar.gz
exec.c: Use a QTAILQ to list CPUs.
This introduces CPUState, a mere typedef to CPUOldState for now, and changes the way CPUs are listed in QEMU. The goal is to get closer to upstream, while also allowing really separating CPUState from CPUArmState in future patches. + Move "current_cpu" to a thread-local variable on Linux, just like upstream. Testing shows this doesn't affect performance. Change-Id: Id07bbef4ba1584e607bec647d5117ac755c48ce6
Diffstat (limited to 'include')
-rw-r--r--include/exec/cpu-all.h18
-rw-r--r--include/exec/cpu-defs.h2
-rw-r--r--include/qemu/tls.h52
3 files changed, 69 insertions, 3 deletions
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 91822d95f0..0b269e3263 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -20,7 +20,9 @@
#define CPU_ALL_H
#include "qemu-common.h"
+#include "qemu/queue.h"
#include "qemu/thread.h"
+#include "qemu/tls.h"
#include "exec/cpu-common.h"
/* some important defines:
@@ -371,8 +373,20 @@ void cpu_dump_statistics(CPUArchState *env, FILE *f, fprintf_function cpu_fprint
void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
-extern CPUArchState *first_cpu;
-extern CPUArchState *cpu_single_env;
+
+typedef CPUOldState CPUState;
+Q_TAILQ_HEAD(CPUTailQ, CPUState,);
+extern struct CPUTailQ cpus;
+#define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
+#define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
+#define CPU_FOREACH_SAFE(cpu, next_cpu) \
+ QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
+#define first_cpu QTAILQ_FIRST(&cpus)
+
+DECLARE_TLS(CPUState *, current_cpu);
+#define current_cpu tls_var(current_cpu)
+// TODO(digit): Remove this.
+#define cpu_single_env current_cpu
/* Flags for use in ENV->INTERRUPT_PENDING.
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index d8583adc7e..4ed8a2472c 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -191,7 +191,7 @@ typedef struct CPUWatchpoint {
jmp_buf jmp_env; \
int exception_index; \
\
- CPUOldState *next_cpu; /* next CPU sharing TB cache */ \
+ Q_TAILQ_ENTRY(CPUOldState,) node; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
uint32_t host_tid; /* host thread ID */ \
int numa_node; /* NUMA node this cpu is belonging to */ \
diff --git a/include/qemu/tls.h b/include/qemu/tls.h
new file mode 100644
index 0000000000..b92ea9d7da
--- /dev/null
+++ b/include/qemu/tls.h
@@ -0,0 +1,52 @@
+/*
+ * Abstraction layer for defining and using TLS variables
+ *
+ * Copyright (c) 2011 Red Hat, Inc
+ * Copyright (c) 2011 Linaro Limited
+ *
+ * Authors:
+ * Paolo Bonzini <pbonzini@redhat.com>
+ * Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_TLS_H
+#define QEMU_TLS_H
+
+/* Per-thread variables. Note that we only have implementations
+ * which are really thread-local on Linux; the dummy implementations
+ * define plain global variables.
+ *
+ * This means that for the moment use should be restricted to
+ * per-VCPU variables, which are OK because:
+ * - the only -user mode supporting multiple VCPU threads is linux-user
+ * - TCG system mode is single-threaded regarding VCPUs
+ * - KVM system mode is multi-threaded but limited to Linux
+ *
+ * TODO: proper implementations via Win32 .tls sections and
+ * POSIX pthread_getspecific.
+ */
+#ifdef __linux__
+#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
+#define DEFINE_TLS(type, x) __thread __typeof__(type) tls__##x
+#define tls_var(x) tls__##x
+#else
+/* Dummy implementations which define plain global variables */
+#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
+#define DEFINE_TLS(type, x) __typeof__(type) tls__##x
+#define tls_var(x) tls__##x
+#endif
+
+#endif