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:
Cunming Liang 2015-02-17 10:08:03 +08:00 committed by Thomas Monjalon
parent ef76436c68
commit 9e29251b2a
9 changed files with 222 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View 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;
}

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;