|
@@ -16,6 +16,7 @@
|
|
#include "qemu/notify.h"
|
|
#include "qemu/notify.h"
|
|
#include "qemu-thread-common.h"
|
|
#include "qemu-thread-common.h"
|
|
#include "qemu/tsan.h"
|
|
#include "qemu/tsan.h"
|
|
|
|
+#include "qemu/bitmap.h"
|
|
|
|
|
|
static bool name_threads;
|
|
static bool name_threads;
|
|
|
|
|
|
@@ -552,6 +553,75 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
|
pthread_attr_destroy(&attr);
|
|
pthread_attr_destroy(&attr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int qemu_thread_set_affinity(QemuThread *thread, unsigned long *host_cpus,
|
|
|
|
+ unsigned long nbits)
|
|
|
|
+{
|
|
|
|
+#if defined(CONFIG_PTHREAD_AFFINITY_NP)
|
|
|
|
+ const size_t setsize = CPU_ALLOC_SIZE(nbits);
|
|
|
|
+ unsigned long value;
|
|
|
|
+ cpu_set_t *cpuset;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ cpuset = CPU_ALLOC(nbits);
|
|
|
|
+ g_assert(cpuset);
|
|
|
|
+
|
|
|
|
+ CPU_ZERO_S(setsize, cpuset);
|
|
|
|
+ value = find_first_bit(host_cpus, nbits);
|
|
|
|
+ while (value < nbits) {
|
|
|
|
+ CPU_SET_S(value, setsize, cpuset);
|
|
|
|
+ value = find_next_bit(host_cpus, nbits, value + 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ err = pthread_setaffinity_np(thread->thread, setsize, cpuset);
|
|
|
|
+ CPU_FREE(cpuset);
|
|
|
|
+ return err;
|
|
|
|
+#else
|
|
|
|
+ return -ENOSYS;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int qemu_thread_get_affinity(QemuThread *thread, unsigned long **host_cpus,
|
|
|
|
+ unsigned long *nbits)
|
|
|
|
+{
|
|
|
|
+#if defined(CONFIG_PTHREAD_AFFINITY_NP)
|
|
|
|
+ unsigned long tmpbits;
|
|
|
|
+ cpu_set_t *cpuset;
|
|
|
|
+ size_t setsize;
|
|
|
|
+ int i, err;
|
|
|
|
+
|
|
|
|
+ tmpbits = CPU_SETSIZE;
|
|
|
|
+ while (true) {
|
|
|
|
+ setsize = CPU_ALLOC_SIZE(tmpbits);
|
|
|
|
+ cpuset = CPU_ALLOC(tmpbits);
|
|
|
|
+ g_assert(cpuset);
|
|
|
|
+
|
|
|
|
+ err = pthread_getaffinity_np(thread->thread, setsize, cpuset);
|
|
|
|
+ if (err) {
|
|
|
|
+ CPU_FREE(cpuset);
|
|
|
|
+ if (err != -EINVAL) {
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+ tmpbits *= 2;
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Convert the result into a proper bitmap. */
|
|
|
|
+ *nbits = tmpbits;
|
|
|
|
+ *host_cpus = bitmap_new(tmpbits);
|
|
|
|
+ for (i = 0; i < tmpbits; i++) {
|
|
|
|
+ if (CPU_ISSET(i, cpuset)) {
|
|
|
|
+ set_bit(i, *host_cpus);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ CPU_FREE(cpuset);
|
|
|
|
+ return 0;
|
|
|
|
+#else
|
|
|
|
+ return -ENOSYS;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
void qemu_thread_get_self(QemuThread *thread)
|
|
void qemu_thread_get_self(QemuThread *thread)
|
|
{
|
|
{
|
|
thread->thread = pthread_self();
|
|
thread->thread = pthread_self();
|