eal: thread affinity API
1. add two TLS *_socket_id* and *_cpuset* 2. add one internal API, eal_cpu_socket_id/eal_thread_dump_affinity 3. add two public API, rte_thread_set/get_affinity 4. update EAL version map for EAL public API The API works for both EAL thread and non EAL thread. When calling rte_thread_set_affinity, the *_socket_id* and *_cpuset* of calling thread will be updated if the thread successfully set the cpu affinity. Signed-off-by: Cunming Liang <cunming.liang@intel.com> Acked-by: Olivier Matz <olivier.matz@6wind.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
This commit is contained in:
parent
ef76436c68
commit
9e29251b2a
@ -77,6 +77,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_hexdump.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_devargs.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_dev.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_options.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_thread.c
|
||||
|
||||
CFLAGS_eal.o := -D_GNU_SOURCE
|
||||
#CFLAGS_eal_thread.o := -D_GNU_SOURCE
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "eal_thread.h"
|
||||
|
||||
RTE_DEFINE_PER_LCORE(unsigned, _lcore_id);
|
||||
RTE_DEFINE_PER_LCORE(unsigned, _socket_id);
|
||||
RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset);
|
||||
|
||||
/*
|
||||
* Send a message to a slave lcore identified by slave_id to call a
|
||||
|
@ -83,6 +83,8 @@ DPDK_2.0 {
|
||||
rte_snprintf;
|
||||
rte_strerror;
|
||||
rte_strsplit;
|
||||
rte_thread_get_affinity;
|
||||
rte_thread_set_affinity;
|
||||
rte_vlog;
|
||||
rte_xen_dom0_memory_attach;
|
||||
rte_xen_dom0_memory_init;
|
||||
|
150
lib/librte_eal/common/eal_common_thread.c
Normal file
150
lib/librte_eal/common/eal_common_thread.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_memory.h>
|
||||
#include <rte_log.h>
|
||||
|
||||
#include "eal_thread.h"
|
||||
|
||||
int eal_cpuset_socket_id(rte_cpuset_t *cpusetp)
|
||||
{
|
||||
unsigned cpu = 0;
|
||||
int socket_id = SOCKET_ID_ANY;
|
||||
int sid;
|
||||
|
||||
if (cpusetp == NULL)
|
||||
return SOCKET_ID_ANY;
|
||||
|
||||
do {
|
||||
if (!CPU_ISSET(cpu, cpusetp))
|
||||
continue;
|
||||
|
||||
if (socket_id == SOCKET_ID_ANY)
|
||||
socket_id = eal_cpu_socket_id(cpu);
|
||||
|
||||
sid = eal_cpu_socket_id(cpu);
|
||||
if (socket_id != sid) {
|
||||
socket_id = SOCKET_ID_ANY;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (++cpu < RTE_MAX_LCORE);
|
||||
|
||||
return socket_id;
|
||||
}
|
||||
|
||||
int
|
||||
rte_thread_set_affinity(rte_cpuset_t *cpusetp)
|
||||
{
|
||||
int s;
|
||||
unsigned lcore_id;
|
||||
pthread_t tid;
|
||||
|
||||
tid = pthread_self();
|
||||
|
||||
s = pthread_setaffinity_np(tid, sizeof(rte_cpuset_t), cpusetp);
|
||||
if (s != 0) {
|
||||
RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* store socket_id in TLS for quick access */
|
||||
RTE_PER_LCORE(_socket_id) =
|
||||
eal_cpuset_socket_id(cpusetp);
|
||||
|
||||
/* store cpuset in TLS for quick access */
|
||||
memmove(&RTE_PER_LCORE(_cpuset), cpusetp,
|
||||
sizeof(rte_cpuset_t));
|
||||
|
||||
lcore_id = rte_lcore_id();
|
||||
if (lcore_id != (unsigned)LCORE_ID_ANY) {
|
||||
/* EAL thread will update lcore_config */
|
||||
lcore_config[lcore_id].socket_id = RTE_PER_LCORE(_socket_id);
|
||||
memmove(&lcore_config[lcore_id].cpuset, cpusetp,
|
||||
sizeof(rte_cpuset_t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rte_thread_get_affinity(rte_cpuset_t *cpusetp)
|
||||
{
|
||||
assert(cpusetp);
|
||||
memmove(cpusetp, &RTE_PER_LCORE(_cpuset),
|
||||
sizeof(rte_cpuset_t));
|
||||
}
|
||||
|
||||
int
|
||||
eal_thread_dump_affinity(char *str, unsigned size)
|
||||
{
|
||||
rte_cpuset_t cpuset;
|
||||
unsigned cpu;
|
||||
int ret;
|
||||
unsigned int out = 0;
|
||||
|
||||
rte_thread_get_affinity(&cpuset);
|
||||
|
||||
for (cpu = 0; cpu < RTE_MAX_LCORE; cpu++) {
|
||||
if (!CPU_ISSET(cpu, &cpuset))
|
||||
continue;
|
||||
|
||||
ret = snprintf(str + out,
|
||||
size - out, "%u,", cpu);
|
||||
if (ret < 0 || (unsigned)ret >= size - out) {
|
||||
/* string will be truncated */
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
out += ret;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
/* remove the last separator */
|
||||
if (out > 0)
|
||||
str[out - 1] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
@ -34,6 +34,8 @@
|
||||
#ifndef EAL_THREAD_H
|
||||
#define EAL_THREAD_H
|
||||
|
||||
#include <rte_lcore.h>
|
||||
|
||||
/**
|
||||
* basic loop of thread, called for each thread by eal_init().
|
||||
*
|
||||
@ -61,4 +63,38 @@ void eal_thread_init_master(unsigned lcore_id);
|
||||
*/
|
||||
unsigned eal_cpu_socket_id(unsigned cpu_id);
|
||||
|
||||
/**
|
||||
* Get the NUMA socket id from cpuset.
|
||||
* This function is private to EAL.
|
||||
*
|
||||
* @param cpusetp
|
||||
* The point to a valid cpu set.
|
||||
* @return
|
||||
* socket_id or SOCKET_ID_ANY
|
||||
*/
|
||||
int eal_cpuset_socket_id(rte_cpuset_t *cpusetp);
|
||||
|
||||
/**
|
||||
* Default buffer size to use with eal_thread_dump_affinity()
|
||||
*/
|
||||
#define RTE_CPU_AFFINITY_STR_LEN 256
|
||||
|
||||
/**
|
||||
* Dump the current pthread cpuset.
|
||||
* This function is private to EAL.
|
||||
*
|
||||
* Note:
|
||||
* If the dump size is greater than the size of given buffer,
|
||||
* the string will be truncated and with '\0' at the end.
|
||||
*
|
||||
* @param str
|
||||
* The string buffer the cpuset will dump to.
|
||||
* @param size
|
||||
* The string buffer size.
|
||||
* @return
|
||||
* 0 for success, -1 if truncation happens.
|
||||
*/
|
||||
int
|
||||
eal_thread_dump_affinity(char *str, unsigned size);
|
||||
|
||||
#endif /* EAL_THREAD_H */
|
||||
|
@ -80,7 +80,9 @@ struct lcore_config {
|
||||
*/
|
||||
extern struct lcore_config lcore_config[RTE_MAX_LCORE];
|
||||
|
||||
RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per core "core id". */
|
||||
RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per thread "lcore id". */
|
||||
RTE_DECLARE_PER_LCORE(unsigned, _socket_id); /**< Per thread "socket id". */
|
||||
RTE_DECLARE_PER_LCORE(rte_cpuset_t, _cpuset); /**< Per thread "cpuset". */
|
||||
|
||||
/**
|
||||
* Return the ID of the execution unit we are running on.
|
||||
@ -229,6 +231,28 @@ rte_get_next_lcore(unsigned i, int skip_master, int wrap)
|
||||
i<RTE_MAX_LCORE; \
|
||||
i = rte_get_next_lcore(i, 1, 0))
|
||||
|
||||
/**
|
||||
* Set core affinity of the current thread.
|
||||
* Support both EAL and non-EAL thread and update TLS.
|
||||
*
|
||||
* @param cpusetp
|
||||
* Point to cpu_set_t for setting current thread affinity.
|
||||
* @return
|
||||
* On success, return 0; otherwise return -1;
|
||||
*/
|
||||
int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
|
||||
|
||||
/**
|
||||
* Get core affinity of the current thread.
|
||||
*
|
||||
* @param cpusetp
|
||||
* Point to cpu_set_t for getting current thread cpu affinity.
|
||||
* It presumes input is not NULL, otherwise it causes panic.
|
||||
*
|
||||
*/
|
||||
void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -89,6 +89,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_hexdump.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_devargs.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_dev.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_options.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_thread.c
|
||||
|
||||
CFLAGS_eal.o := -D_GNU_SOURCE
|
||||
CFLAGS_eal_lcore.o := -D_GNU_SOURCE
|
||||
@ -100,6 +101,7 @@ CFLAGS_eal_pci.o := -D_GNU_SOURCE
|
||||
CFLAGS_eal_pci_vfio.o := -D_GNU_SOURCE
|
||||
CFLAGS_eal_common_whitelist.o := -D_GNU_SOURCE
|
||||
CFLAGS_eal_common_options.o := -D_GNU_SOURCE
|
||||
CFLAGS_eal_common_thread.o := -D_GNU_SOURCE
|
||||
|
||||
# workaround for a gcc bug with noreturn attribute
|
||||
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "eal_thread.h"
|
||||
|
||||
RTE_DEFINE_PER_LCORE(unsigned, _lcore_id);
|
||||
RTE_DEFINE_PER_LCORE(unsigned, _socket_id);
|
||||
RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset);
|
||||
|
||||
/*
|
||||
* Send a message to a slave lcore identified by slave_id to call a
|
||||
|
@ -83,6 +83,8 @@ DPDK_2.0 {
|
||||
rte_snprintf;
|
||||
rte_strerror;
|
||||
rte_strsplit;
|
||||
rte_thread_get_affinity;
|
||||
rte_thread_set_affinity;
|
||||
rte_vlog;
|
||||
rte_xen_dom0_memory_attach;
|
||||
rte_xen_dom0_memory_init;
|
||||
|
Loading…
Reference in New Issue
Block a user