xref: /dpdk/lib/eal/common/eal_common_lcore.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
59ab18049SRobin Jarry #include <inttypes.h>
672b452c5SDmitry Kozlyuk #include <stdlib.h>
799a2dd95SBruce Richardson #include <string.h>
899a2dd95SBruce Richardson 
999a2dd95SBruce Richardson #include <rte_common.h>
1030a1de10SSean Morrissey #include <rte_branch_prediction.h>
1199a2dd95SBruce Richardson #include <rte_errno.h>
1299a2dd95SBruce Richardson #include <rte_lcore.h>
1399a2dd95SBruce Richardson #include <rte_log.h>
14f2b852d9SRobin Jarry #ifndef RTE_EXEC_ENV_WINDOWS
15f2b852d9SRobin Jarry #include <rte_telemetry.h>
16f2b852d9SRobin Jarry #endif
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson #include "eal_private.h"
1999a2dd95SBruce Richardson #include "eal_thread.h"
2099a2dd95SBruce Richardson 
rte_get_main_lcore(void)2199a2dd95SBruce Richardson unsigned int rte_get_main_lcore(void)
2299a2dd95SBruce Richardson {
2399a2dd95SBruce Richardson 	return rte_eal_get_configuration()->main_lcore;
2499a2dd95SBruce Richardson }
2599a2dd95SBruce Richardson 
rte_lcore_count(void)2699a2dd95SBruce Richardson unsigned int rte_lcore_count(void)
2799a2dd95SBruce Richardson {
2899a2dd95SBruce Richardson 	return rte_eal_get_configuration()->lcore_count;
2999a2dd95SBruce Richardson }
3099a2dd95SBruce Richardson 
rte_lcore_index(int lcore_id)3199a2dd95SBruce Richardson int rte_lcore_index(int lcore_id)
3299a2dd95SBruce Richardson {
3399a2dd95SBruce Richardson 	if (unlikely(lcore_id >= RTE_MAX_LCORE))
3499a2dd95SBruce Richardson 		return -1;
3599a2dd95SBruce Richardson 
3699a2dd95SBruce Richardson 	if (lcore_id < 0) {
3799a2dd95SBruce Richardson 		if (rte_lcore_id() == LCORE_ID_ANY)
3899a2dd95SBruce Richardson 			return -1;
3999a2dd95SBruce Richardson 
4099a2dd95SBruce Richardson 		lcore_id = (int)rte_lcore_id();
4199a2dd95SBruce Richardson 	}
4299a2dd95SBruce Richardson 
4399a2dd95SBruce Richardson 	return lcore_config[lcore_id].core_index;
4499a2dd95SBruce Richardson }
4599a2dd95SBruce Richardson 
rte_lcore_to_cpu_id(int lcore_id)4699a2dd95SBruce Richardson int rte_lcore_to_cpu_id(int lcore_id)
4799a2dd95SBruce Richardson {
4899a2dd95SBruce Richardson 	if (unlikely(lcore_id >= RTE_MAX_LCORE))
4999a2dd95SBruce Richardson 		return -1;
5099a2dd95SBruce Richardson 
5199a2dd95SBruce Richardson 	if (lcore_id < 0) {
5299a2dd95SBruce Richardson 		if (rte_lcore_id() == LCORE_ID_ANY)
5399a2dd95SBruce Richardson 			return -1;
5499a2dd95SBruce Richardson 
5599a2dd95SBruce Richardson 		lcore_id = (int)rte_lcore_id();
5699a2dd95SBruce Richardson 	}
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson 	return lcore_config[lcore_id].core_id;
5999a2dd95SBruce Richardson }
6099a2dd95SBruce Richardson 
rte_lcore_cpuset(unsigned int lcore_id)6199a2dd95SBruce Richardson rte_cpuset_t rte_lcore_cpuset(unsigned int lcore_id)
6299a2dd95SBruce Richardson {
6399a2dd95SBruce Richardson 	return lcore_config[lcore_id].cpuset;
6499a2dd95SBruce Richardson }
6599a2dd95SBruce Richardson 
6699a2dd95SBruce Richardson enum rte_lcore_role_t
rte_eal_lcore_role(unsigned int lcore_id)6799a2dd95SBruce Richardson rte_eal_lcore_role(unsigned int lcore_id)
6899a2dd95SBruce Richardson {
6999a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson 	if (lcore_id >= RTE_MAX_LCORE)
7299a2dd95SBruce Richardson 		return ROLE_OFF;
7399a2dd95SBruce Richardson 	return cfg->lcore_role[lcore_id];
7499a2dd95SBruce Richardson }
7599a2dd95SBruce Richardson 
7699a2dd95SBruce Richardson int
rte_lcore_has_role(unsigned int lcore_id,enum rte_lcore_role_t role)7799a2dd95SBruce Richardson rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role)
7899a2dd95SBruce Richardson {
7999a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
8099a2dd95SBruce Richardson 
8199a2dd95SBruce Richardson 	if (lcore_id >= RTE_MAX_LCORE)
8299a2dd95SBruce Richardson 		return -EINVAL;
8399a2dd95SBruce Richardson 
8499a2dd95SBruce Richardson 	return cfg->lcore_role[lcore_id] == role;
8599a2dd95SBruce Richardson }
8699a2dd95SBruce Richardson 
rte_lcore_is_enabled(unsigned int lcore_id)8799a2dd95SBruce Richardson int rte_lcore_is_enabled(unsigned int lcore_id)
8899a2dd95SBruce Richardson {
8999a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
9099a2dd95SBruce Richardson 
9199a2dd95SBruce Richardson 	if (lcore_id >= RTE_MAX_LCORE)
9299a2dd95SBruce Richardson 		return 0;
9399a2dd95SBruce Richardson 	return cfg->lcore_role[lcore_id] == ROLE_RTE;
9499a2dd95SBruce Richardson }
9599a2dd95SBruce Richardson 
rte_get_next_lcore(unsigned int i,int skip_main,int wrap)9699a2dd95SBruce Richardson unsigned int rte_get_next_lcore(unsigned int i, int skip_main, int wrap)
9799a2dd95SBruce Richardson {
9899a2dd95SBruce Richardson 	i++;
9999a2dd95SBruce Richardson 	if (wrap)
10099a2dd95SBruce Richardson 		i %= RTE_MAX_LCORE;
10199a2dd95SBruce Richardson 
10299a2dd95SBruce Richardson 	while (i < RTE_MAX_LCORE) {
10399a2dd95SBruce Richardson 		if (!rte_lcore_is_enabled(i) ||
10499a2dd95SBruce Richardson 		    (skip_main && (i == rte_get_main_lcore()))) {
10599a2dd95SBruce Richardson 			i++;
10699a2dd95SBruce Richardson 			if (wrap)
10799a2dd95SBruce Richardson 				i %= RTE_MAX_LCORE;
10899a2dd95SBruce Richardson 			continue;
10999a2dd95SBruce Richardson 		}
11099a2dd95SBruce Richardson 		break;
11199a2dd95SBruce Richardson 	}
11299a2dd95SBruce Richardson 	return i;
11399a2dd95SBruce Richardson }
11499a2dd95SBruce Richardson 
11599a2dd95SBruce Richardson unsigned int
rte_lcore_to_socket_id(unsigned int lcore_id)11699a2dd95SBruce Richardson rte_lcore_to_socket_id(unsigned int lcore_id)
11799a2dd95SBruce Richardson {
11899a2dd95SBruce Richardson 	return lcore_config[lcore_id].socket_id;
11999a2dd95SBruce Richardson }
12099a2dd95SBruce Richardson 
12199a2dd95SBruce Richardson static int
socket_id_cmp(const void * a,const void * b)12299a2dd95SBruce Richardson socket_id_cmp(const void *a, const void *b)
12399a2dd95SBruce Richardson {
12499a2dd95SBruce Richardson 	const int *lcore_id_a = a;
12599a2dd95SBruce Richardson 	const int *lcore_id_b = b;
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson 	if (*lcore_id_a < *lcore_id_b)
12899a2dd95SBruce Richardson 		return -1;
12999a2dd95SBruce Richardson 	if (*lcore_id_a > *lcore_id_b)
13099a2dd95SBruce Richardson 		return 1;
13199a2dd95SBruce Richardson 	return 0;
13299a2dd95SBruce Richardson }
13399a2dd95SBruce Richardson 
13499a2dd95SBruce Richardson /*
13599a2dd95SBruce Richardson  * Parse /sys/devices/system/cpu to get the number of physical and logical
13699a2dd95SBruce Richardson  * processors on the machine. The function will fill the cpu_info
13799a2dd95SBruce Richardson  * structure.
13899a2dd95SBruce Richardson  */
13999a2dd95SBruce Richardson int
rte_eal_cpu_init(void)14099a2dd95SBruce Richardson rte_eal_cpu_init(void)
14199a2dd95SBruce Richardson {
14299a2dd95SBruce Richardson 	/* pointer to global configuration */
14399a2dd95SBruce Richardson 	struct rte_config *config = rte_eal_get_configuration();
14499a2dd95SBruce Richardson 	unsigned lcore_id;
14599a2dd95SBruce Richardson 	unsigned count = 0;
14699a2dd95SBruce Richardson 	unsigned int socket_id, prev_socket_id;
14799a2dd95SBruce Richardson 	int lcore_to_socket_id[RTE_MAX_LCORE];
14899a2dd95SBruce Richardson 
14999a2dd95SBruce Richardson 	/*
15099a2dd95SBruce Richardson 	 * Parse the maximum set of logical cores, detect the subset of running
15199a2dd95SBruce Richardson 	 * ones and enable them by default.
15299a2dd95SBruce Richardson 	 */
15399a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
15499a2dd95SBruce Richardson 		lcore_config[lcore_id].core_index = count;
15599a2dd95SBruce Richardson 
15699a2dd95SBruce Richardson 		/* init cpuset for per lcore config */
15799a2dd95SBruce Richardson 		CPU_ZERO(&lcore_config[lcore_id].cpuset);
15899a2dd95SBruce Richardson 
15999a2dd95SBruce Richardson 		/* find socket first */
16099a2dd95SBruce Richardson 		socket_id = eal_cpu_socket_id(lcore_id);
16199a2dd95SBruce Richardson 		lcore_to_socket_id[lcore_id] = socket_id;
16299a2dd95SBruce Richardson 
16399a2dd95SBruce Richardson 		if (eal_cpu_detected(lcore_id) == 0) {
16499a2dd95SBruce Richardson 			config->lcore_role[lcore_id] = ROLE_OFF;
16599a2dd95SBruce Richardson 			lcore_config[lcore_id].core_index = -1;
16699a2dd95SBruce Richardson 			continue;
16799a2dd95SBruce Richardson 		}
16899a2dd95SBruce Richardson 
16999a2dd95SBruce Richardson 		/* By default, lcore 1:1 map to cpu id */
17099a2dd95SBruce Richardson 		CPU_SET(lcore_id, &lcore_config[lcore_id].cpuset);
17199a2dd95SBruce Richardson 
17299a2dd95SBruce Richardson 		/* By default, each detected core is enabled */
17399a2dd95SBruce Richardson 		config->lcore_role[lcore_id] = ROLE_RTE;
17499a2dd95SBruce Richardson 		lcore_config[lcore_id].core_role = ROLE_RTE;
17599a2dd95SBruce Richardson 		lcore_config[lcore_id].core_id = eal_cpu_core_id(lcore_id);
17699a2dd95SBruce Richardson 		lcore_config[lcore_id].socket_id = socket_id;
177*ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Detected lcore %u as "
178*ae67895bSDavid Marchand 				"core %u on socket %u",
17999a2dd95SBruce Richardson 				lcore_id, lcore_config[lcore_id].core_id,
18099a2dd95SBruce Richardson 				lcore_config[lcore_id].socket_id);
18199a2dd95SBruce Richardson 		count++;
18299a2dd95SBruce Richardson 	}
18399a2dd95SBruce Richardson 	for (; lcore_id < CPU_SETSIZE; lcore_id++) {
18499a2dd95SBruce Richardson 		if (eal_cpu_detected(lcore_id) == 0)
18599a2dd95SBruce Richardson 			continue;
186*ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Skipped lcore %u as core %u on socket %u",
18799a2dd95SBruce Richardson 			lcore_id, eal_cpu_core_id(lcore_id),
18899a2dd95SBruce Richardson 			eal_cpu_socket_id(lcore_id));
18999a2dd95SBruce Richardson 	}
19099a2dd95SBruce Richardson 
19199a2dd95SBruce Richardson 	/* Set the count of enabled logical cores of the EAL configuration */
19299a2dd95SBruce Richardson 	config->lcore_count = count;
193*ae67895bSDavid Marchand 	EAL_LOG(DEBUG,
194*ae67895bSDavid Marchand 			"Maximum logical cores by configuration: %u",
19599a2dd95SBruce Richardson 			RTE_MAX_LCORE);
196*ae67895bSDavid Marchand 	EAL_LOG(INFO, "Detected CPU lcores: %u", config->lcore_count);
19799a2dd95SBruce Richardson 
19899a2dd95SBruce Richardson 	/* sort all socket id's in ascending order */
19999a2dd95SBruce Richardson 	qsort(lcore_to_socket_id, RTE_DIM(lcore_to_socket_id),
20099a2dd95SBruce Richardson 			sizeof(lcore_to_socket_id[0]), socket_id_cmp);
20199a2dd95SBruce Richardson 
20299a2dd95SBruce Richardson 	prev_socket_id = -1;
20399a2dd95SBruce Richardson 	config->numa_node_count = 0;
20499a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
20599a2dd95SBruce Richardson 		socket_id = lcore_to_socket_id[lcore_id];
20699a2dd95SBruce Richardson 		if (socket_id != prev_socket_id)
20799a2dd95SBruce Richardson 			config->numa_nodes[config->numa_node_count++] =
20899a2dd95SBruce Richardson 					socket_id;
20999a2dd95SBruce Richardson 		prev_socket_id = socket_id;
21099a2dd95SBruce Richardson 	}
211*ae67895bSDavid Marchand 	EAL_LOG(INFO, "Detected NUMA nodes: %u", config->numa_node_count);
21299a2dd95SBruce Richardson 
21399a2dd95SBruce Richardson 	return 0;
21499a2dd95SBruce Richardson }
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson unsigned int
rte_socket_count(void)21799a2dd95SBruce Richardson rte_socket_count(void)
21899a2dd95SBruce Richardson {
21999a2dd95SBruce Richardson 	const struct rte_config *config = rte_eal_get_configuration();
22099a2dd95SBruce Richardson 	return config->numa_node_count;
22199a2dd95SBruce Richardson }
22299a2dd95SBruce Richardson 
22399a2dd95SBruce Richardson int
rte_socket_id_by_idx(unsigned int idx)22499a2dd95SBruce Richardson rte_socket_id_by_idx(unsigned int idx)
22599a2dd95SBruce Richardson {
22699a2dd95SBruce Richardson 	const struct rte_config *config = rte_eal_get_configuration();
22799a2dd95SBruce Richardson 	if (idx >= config->numa_node_count) {
22899a2dd95SBruce Richardson 		rte_errno = EINVAL;
22999a2dd95SBruce Richardson 		return -1;
23099a2dd95SBruce Richardson 	}
23199a2dd95SBruce Richardson 	return config->numa_nodes[idx];
23299a2dd95SBruce Richardson }
23399a2dd95SBruce Richardson 
23499a2dd95SBruce Richardson static rte_rwlock_t lcore_lock = RTE_RWLOCK_INITIALIZER;
23599a2dd95SBruce Richardson struct lcore_callback {
23699a2dd95SBruce Richardson 	TAILQ_ENTRY(lcore_callback) next;
23799a2dd95SBruce Richardson 	char *name;
23899a2dd95SBruce Richardson 	rte_lcore_init_cb init;
23999a2dd95SBruce Richardson 	rte_lcore_uninit_cb uninit;
24099a2dd95SBruce Richardson 	void *arg;
24199a2dd95SBruce Richardson };
24299a2dd95SBruce Richardson static TAILQ_HEAD(lcore_callbacks_head, lcore_callback) lcore_callbacks =
24399a2dd95SBruce Richardson 	TAILQ_HEAD_INITIALIZER(lcore_callbacks);
24499a2dd95SBruce Richardson 
24599a2dd95SBruce Richardson static int
callback_init(struct lcore_callback * callback,unsigned int lcore_id)24699a2dd95SBruce Richardson callback_init(struct lcore_callback *callback, unsigned int lcore_id)
24799a2dd95SBruce Richardson {
24899a2dd95SBruce Richardson 	if (callback->init == NULL)
24999a2dd95SBruce Richardson 		return 0;
250*ae67895bSDavid Marchand 	EAL_LOG(DEBUG, "Call init for lcore callback %s, lcore_id %u",
25199a2dd95SBruce Richardson 		callback->name, lcore_id);
25299a2dd95SBruce Richardson 	return callback->init(lcore_id, callback->arg);
25399a2dd95SBruce Richardson }
25499a2dd95SBruce Richardson 
25599a2dd95SBruce Richardson static void
callback_uninit(struct lcore_callback * callback,unsigned int lcore_id)25699a2dd95SBruce Richardson callback_uninit(struct lcore_callback *callback, unsigned int lcore_id)
25799a2dd95SBruce Richardson {
25899a2dd95SBruce Richardson 	if (callback->uninit == NULL)
25999a2dd95SBruce Richardson 		return;
260*ae67895bSDavid Marchand 	EAL_LOG(DEBUG, "Call uninit for lcore callback %s, lcore_id %u",
26199a2dd95SBruce Richardson 		callback->name, lcore_id);
26299a2dd95SBruce Richardson 	callback->uninit(lcore_id, callback->arg);
26399a2dd95SBruce Richardson }
26499a2dd95SBruce Richardson 
26599a2dd95SBruce Richardson static void
free_callback(struct lcore_callback * callback)26699a2dd95SBruce Richardson free_callback(struct lcore_callback *callback)
26799a2dd95SBruce Richardson {
26899a2dd95SBruce Richardson 	free(callback->name);
26999a2dd95SBruce Richardson 	free(callback);
27099a2dd95SBruce Richardson }
27199a2dd95SBruce Richardson 
27299a2dd95SBruce Richardson void *
rte_lcore_callback_register(const char * name,rte_lcore_init_cb init,rte_lcore_uninit_cb uninit,void * arg)27399a2dd95SBruce Richardson rte_lcore_callback_register(const char *name, rte_lcore_init_cb init,
27499a2dd95SBruce Richardson 	rte_lcore_uninit_cb uninit, void *arg)
27599a2dd95SBruce Richardson {
27699a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
27799a2dd95SBruce Richardson 	struct lcore_callback *callback;
27899a2dd95SBruce Richardson 	unsigned int lcore_id;
27999a2dd95SBruce Richardson 
28099a2dd95SBruce Richardson 	if (name == NULL)
28199a2dd95SBruce Richardson 		return NULL;
28299a2dd95SBruce Richardson 	callback = calloc(1, sizeof(*callback));
28399a2dd95SBruce Richardson 	if (callback == NULL)
28499a2dd95SBruce Richardson 		return NULL;
28599a2dd95SBruce Richardson 	if (asprintf(&callback->name, "%s-%p", name, arg) == -1) {
28699a2dd95SBruce Richardson 		free(callback);
28799a2dd95SBruce Richardson 		return NULL;
28899a2dd95SBruce Richardson 	}
28999a2dd95SBruce Richardson 	callback->init = init;
29099a2dd95SBruce Richardson 	callback->uninit = uninit;
29199a2dd95SBruce Richardson 	callback->arg = arg;
29299a2dd95SBruce Richardson 	rte_rwlock_write_lock(&lcore_lock);
29399a2dd95SBruce Richardson 	if (callback->init == NULL)
29499a2dd95SBruce Richardson 		goto no_init;
29599a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
29699a2dd95SBruce Richardson 		if (cfg->lcore_role[lcore_id] == ROLE_OFF)
29799a2dd95SBruce Richardson 			continue;
29899a2dd95SBruce Richardson 		if (callback_init(callback, lcore_id) == 0)
29999a2dd95SBruce Richardson 			continue;
30099a2dd95SBruce Richardson 		/* Callback refused init for this lcore, uninitialize all
30199a2dd95SBruce Richardson 		 * previous lcore.
30299a2dd95SBruce Richardson 		 */
30399a2dd95SBruce Richardson 		while (lcore_id-- != 0) {
30499a2dd95SBruce Richardson 			if (cfg->lcore_role[lcore_id] == ROLE_OFF)
30599a2dd95SBruce Richardson 				continue;
30699a2dd95SBruce Richardson 			callback_uninit(callback, lcore_id);
30799a2dd95SBruce Richardson 		}
30899a2dd95SBruce Richardson 		free_callback(callback);
30999a2dd95SBruce Richardson 		callback = NULL;
31099a2dd95SBruce Richardson 		goto out;
31199a2dd95SBruce Richardson 	}
31299a2dd95SBruce Richardson no_init:
31399a2dd95SBruce Richardson 	TAILQ_INSERT_TAIL(&lcore_callbacks, callback, next);
314*ae67895bSDavid Marchand 	EAL_LOG(DEBUG, "Registered new lcore callback %s (%sinit, %suninit).",
31599a2dd95SBruce Richardson 		callback->name, callback->init == NULL ? "NO " : "",
31699a2dd95SBruce Richardson 		callback->uninit == NULL ? "NO " : "");
31799a2dd95SBruce Richardson out:
31899a2dd95SBruce Richardson 	rte_rwlock_write_unlock(&lcore_lock);
31999a2dd95SBruce Richardson 	return callback;
32099a2dd95SBruce Richardson }
32199a2dd95SBruce Richardson 
32299a2dd95SBruce Richardson void
rte_lcore_callback_unregister(void * handle)32399a2dd95SBruce Richardson rte_lcore_callback_unregister(void *handle)
32499a2dd95SBruce Richardson {
32599a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
32699a2dd95SBruce Richardson 	struct lcore_callback *callback = handle;
32799a2dd95SBruce Richardson 	unsigned int lcore_id;
32899a2dd95SBruce Richardson 
32999a2dd95SBruce Richardson 	if (callback == NULL)
33099a2dd95SBruce Richardson 		return;
33199a2dd95SBruce Richardson 	rte_rwlock_write_lock(&lcore_lock);
33299a2dd95SBruce Richardson 	if (callback->uninit == NULL)
33399a2dd95SBruce Richardson 		goto no_uninit;
33499a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
33599a2dd95SBruce Richardson 		if (cfg->lcore_role[lcore_id] == ROLE_OFF)
33699a2dd95SBruce Richardson 			continue;
33799a2dd95SBruce Richardson 		callback_uninit(callback, lcore_id);
33899a2dd95SBruce Richardson 	}
33999a2dd95SBruce Richardson no_uninit:
34099a2dd95SBruce Richardson 	TAILQ_REMOVE(&lcore_callbacks, callback, next);
34199a2dd95SBruce Richardson 	rte_rwlock_write_unlock(&lcore_lock);
342*ae67895bSDavid Marchand 	EAL_LOG(DEBUG, "Unregistered lcore callback %s-%p.",
34399a2dd95SBruce Richardson 		callback->name, callback->arg);
34499a2dd95SBruce Richardson 	free_callback(callback);
34599a2dd95SBruce Richardson }
34699a2dd95SBruce Richardson 
34799a2dd95SBruce Richardson unsigned int
eal_lcore_non_eal_allocate(void)34899a2dd95SBruce Richardson eal_lcore_non_eal_allocate(void)
34999a2dd95SBruce Richardson {
35099a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
35199a2dd95SBruce Richardson 	struct lcore_callback *callback;
35299a2dd95SBruce Richardson 	struct lcore_callback *prev;
35399a2dd95SBruce Richardson 	unsigned int lcore_id;
35499a2dd95SBruce Richardson 
35599a2dd95SBruce Richardson 	rte_rwlock_write_lock(&lcore_lock);
35699a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
35799a2dd95SBruce Richardson 		if (cfg->lcore_role[lcore_id] != ROLE_OFF)
35899a2dd95SBruce Richardson 			continue;
35999a2dd95SBruce Richardson 		cfg->lcore_role[lcore_id] = ROLE_NON_EAL;
36099a2dd95SBruce Richardson 		cfg->lcore_count++;
36199a2dd95SBruce Richardson 		break;
36299a2dd95SBruce Richardson 	}
36399a2dd95SBruce Richardson 	if (lcore_id == RTE_MAX_LCORE) {
364*ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "No lcore available.");
36599a2dd95SBruce Richardson 		goto out;
36699a2dd95SBruce Richardson 	}
36799a2dd95SBruce Richardson 	TAILQ_FOREACH(callback, &lcore_callbacks, next) {
36899a2dd95SBruce Richardson 		if (callback_init(callback, lcore_id) == 0)
36999a2dd95SBruce Richardson 			continue;
37099a2dd95SBruce Richardson 		/* Callback refused init for this lcore, call uninit for all
37199a2dd95SBruce Richardson 		 * previous callbacks.
37299a2dd95SBruce Richardson 		 */
37399a2dd95SBruce Richardson 		prev = TAILQ_PREV(callback, lcore_callbacks_head, next);
37499a2dd95SBruce Richardson 		while (prev != NULL) {
37599a2dd95SBruce Richardson 			callback_uninit(prev, lcore_id);
37699a2dd95SBruce Richardson 			prev = TAILQ_PREV(prev, lcore_callbacks_head, next);
37799a2dd95SBruce Richardson 		}
378*ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Initialization refused for lcore %u.",
37999a2dd95SBruce Richardson 			lcore_id);
38099a2dd95SBruce Richardson 		cfg->lcore_role[lcore_id] = ROLE_OFF;
38199a2dd95SBruce Richardson 		cfg->lcore_count--;
38299a2dd95SBruce Richardson 		lcore_id = RTE_MAX_LCORE;
38399a2dd95SBruce Richardson 		goto out;
38499a2dd95SBruce Richardson 	}
38599a2dd95SBruce Richardson out:
38699a2dd95SBruce Richardson 	rte_rwlock_write_unlock(&lcore_lock);
38799a2dd95SBruce Richardson 	return lcore_id;
38899a2dd95SBruce Richardson }
38999a2dd95SBruce Richardson 
39099a2dd95SBruce Richardson void
eal_lcore_non_eal_release(unsigned int lcore_id)39199a2dd95SBruce Richardson eal_lcore_non_eal_release(unsigned int lcore_id)
39299a2dd95SBruce Richardson {
39399a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
39499a2dd95SBruce Richardson 	struct lcore_callback *callback;
39599a2dd95SBruce Richardson 
39699a2dd95SBruce Richardson 	rte_rwlock_write_lock(&lcore_lock);
39799a2dd95SBruce Richardson 	if (cfg->lcore_role[lcore_id] != ROLE_NON_EAL)
39899a2dd95SBruce Richardson 		goto out;
39999a2dd95SBruce Richardson 	TAILQ_FOREACH(callback, &lcore_callbacks, next)
40099a2dd95SBruce Richardson 		callback_uninit(callback, lcore_id);
40199a2dd95SBruce Richardson 	cfg->lcore_role[lcore_id] = ROLE_OFF;
40299a2dd95SBruce Richardson 	cfg->lcore_count--;
40399a2dd95SBruce Richardson out:
40499a2dd95SBruce Richardson 	rte_rwlock_write_unlock(&lcore_lock);
40599a2dd95SBruce Richardson }
40699a2dd95SBruce Richardson 
40799a2dd95SBruce Richardson int
rte_lcore_iterate(rte_lcore_iterate_cb cb,void * arg)40899a2dd95SBruce Richardson rte_lcore_iterate(rte_lcore_iterate_cb cb, void *arg)
40999a2dd95SBruce Richardson {
41099a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
41199a2dd95SBruce Richardson 	unsigned int lcore_id;
41299a2dd95SBruce Richardson 	int ret = 0;
41399a2dd95SBruce Richardson 
41499a2dd95SBruce Richardson 	rte_rwlock_read_lock(&lcore_lock);
41599a2dd95SBruce Richardson 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
41699a2dd95SBruce Richardson 		if (cfg->lcore_role[lcore_id] == ROLE_OFF)
41799a2dd95SBruce Richardson 			continue;
41899a2dd95SBruce Richardson 		ret = cb(lcore_id, arg);
41999a2dd95SBruce Richardson 		if (ret != 0)
42099a2dd95SBruce Richardson 			break;
42199a2dd95SBruce Richardson 	}
42299a2dd95SBruce Richardson 	rte_rwlock_read_unlock(&lcore_lock);
42399a2dd95SBruce Richardson 	return ret;
42499a2dd95SBruce Richardson }
42599a2dd95SBruce Richardson 
426f2b852d9SRobin Jarry static const char *
lcore_role_str(enum rte_lcore_role_t role)427f2b852d9SRobin Jarry lcore_role_str(enum rte_lcore_role_t role)
428f2b852d9SRobin Jarry {
429f2b852d9SRobin Jarry 	switch (role) {
430f2b852d9SRobin Jarry 	case ROLE_RTE:
431f2b852d9SRobin Jarry 		return "RTE";
432f2b852d9SRobin Jarry 	case ROLE_SERVICE:
433f2b852d9SRobin Jarry 		return "SERVICE";
434f2b852d9SRobin Jarry 	case ROLE_NON_EAL:
435f2b852d9SRobin Jarry 		return "NON_EAL";
436f2b852d9SRobin Jarry 	default:
437f2b852d9SRobin Jarry 		return "UNKNOWN";
438f2b852d9SRobin Jarry 	}
439f2b852d9SRobin Jarry }
440f2b852d9SRobin Jarry 
4419ab18049SRobin Jarry static rte_lcore_usage_cb lcore_usage_cb;
4429ab18049SRobin Jarry 
4439ab18049SRobin Jarry void
rte_lcore_register_usage_cb(rte_lcore_usage_cb cb)4449ab18049SRobin Jarry rte_lcore_register_usage_cb(rte_lcore_usage_cb cb)
4459ab18049SRobin Jarry {
4469ab18049SRobin Jarry 	lcore_usage_cb = cb;
4479ab18049SRobin Jarry }
4489ab18049SRobin Jarry 
449b1f0008fSChengwen Feng static float
calc_usage_ratio(const struct rte_lcore_usage * usage)450b1f0008fSChengwen Feng calc_usage_ratio(const struct rte_lcore_usage *usage)
451b1f0008fSChengwen Feng {
452b1f0008fSChengwen Feng 	return usage->total_cycles != 0 ?
453b1f0008fSChengwen Feng 		(usage->busy_cycles * 100.0) / usage->total_cycles : (float)0;
454b1f0008fSChengwen Feng }
455b1f0008fSChengwen Feng 
45699a2dd95SBruce Richardson static int
lcore_dump_cb(unsigned int lcore_id,void * arg)45799a2dd95SBruce Richardson lcore_dump_cb(unsigned int lcore_id, void *arg)
45899a2dd95SBruce Richardson {
45999a2dd95SBruce Richardson 	struct rte_config *cfg = rte_eal_get_configuration();
46099a2dd95SBruce Richardson 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
4619ab18049SRobin Jarry 	struct rte_lcore_usage usage;
4629ab18049SRobin Jarry 	rte_lcore_usage_cb usage_cb;
4639ab18049SRobin Jarry 	char *usage_str = NULL;
46499a2dd95SBruce Richardson 	FILE *f = arg;
46599a2dd95SBruce Richardson 	int ret;
46699a2dd95SBruce Richardson 
4679ab18049SRobin Jarry 	/* The callback may not set all the fields in the structure, so clear it here. */
4689ab18049SRobin Jarry 	memset(&usage, 0, sizeof(usage));
4699ab18049SRobin Jarry 	/* Guard against concurrent modification of lcore_usage_cb. */
4709ab18049SRobin Jarry 	usage_cb = lcore_usage_cb;
4719ab18049SRobin Jarry 	if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
472b1f0008fSChengwen Feng 		if (asprintf(&usage_str, ", busy cycles %"PRIu64"/%"PRIu64" (ratio %.02f%%)",
473b1f0008fSChengwen Feng 				usage.busy_cycles, usage.total_cycles,
474b1f0008fSChengwen Feng 				calc_usage_ratio(&usage)) < 0) {
4759ab18049SRobin Jarry 			return -ENOMEM;
4769ab18049SRobin Jarry 		}
4779ab18049SRobin Jarry 	}
47899a2dd95SBruce Richardson 	ret = eal_thread_dump_affinity(&lcore_config[lcore_id].cpuset, cpuset,
47999a2dd95SBruce Richardson 		sizeof(cpuset));
4809ab18049SRobin Jarry 	fprintf(f, "lcore %u, socket %u, role %s, cpuset %s%s%s\n", lcore_id,
481f2b852d9SRobin Jarry 		rte_lcore_to_socket_id(lcore_id),
482f2b852d9SRobin Jarry 		lcore_role_str(cfg->lcore_role[lcore_id]), cpuset,
4839ab18049SRobin Jarry 		ret == 0 ? "" : "...", usage_str != NULL ? usage_str : "");
4849ab18049SRobin Jarry 	free(usage_str);
4859ab18049SRobin Jarry 
48699a2dd95SBruce Richardson 	return 0;
48799a2dd95SBruce Richardson }
48899a2dd95SBruce Richardson 
48999a2dd95SBruce Richardson void
rte_lcore_dump(FILE * f)49099a2dd95SBruce Richardson rte_lcore_dump(FILE *f)
49199a2dd95SBruce Richardson {
49299a2dd95SBruce Richardson 	rte_lcore_iterate(lcore_dump_cb, f);
49399a2dd95SBruce Richardson }
494f2b852d9SRobin Jarry 
495f2b852d9SRobin Jarry #ifndef RTE_EXEC_ENV_WINDOWS
496f2b852d9SRobin Jarry static int
lcore_telemetry_id_cb(unsigned int lcore_id,void * arg)497f2b852d9SRobin Jarry lcore_telemetry_id_cb(unsigned int lcore_id, void *arg)
498f2b852d9SRobin Jarry {
499f2b852d9SRobin Jarry 	struct rte_tel_data *d = arg;
500f2b852d9SRobin Jarry 
501f2b852d9SRobin Jarry 	return rte_tel_data_add_array_int(d, lcore_id);
502f2b852d9SRobin Jarry }
503f2b852d9SRobin Jarry 
504f2b852d9SRobin Jarry static int
handle_lcore_list(const char * cmd __rte_unused,const char * params __rte_unused,struct rte_tel_data * d)505f2b852d9SRobin Jarry handle_lcore_list(const char *cmd __rte_unused, const char *params __rte_unused,
506f2b852d9SRobin Jarry 	struct rte_tel_data *d)
507f2b852d9SRobin Jarry {
508f2b852d9SRobin Jarry 	int ret;
509f2b852d9SRobin Jarry 
510f2b852d9SRobin Jarry 	ret = rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
511f2b852d9SRobin Jarry 	if (ret == 0)
512f2b852d9SRobin Jarry 		ret = rte_lcore_iterate(lcore_telemetry_id_cb, d);
513f2b852d9SRobin Jarry 
514f2b852d9SRobin Jarry 	return ret;
515f2b852d9SRobin Jarry }
516f2b852d9SRobin Jarry 
517f2b852d9SRobin Jarry struct lcore_telemetry_info {
518f2b852d9SRobin Jarry 	unsigned int lcore_id;
519f2b852d9SRobin Jarry 	struct rte_tel_data *d;
520f2b852d9SRobin Jarry };
521f2b852d9SRobin Jarry 
522b1f0008fSChengwen Feng static void
format_usage_ratio(char * buf,uint16_t size,const struct rte_lcore_usage * usage)523b1f0008fSChengwen Feng format_usage_ratio(char *buf, uint16_t size, const struct rte_lcore_usage *usage)
524b1f0008fSChengwen Feng {
525b1f0008fSChengwen Feng 	float ratio = calc_usage_ratio(usage);
526b1f0008fSChengwen Feng 	snprintf(buf, size, "%.02f%%", ratio);
527b1f0008fSChengwen Feng }
528b1f0008fSChengwen Feng 
529f2b852d9SRobin Jarry static int
lcore_telemetry_info_cb(unsigned int lcore_id,void * arg)530f2b852d9SRobin Jarry lcore_telemetry_info_cb(unsigned int lcore_id, void *arg)
531f2b852d9SRobin Jarry {
532f2b852d9SRobin Jarry 	struct rte_config *cfg = rte_eal_get_configuration();
533f2b852d9SRobin Jarry 	struct lcore_telemetry_info *info = arg;
534b1f0008fSChengwen Feng 	char ratio_str[RTE_TEL_MAX_STRING_LEN];
5359ab18049SRobin Jarry 	struct rte_lcore_usage usage;
536f2b852d9SRobin Jarry 	struct rte_tel_data *cpuset;
5379ab18049SRobin Jarry 	rte_lcore_usage_cb usage_cb;
538f2b852d9SRobin Jarry 	unsigned int cpu;
539f2b852d9SRobin Jarry 
540f2b852d9SRobin Jarry 	if (lcore_id != info->lcore_id)
541f2b852d9SRobin Jarry 		return 0;
542f2b852d9SRobin Jarry 
543f2b852d9SRobin Jarry 	rte_tel_data_start_dict(info->d);
544f2b852d9SRobin Jarry 	rte_tel_data_add_dict_int(info->d, "lcore_id", lcore_id);
545f2b852d9SRobin Jarry 	rte_tel_data_add_dict_int(info->d, "socket", rte_lcore_to_socket_id(lcore_id));
546f2b852d9SRobin Jarry 	rte_tel_data_add_dict_string(info->d, "role", lcore_role_str(cfg->lcore_role[lcore_id]));
547f2b852d9SRobin Jarry 	cpuset = rte_tel_data_alloc();
548f2b852d9SRobin Jarry 	if (cpuset == NULL)
549f2b852d9SRobin Jarry 		return -ENOMEM;
550f2b852d9SRobin Jarry 	rte_tel_data_start_array(cpuset, RTE_TEL_INT_VAL);
551f2b852d9SRobin Jarry 	for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
552f2b852d9SRobin Jarry 		if (CPU_ISSET(cpu, &lcore_config[lcore_id].cpuset))
553f2b852d9SRobin Jarry 			rte_tel_data_add_array_int(cpuset, cpu);
554f2b852d9SRobin Jarry 	}
555f2b852d9SRobin Jarry 	rte_tel_data_add_dict_container(info->d, "cpuset", cpuset, 0);
5569ab18049SRobin Jarry 	/* The callback may not set all the fields in the structure, so clear it here. */
5579ab18049SRobin Jarry 	memset(&usage, 0, sizeof(usage));
5589ab18049SRobin Jarry 	/* Guard against concurrent modification of lcore_usage_cb. */
5599ab18049SRobin Jarry 	usage_cb = lcore_usage_cb;
5609ab18049SRobin Jarry 	if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
5619ab18049SRobin Jarry 		rte_tel_data_add_dict_uint(info->d, "total_cycles", usage.total_cycles);
5629ab18049SRobin Jarry 		rte_tel_data_add_dict_uint(info->d, "busy_cycles", usage.busy_cycles);
563b1f0008fSChengwen Feng 		format_usage_ratio(ratio_str, sizeof(ratio_str), &usage);
564b1f0008fSChengwen Feng 		rte_tel_data_add_dict_string(info->d, "usage_ratio", ratio_str);
5659ab18049SRobin Jarry 	}
566f2b852d9SRobin Jarry 
567d07e7910SRuifeng Wang 	/* Return non-zero positive value to stop iterating over lcore_id. */
568d07e7910SRuifeng Wang 	return 1;
569f2b852d9SRobin Jarry }
570f2b852d9SRobin Jarry 
571f2b852d9SRobin Jarry static int
handle_lcore_info(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)572f2b852d9SRobin Jarry handle_lcore_info(const char *cmd __rte_unused, const char *params, struct rte_tel_data *d)
573f2b852d9SRobin Jarry {
574f2b852d9SRobin Jarry 	struct lcore_telemetry_info info = { .d = d };
575f2b852d9SRobin Jarry 	unsigned long lcore_id;
576f2b852d9SRobin Jarry 	char *endptr;
577f2b852d9SRobin Jarry 
578f2b852d9SRobin Jarry 	if (params == NULL)
579f2b852d9SRobin Jarry 		return -EINVAL;
580f2b852d9SRobin Jarry 	errno = 0;
581f2b852d9SRobin Jarry 	lcore_id = strtoul(params, &endptr, 10);
582f2b852d9SRobin Jarry 	if (errno)
583f2b852d9SRobin Jarry 		return -errno;
584f2b852d9SRobin Jarry 	if (*params == '\0' || *endptr != '\0' || lcore_id >= RTE_MAX_LCORE)
585f2b852d9SRobin Jarry 		return -EINVAL;
586f2b852d9SRobin Jarry 
587f2b852d9SRobin Jarry 	info.lcore_id = lcore_id;
588f2b852d9SRobin Jarry 
589f2b852d9SRobin Jarry 	return rte_lcore_iterate(lcore_telemetry_info_cb, &info);
590f2b852d9SRobin Jarry }
591f2b852d9SRobin Jarry 
59239d469a7SRobin Jarry struct lcore_telemetry_usage {
59339d469a7SRobin Jarry 	struct rte_tel_data *lcore_ids;
59439d469a7SRobin Jarry 	struct rte_tel_data *total_cycles;
59539d469a7SRobin Jarry 	struct rte_tel_data *busy_cycles;
596b1f0008fSChengwen Feng 	struct rte_tel_data *usage_ratio;
59739d469a7SRobin Jarry };
59839d469a7SRobin Jarry 
59939d469a7SRobin Jarry static int
lcore_telemetry_usage_cb(unsigned int lcore_id,void * arg)60039d469a7SRobin Jarry lcore_telemetry_usage_cb(unsigned int lcore_id, void *arg)
60139d469a7SRobin Jarry {
602b1f0008fSChengwen Feng 	char ratio_str[RTE_TEL_MAX_STRING_LEN];
60339d469a7SRobin Jarry 	struct lcore_telemetry_usage *u = arg;
60439d469a7SRobin Jarry 	struct rte_lcore_usage usage;
60539d469a7SRobin Jarry 	rte_lcore_usage_cb usage_cb;
60639d469a7SRobin Jarry 
60739d469a7SRobin Jarry 	/* The callback may not set all the fields in the structure, so clear it here. */
60839d469a7SRobin Jarry 	memset(&usage, 0, sizeof(usage));
60939d469a7SRobin Jarry 	/* Guard against concurrent modification of lcore_usage_cb. */
61039d469a7SRobin Jarry 	usage_cb = lcore_usage_cb;
61139d469a7SRobin Jarry 	if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
61239d469a7SRobin Jarry 		rte_tel_data_add_array_uint(u->lcore_ids, lcore_id);
61339d469a7SRobin Jarry 		rte_tel_data_add_array_uint(u->total_cycles, usage.total_cycles);
61439d469a7SRobin Jarry 		rte_tel_data_add_array_uint(u->busy_cycles, usage.busy_cycles);
615b1f0008fSChengwen Feng 		format_usage_ratio(ratio_str, sizeof(ratio_str), &usage);
616b1f0008fSChengwen Feng 		rte_tel_data_add_array_string(u->usage_ratio, ratio_str);
61739d469a7SRobin Jarry 	}
61839d469a7SRobin Jarry 
61939d469a7SRobin Jarry 	return 0;
62039d469a7SRobin Jarry }
62139d469a7SRobin Jarry 
62239d469a7SRobin Jarry static int
handle_lcore_usage(const char * cmd __rte_unused,const char * params __rte_unused,struct rte_tel_data * d)62339d469a7SRobin Jarry handle_lcore_usage(const char *cmd __rte_unused, const char *params __rte_unused,
62439d469a7SRobin Jarry 	struct rte_tel_data *d)
62539d469a7SRobin Jarry {
62639d469a7SRobin Jarry 	struct lcore_telemetry_usage usage;
62739d469a7SRobin Jarry 	struct rte_tel_data *total_cycles;
62839d469a7SRobin Jarry 	struct rte_tel_data *busy_cycles;
629b1f0008fSChengwen Feng 	struct rte_tel_data *usage_ratio;
63039d469a7SRobin Jarry 	struct rte_tel_data *lcore_ids;
63139d469a7SRobin Jarry 
63239d469a7SRobin Jarry 	lcore_ids = rte_tel_data_alloc();
63339d469a7SRobin Jarry 	total_cycles = rte_tel_data_alloc();
63439d469a7SRobin Jarry 	busy_cycles = rte_tel_data_alloc();
635b1f0008fSChengwen Feng 	usage_ratio = rte_tel_data_alloc();
636b1f0008fSChengwen Feng 	if (lcore_ids == NULL || total_cycles == NULL || busy_cycles == NULL ||
637b1f0008fSChengwen Feng 	    usage_ratio == NULL) {
63839d469a7SRobin Jarry 		rte_tel_data_free(lcore_ids);
63939d469a7SRobin Jarry 		rte_tel_data_free(total_cycles);
64039d469a7SRobin Jarry 		rte_tel_data_free(busy_cycles);
641b1f0008fSChengwen Feng 		rte_tel_data_free(usage_ratio);
64239d469a7SRobin Jarry 		return -ENOMEM;
64339d469a7SRobin Jarry 	}
64439d469a7SRobin Jarry 
64539d469a7SRobin Jarry 	rte_tel_data_start_dict(d);
64639d469a7SRobin Jarry 	rte_tel_data_start_array(lcore_ids, RTE_TEL_UINT_VAL);
64739d469a7SRobin Jarry 	rte_tel_data_start_array(total_cycles, RTE_TEL_UINT_VAL);
64839d469a7SRobin Jarry 	rte_tel_data_start_array(busy_cycles, RTE_TEL_UINT_VAL);
649b1f0008fSChengwen Feng 	rte_tel_data_start_array(usage_ratio, RTE_TEL_STRING_VAL);
65039d469a7SRobin Jarry 	rte_tel_data_add_dict_container(d, "lcore_ids", lcore_ids, 0);
65139d469a7SRobin Jarry 	rte_tel_data_add_dict_container(d, "total_cycles", total_cycles, 0);
65239d469a7SRobin Jarry 	rte_tel_data_add_dict_container(d, "busy_cycles", busy_cycles, 0);
653b1f0008fSChengwen Feng 	rte_tel_data_add_dict_container(d, "usage_ratio", usage_ratio, 0);
65439d469a7SRobin Jarry 	usage.lcore_ids = lcore_ids;
65539d469a7SRobin Jarry 	usage.total_cycles = total_cycles;
65639d469a7SRobin Jarry 	usage.busy_cycles = busy_cycles;
657b1f0008fSChengwen Feng 	usage.usage_ratio = usage_ratio;
65839d469a7SRobin Jarry 
65939d469a7SRobin Jarry 	return rte_lcore_iterate(lcore_telemetry_usage_cb, &usage);
66039d469a7SRobin Jarry }
66139d469a7SRobin Jarry 
RTE_INIT(lcore_telemetry)662f2b852d9SRobin Jarry RTE_INIT(lcore_telemetry)
663f2b852d9SRobin Jarry {
664f2b852d9SRobin Jarry 	rte_telemetry_register_cmd("/eal/lcore/list", handle_lcore_list,
665f2b852d9SRobin Jarry 		"List of lcore ids. Takes no parameters");
666f2b852d9SRobin Jarry 	rte_telemetry_register_cmd("/eal/lcore/info", handle_lcore_info,
667f2b852d9SRobin Jarry 		"Returns lcore info. Parameters: int lcore_id");
66839d469a7SRobin Jarry 	rte_telemetry_register_cmd("/eal/lcore/usage", handle_lcore_usage,
66939d469a7SRobin Jarry 		"Returns lcore cycles usage. Takes no parameters");
670f2b852d9SRobin Jarry }
671f2b852d9SRobin Jarry #endif /* !RTE_EXEC_ENV_WINDOWS */
672