Commit 601bcbcf authored by Tomasz Kulasek's avatar Tomasz Kulasek Committed by Jim Harris
Browse files

util: extend cpumask to hold more than 64 cpus



Fixes github issue #218.

This patch introduces spdk_cpuset object to store and manipulate
the set of individual CPUs. The main objective of this object is
to replace cpumask declared as uint64_t and extend the limitation
of supported CPUs (lcores) above 64 CPUs.

spdk_cpuset is always allocated dynamically and accessed by opaque
pointer, what makes it easier to extend in the future without
breaking API/ABI.

This patch also extends parsing function allowing to set cpumask
using a list of cpus e.g. "[0-4,10,12]" sets mask of 0,1,2,3,4,10,12
as well as hexadecimal string with and without "0x" prefix.

Change-Id: I475c3ba7fab629021a22e03176e57e400dd24a49
Signed-off-by: default avatarTomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/390794


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 0ff878d0
Loading
Loading
Loading
Loading

include/spdk/cpuset.h

0 → 100644
+155 −0
Original line number Diff line number Diff line
/*-
 *   BSD LICENSE
 *
 *   Copyright (c) Intel Corporation.
 *   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.
 */

/**
 * \file
 * CPU set management functions
 */

#ifndef SPDK_CPUSET_H
#define SPDK_CPUSET_H

#include "spdk/stdinc.h"

#ifdef __cplusplus
extern "C" {
#endif

#define SPDK_CPUSET_SIZE 1024

/**
 * List of CPUs.
 */
struct spdk_cpuset;

/**
 * Allocate CPU set object.
 *
 * \return Allocated zeroed cpuset or NULL if fails.
 */
struct spdk_cpuset *spdk_cpuset_alloc(void);

/**
 * Free allocated CPU set.
 *
 * \param set CPU set to be freed.
 */
void spdk_cpuset_free(struct spdk_cpuset *set);

/**
 * Compare two CPU sets.
 *
 * \return True if both CPU sets are equal.
 */
bool spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2);

/**
 * Copy the content of CPU set to another.
 *
 * \param dst Destination CPU set
 * \param src Source CPU set
 */
void spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src);

/**
 * Perform AND operation on two CPU sets. The result is stored in dst.
 *
 * \param dst First argument of operation. This value also stores the result of operation.
 * \param src Second argument of operation.
 */
void spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src);

/**
 * Perform OR operation on two CPU sets. The result is stored in dst.
 *
 * \param dst First argument of operation. This value also stores the result of operation.
 * \param src Second argument of operation.
 */
void spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src);

/**
 * Clear all CPUs in CPU set.
 *
 * \param set CPU set to be cleared.
 */
void spdk_cpuset_zero(struct spdk_cpuset *set);

/**
 * Set or clear CPU state in CPU set.
 *
 * \param set CPU set object.
 * \param cpu CPU index to be set or cleared.
 * \param state *true* to set cpu, *false* to clear.
 */
void spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state);

/**
 * Get the state of CPU in CPU set.
 *
 * \param set CPU set object.
 * \param cpu CPU index.
 * \return State of selected CPU.
 */
bool spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu);

/**
 * Get the number of CPUs that are set in CPU set.
 *
 * \param set CPU set object.
 * \return Number of CPUs.
 */
uint32_t spdk_cpuset_count(const struct spdk_cpuset *set);

/**
 * Convert a CPU set to hex string.
 *
 * \param CPU set.
 * \return Pointer to hexadecimal representation of CPU set. Buffer to store a
 * string is dynamically allocated internally and freed with CPU set object.
 */
char *spdk_cpuset_fmt(struct spdk_cpuset *set);

/**
 * Convert a string containing a CPU core mask into a CPU set.
 *
 * \param set
 * \param mask String defining CPU set. By default hexadecimal value is used or
 * as CPU list enclosed in square brackets defined as: 'c1[-c2][,c3[-c4],...]'
 * \return Zero if success, non zero if fails.
 */
int spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask);

#ifdef __cplusplus
}
#endif
#endif /* SPDK_CPUSET_H */
+3 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@

#include "spdk/stdinc.h"

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

@@ -140,12 +141,12 @@ int spdk_app_get_shm_id(void);
/**
 * \brief Convert a string containing a CPU core mask into a bitmask
 */
int spdk_app_parse_core_mask(const char *mask, uint64_t *cpumask);
int spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask);

/**
 * \brief Return a mask of the CPU cores active for this application
 */
uint64_t spdk_app_get_core_mask(void);
struct spdk_cpuset *spdk_app_get_core_mask(void);

/**
 * \brief Return the number of CPU cores utilized by this application
+5 −5
Original line number Diff line number Diff line
@@ -100,15 +100,15 @@ typedef int (*spdk_vhost_event_fn)(struct spdk_vhost_dev *vdev, void *arg);
const char *spdk_vhost_dev_get_name(struct spdk_vhost_dev *vdev);

/**
 * Get cpumask of the vhost device.  The mask is constant
 * Get cpuset of the vhost device.  The cpuset is constant
 * throughout the lifetime of a vdev. It is be a subset
 * of SPDK app cpumask vhost was started with.
 * of SPDK app cpuset vhost was started with.
 *
 * \param dev vhost device
 * \return cpumask of the vdev. The mask is constructed as:
 * ((1 << cpu0) | (1 << cpu1) | ... | (1 << cpuN)).
 * \param cpuset pointer to the cpuset of the vdev.
 */
uint64_t spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *vdev);
void spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *vdev,
				struct spdk_cpuset *cpuset);

/**
 * By default, events are generated when asked, but for high queue depth and
+13 −1
Original line number Diff line number Diff line
@@ -190,7 +190,19 @@ spdk_build_eal_cmdline(const struct spdk_env_opts *opts)
	}

	/* set the coremask */
	/* NOTE: If coremask starts with '[' and ends with ']' it is a core list
	 */
	if (opts->core_mask[0] == '[') {
		char *l_arg = _sprintf_alloc("-l %s", opts->core_mask + 1);
		int len = strlen(l_arg);
		if (l_arg[len - 1] == ']') {
			l_arg[len - 1] = '\0';
		}
		args = spdk_push_arg(args, &argcount, l_arg);
	} else {
		args = spdk_push_arg(args, &argcount, _sprintf_alloc("-c %s", opts->core_mask));
	}

	if (args == NULL) {
		return -1;
	}
+7 −3
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ spdk_app_get_shm_id(void)
"  #  specifying a ReactorMask.  Default is to allow work items to run\n" \
"  #  on all cores.  Core 0 must be set in the mask if one is specified.\n" \
"  # Default: 0xFFFF (cores 0-15)\n" \
"  ReactorMask \"0x%" PRIX64 "\"\n" \
"  ReactorMask \"0x%s\"\n" \
"\n" \
"  # Tracepoint group mask for spdk trace buffers\n" \
"  # Default: 0x0 (all tracepoint groups disabled)\n" \
@@ -102,12 +102,16 @@ spdk_app_get_shm_id(void)
static void
spdk_app_config_dump_global_section(FILE *fp)
{
	struct spdk_cpuset *coremask;

	if (NULL == fp) {
		return;
	}

	fprintf(fp, GLOBAL_CONFIG_TMPL,
		spdk_app_get_core_mask(), spdk_trace_get_tpoint_group_mask());
	coremask = spdk_app_get_core_mask();

	fprintf(fp, GLOBAL_CONFIG_TMPL, spdk_cpuset_fmt(coremask),
		spdk_trace_get_tpoint_group_mask());
}

int
Loading