13
#include "qemu/osdep.h"
14
#include "qemu/thread-context.h"
15
#include "qapi/error.h"
16
#include "qapi/qapi-builtin-visit.h"
17
#include "qapi/visitor.h"
18
#include "qemu/config-file.h"
19
#include "qapi/qapi-builtin-visit.h"
20
#include "qom/object_interfaces.h"
21
#include "qemu/module.h"
22
#include "qemu/bitmap.h"
34
typedef struct ThreadContextCmdNew {
37
void *(*start_routine)(void *);
42
static void *thread_context_run(void *opaque)
44
ThreadContext *tc = opaque;
46
tc->thread_id = qemu_get_thread_id();
47
qemu_sem_post(&tc->sem);
60
switch (tc->thread_cmd) {
64
tc->thread_cmd = TC_CMD_NONE;
65
qemu_sem_post(&tc->sem);
68
ThreadContextCmdNew *cmd_new = tc->thread_cmd_data;
70
qemu_thread_create(cmd_new->thread, cmd_new->name,
71
cmd_new->start_routine, cmd_new->arg,
73
tc->thread_cmd = TC_CMD_NONE;
74
tc->thread_cmd_data = NULL;
75
qemu_sem_post(&tc->sem);
79
g_assert_not_reached();
81
qemu_sem_wait(&tc->sem_thread);
85
static void thread_context_set_cpu_affinity(Object *obj, Visitor *v,
86
const char *name, void *opaque,
89
ThreadContext *tc = THREAD_CONTEXT(obj);
90
uint16List *l, *host_cpus = NULL;
91
unsigned long *bitmap = NULL;
94
if (tc->init_cpu_bitmap) {
95
error_setg(errp, "Mixing CPU and node affinity not supported");
99
if (!visit_type_uint16List(v, name, &host_cpus, errp)) {
104
error_setg(errp, "CPU list is empty");
108
for (l = host_cpus; l; l = l->next) {
109
nbits = MAX(nbits, l->value + 1);
111
bitmap = bitmap_new(nbits);
112
for (l = host_cpus; l; l = l->next) {
113
set_bit(l->value, bitmap);
116
if (tc->thread_id != -1) {
121
ret = qemu_thread_set_affinity(&tc->thread, bitmap, nbits);
123
error_setg(errp, "Setting CPU affinity failed: %s", strerror(ret));
126
tc->init_cpu_bitmap = bitmap;
128
tc->init_cpu_nbits = nbits;
132
qapi_free_uint16List(host_cpus);
135
static void thread_context_get_cpu_affinity(Object *obj, Visitor *v,
136
const char *name, void *opaque,
139
unsigned long *bitmap, nbits, value;
140
ThreadContext *tc = THREAD_CONTEXT(obj);
141
uint16List *host_cpus = NULL;
142
uint16List **tail = &host_cpus;
145
if (tc->thread_id == -1) {
146
error_setg(errp, "Object not initialized yet");
150
ret = qemu_thread_get_affinity(&tc->thread, &bitmap, &nbits);
152
error_setg(errp, "Getting CPU affinity failed: %s", strerror(ret));
156
value = find_first_bit(bitmap, nbits);
157
while (value < nbits) {
158
QAPI_LIST_APPEND(tail, value);
160
value = find_next_bit(bitmap, nbits, value + 1);
164
visit_type_uint16List(v, name, &host_cpus, errp);
165
qapi_free_uint16List(host_cpus);
168
static void thread_context_set_node_affinity(Object *obj, Visitor *v,
169
const char *name, void *opaque,
173
const int nbits = numa_num_possible_cpus();
174
ThreadContext *tc = THREAD_CONTEXT(obj);
175
uint16List *l, *host_nodes = NULL;
176
unsigned long *bitmap = NULL;
177
struct bitmask *tmp_cpus;
180
if (tc->init_cpu_bitmap) {
181
error_setg(errp, "Mixing CPU and node affinity not supported");
185
if (!visit_type_uint16List(v, name, &host_nodes, errp)) {
190
error_setg(errp, "Node list is empty");
194
bitmap = bitmap_new(nbits);
195
tmp_cpus = numa_allocate_cpumask();
196
for (l = host_nodes; l; l = l->next) {
197
numa_bitmask_clearall(tmp_cpus);
198
ret = numa_node_to_cpus(l->value, tmp_cpus);
203
for (i = 0; i < nbits; i++) {
204
if (numa_bitmask_isbitset(tmp_cpus, i)) {
209
numa_free_cpumask(tmp_cpus);
211
if (bitmap_empty(bitmap, nbits)) {
212
error_setg(errp, "The nodes select no CPUs");
216
if (tc->thread_id != -1) {
221
ret = qemu_thread_set_affinity(&tc->thread, bitmap, nbits);
223
error_setg(errp, "Setting CPU affinity failed: %s", strerror(ret));
226
tc->init_cpu_bitmap = bitmap;
228
tc->init_cpu_nbits = nbits;
232
qapi_free_uint16List(host_nodes);
234
error_setg(errp, "NUMA node affinity is not supported by this QEMU");
238
static void thread_context_get_thread_id(Object *obj, Visitor *v,
239
const char *name, void *opaque,
242
ThreadContext *tc = THREAD_CONTEXT(obj);
243
uint64_t value = tc->thread_id;
245
visit_type_uint64(v, name, &value, errp);
248
static void thread_context_instance_complete(UserCreatable *uc, Error **errp)
250
ThreadContext *tc = THREAD_CONTEXT(uc);
254
thread_name = g_strdup_printf("TC %s",
255
object_get_canonical_path_component(OBJECT(uc)));
256
qemu_thread_create(&tc->thread, thread_name, thread_context_run, tc,
257
QEMU_THREAD_JOINABLE);
261
while (tc->thread_id == -1) {
262
qemu_sem_wait(&tc->sem);
265
if (tc->init_cpu_bitmap) {
266
ret = qemu_thread_set_affinity(&tc->thread, tc->init_cpu_bitmap,
269
error_setg(errp, "Setting CPU affinity failed: %s", strerror(ret));
271
g_free(tc->init_cpu_bitmap);
272
tc->init_cpu_bitmap = NULL;
276
static void thread_context_class_init(ObjectClass *oc, void *data)
278
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
280
ucc->complete = thread_context_instance_complete;
281
object_class_property_add(oc, "thread-id", "int",
282
thread_context_get_thread_id, NULL, NULL,
284
object_class_property_add(oc, "cpu-affinity", "int",
285
thread_context_get_cpu_affinity,
286
thread_context_set_cpu_affinity, NULL, NULL);
287
object_class_property_add(oc, "node-affinity", "int", NULL,
288
thread_context_set_node_affinity, NULL, NULL);
291
static void thread_context_instance_init(Object *obj)
293
ThreadContext *tc = THREAD_CONTEXT(obj);
296
qemu_sem_init(&tc->sem, 0);
297
qemu_sem_init(&tc->sem_thread, 0);
298
qemu_mutex_init(&tc->mutex);
301
static void thread_context_instance_finalize(Object *obj)
303
ThreadContext *tc = THREAD_CONTEXT(obj);
305
if (tc->thread_id != -1) {
306
tc->thread_cmd = TC_CMD_STOP;
307
qemu_sem_post(&tc->sem_thread);
308
qemu_thread_join(&tc->thread);
310
qemu_sem_destroy(&tc->sem);
311
qemu_sem_destroy(&tc->sem_thread);
312
qemu_mutex_destroy(&tc->mutex);
315
static const TypeInfo thread_context_info = {
316
.name = TYPE_THREAD_CONTEXT,
317
.parent = TYPE_OBJECT,
318
.class_init = thread_context_class_init,
319
.instance_size = sizeof(ThreadContext),
320
.instance_init = thread_context_instance_init,
321
.instance_finalize = thread_context_instance_finalize,
322
.interfaces = (InterfaceInfo[]) {
323
{ TYPE_USER_CREATABLE },
328
static void thread_context_register_types(void)
330
type_register_static(&thread_context_info);
332
type_init(thread_context_register_types)
334
void thread_context_create_thread(ThreadContext *tc, QemuThread *thread,
336
void *(*start_routine)(void *), void *arg,
339
ThreadContextCmdNew data = {
342
.start_routine = start_routine,
347
qemu_mutex_lock(&tc->mutex);
348
tc->thread_cmd = TC_CMD_NEW;
349
tc->thread_cmd_data = &data;
350
qemu_sem_post(&tc->sem_thread);
352
while (tc->thread_cmd != TC_CMD_NONE) {
353
qemu_sem_wait(&tc->sem);
355
qemu_mutex_unlock(&tc->mutex);