Commit f838343c authored by Jim Harris's avatar Jim Harris Committed by Tomasz Zawadzki
Browse files

env: add spdk_env_core_get_smt_cpuset



This create a cpuset with core bits set for the specified core and
any of its SMT siblings.

If the core has siblings, then all of its siblings will be set, even
those that are not part of the application's core mask.

If the specified core is UINT32_MAX, then bits will be set for all
SMT siblings of all cores in the application's core mask.

Signed-off-by: default avatarJim Harris <jim.harris@samsung.com>
Change-Id: I6e9677414fd3039089c4faec3464cf135a70a6ce
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/23406


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarKrzysztof Karas <krzysztof.karas@intel.com>
parent b554eaea
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -21,6 +21,11 @@ New function `spdk_fd_group_add_for_events()` was added alongside the existing `
Difference is that new API allows for specifying a set of events to be monitored instead of default
SPDK_INTERRUPT_EVENT_IN.

### env

Added `spdk_env_core_get_smt_cpuset()` API to get the list of SMT sibling
cores for a given core ID.

### nvmf

Added public API 'spdk_nvmf_subsystem_set_cntlid_range' to set controller ID
+24 −0
Original line number Diff line number Diff line
@@ -513,6 +513,30 @@ struct spdk_cpuset;
 */
void spdk_env_get_cpuset(struct spdk_cpuset *cpuset);

/**
 * Create a cpuset with each SMT sibling core's bit set to true.
 *
 * This function will first zero the cpuset and then set the bit for each
 * SMT sibling core to true.
 *
 * If the specified core has no SMT siblings, then only the specified
 * core's bit will be set.
 *
 * If the specified core has SMT siblings, then all of the siblings, including
 * the specified core, will be set. Note: this will set bits for all siblings,
 * even ones not part of the application's core mask.
 *
 * If the specified core is UINT32_MAX, then bits will be set for all SMT
 * siblings of all cores in the application's core mask.
 *
 * \param cpuset spdk_cpuset for SMT sibling cores
 * \param core core to get siblings for (UINT32_MAX for all cores in app
 *             core mask)
 * \return true if environment supports SMT detection, false otherwise (in
 *         which case the spdk_cpuset will be invalid)
 */
bool spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core);

typedef int (*thread_start_fn)(void *);

/**
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
	spdk_env_get_next_core;
	spdk_env_get_socket_id;
	spdk_env_get_cpuset;
	spdk_env_core_get_smt_cpuset;
	spdk_env_thread_launch_pinned;
	spdk_env_thread_wait_all;
	spdk_process_is_primary;
+67 −0
Original line number Diff line number Diff line
@@ -9,6 +9,11 @@
#include <rte_lcore.h>

#include "spdk/cpuset.h"
#include "spdk/log.h"
#include "spdk/string.h"

#define THREAD_SIBLINGS_FILE \
	"/sys/devices/system/cpu/cpu%d/topology/thread_siblings"

uint32_t
spdk_env_get_core_count(void)
@@ -82,6 +87,68 @@ spdk_env_get_cpuset(struct spdk_cpuset *cpuset)
	}
}

static bool
env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
{
#ifdef __linux__
	struct spdk_cpuset smt_siblings;
	char path[PATH_MAX];
	FILE *f;
	char *line = NULL;
	size_t len = 0;
	ssize_t read;
	bool valid = false;

	snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core);
	f = fopen(path, "r");
	if (f == NULL) {
		SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno));
		return false;
	}
	read = getline(&line, &len, f);
	if (read == -1) {
		SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno));
		goto ret;
	}

	/* Remove trailing newline */
	line[strlen(line) - 1] = 0;
	if (spdk_cpuset_parse(&smt_siblings, line)) {
		SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path);
		goto ret;
	}

	valid = true;
	spdk_cpuset_or(cpuset, &smt_siblings);
ret:
	free(line);
	fclose(f);
	return valid;
#else
	return false;
#endif
}

bool
spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
{
	uint32_t i;

	spdk_cpuset_zero(cpuset);

	if (core != UINT32_MAX) {
		return env_core_get_smt_cpuset(cpuset, core);
	}

	SPDK_ENV_FOREACH_CORE(i) {
		if (!env_core_get_smt_cpuset(cpuset, i)) {
			return false;
		}
	}

	return true;
}

int
spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg)
{