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: Tomasz Kulasek <tomaszx.kulasek@intel.com> Reviewed-on: https://review.gerrithub.io/390794 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
0ff878d02e
commit
601bcbcf66
155
include/spdk/cpuset.h
Normal file
155
include/spdk/cpuset.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*-
|
||||
* 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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -190,7 +190,19 @@ spdk_build_eal_cmdline(const struct spdk_env_opts *opts)
|
||||
}
|
||||
|
||||
/* set the coremask */
|
||||
args = spdk_push_arg(args, &argcount, _sprintf_alloc("-c %s", opts->core_mask));
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -124,6 +124,8 @@ static void spdk_reactor_construct(struct spdk_reactor *w, uint32_t lcore,
|
||||
|
||||
static struct spdk_mempool *g_spdk_event_mempool[SPDK_MAX_SOCKET];
|
||||
|
||||
static struct spdk_cpuset *g_spdk_app_core_mask;
|
||||
|
||||
static struct spdk_reactor *
|
||||
spdk_reactor_get(uint32_t lcore)
|
||||
{
|
||||
@ -559,46 +561,26 @@ spdk_app_get_current_core(void)
|
||||
}
|
||||
|
||||
int
|
||||
spdk_app_parse_core_mask(const char *mask, uint64_t *cpumask)
|
||||
spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||
{
|
||||
uint32_t i;
|
||||
char *end;
|
||||
uint64_t validmask;
|
||||
int ret;
|
||||
struct spdk_cpuset *validmask;
|
||||
|
||||
if (mask == NULL || cpumask == NULL) {
|
||||
return -1;
|
||||
ret = spdk_cpuset_parse(cpumask, mask);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
*cpumask = strtoull(mask, &end, 16);
|
||||
if (*end != '\0' || errno) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
validmask = 0;
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
if (i >= 64) {
|
||||
break;
|
||||
}
|
||||
validmask |= 1ULL << i;
|
||||
}
|
||||
|
||||
*cpumask &= validmask;
|
||||
validmask = spdk_app_get_core_mask();
|
||||
spdk_cpuset_and(cpumask, validmask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
struct spdk_cpuset *
|
||||
spdk_app_get_core_mask(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t mask = 0;
|
||||
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
mask |= 1ULL << i;
|
||||
}
|
||||
|
||||
return mask;
|
||||
return g_spdk_app_core_mask;
|
||||
}
|
||||
|
||||
|
||||
@ -625,6 +607,7 @@ spdk_reactors_start(void)
|
||||
int rc;
|
||||
|
||||
g_reactor_state = SPDK_REACTOR_STATE_RUNNING;
|
||||
g_spdk_app_core_mask = spdk_cpuset_alloc();
|
||||
|
||||
current_core = spdk_env_get_current_core();
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
@ -637,6 +620,7 @@ spdk_reactors_start(void)
|
||||
return;
|
||||
}
|
||||
}
|
||||
spdk_cpuset_set_cpu(g_spdk_app_core_mask, i, true);
|
||||
}
|
||||
|
||||
/* Start the master reactor */
|
||||
@ -646,6 +630,8 @@ spdk_reactors_start(void)
|
||||
spdk_env_thread_wait_all();
|
||||
|
||||
g_reactor_state = SPDK_REACTOR_STATE_SHUTDOWN;
|
||||
spdk_cpuset_free(g_spdk_app_core_mask);
|
||||
g_spdk_app_core_mask = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -73,7 +73,7 @@ static pthread_mutex_t g_conns_mutex;
|
||||
|
||||
static struct spdk_poller *g_shutdown_timer = NULL;
|
||||
|
||||
static uint32_t spdk_iscsi_conn_allocate_reactor(uint64_t cpumask);
|
||||
static uint32_t spdk_iscsi_conn_allocate_reactor(const struct spdk_cpuset *cpumask);
|
||||
|
||||
void spdk_iscsi_conn_login_do_work(void *arg);
|
||||
void spdk_iscsi_conn_full_feature_do_work(void *arg);
|
||||
@ -1421,7 +1421,7 @@ spdk_iscsi_conn_get_min_per_core(void)
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
spdk_iscsi_conn_allocate_reactor(uint64_t cpumask)
|
||||
spdk_iscsi_conn_allocate_reactor(const struct spdk_cpuset *cpumask)
|
||||
{
|
||||
uint32_t i, selected_core;
|
||||
int32_t num_pollers, min_pollers;
|
||||
@ -1429,9 +1429,8 @@ spdk_iscsi_conn_allocate_reactor(uint64_t cpumask)
|
||||
min_pollers = INT_MAX;
|
||||
selected_core = spdk_env_get_first_core();
|
||||
|
||||
/* we use u64 as CPU core mask */
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
if (!((1ULL << i) & cpumask)) {
|
||||
if (!spdk_cpuset_get_cpu(cpumask, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "iscsi/iscsi.h"
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/cpuset.h"
|
||||
|
||||
/*
|
||||
* MAX_CONNECTION_PARAMS: The numbers of the params in conn_param_table
|
||||
@ -80,7 +81,7 @@ struct spdk_iscsi_conn {
|
||||
int pg_tag;
|
||||
char *portal_host;
|
||||
char *portal_port;
|
||||
uint64_t portal_cpumask;
|
||||
struct spdk_cpuset *portal_cpumask;
|
||||
uint32_t lcore;
|
||||
int sock;
|
||||
struct spdk_iscsi_sess *sess;
|
||||
|
@ -733,7 +733,7 @@ spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request,
|
||||
spdk_json_write_name(w, "port");
|
||||
spdk_json_write_string(w, portal->port);
|
||||
spdk_json_write_name(w, "cpumask");
|
||||
spdk_json_write_string_fmt(w, "%#" PRIx64, portal->cpumask);
|
||||
spdk_json_write_string_fmt(w, "0x%s", spdk_cpuset_fmt(portal->cpumask));
|
||||
spdk_json_write_object_end(w);
|
||||
}
|
||||
spdk_json_write_array_end(w);
|
||||
@ -838,7 +838,6 @@ spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request,
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < req.portal_list.num_portals; i++) {
|
||||
portal_list[i] = spdk_iscsi_portal_create(req.portal_list.portals[i].host,
|
||||
req.portal_list.portals[i].port,
|
||||
|
@ -135,7 +135,7 @@ static const char *portal_group_section = \
|
||||
" Comment \"Portal%d\"\n"
|
||||
|
||||
#define PORTAL_TMPL \
|
||||
" Portal DA1 %s:%s@0x%" PRIx64 "\n"
|
||||
" Portal DA1 %s:%s@0x%s\n"
|
||||
|
||||
static void
|
||||
spdk_iscsi_config_dump_portal_groups(FILE *fp)
|
||||
@ -153,7 +153,8 @@ spdk_iscsi_config_dump_portal_groups(FILE *fp)
|
||||
/* Dump portals */
|
||||
TAILQ_FOREACH(p, &pg->head, per_pg_tailq) {
|
||||
if (NULL == p) { continue; }
|
||||
fprintf(fp, PORTAL_TMPL, p->host, p->port, p->cpumask);
|
||||
fprintf(fp, PORTAL_TMPL, p->host, p->port,
|
||||
spdk_cpuset_fmt(p->cpumask));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ struct spdk_iscsi_portal *
|
||||
spdk_iscsi_portal_create(const char *host, const char *port, const char *cpumask)
|
||||
{
|
||||
struct spdk_iscsi_portal *p = NULL;
|
||||
uint64_t core_mask;
|
||||
struct spdk_cpuset *core_mask = NULL;
|
||||
int rc;
|
||||
|
||||
assert(host != NULL);
|
||||
@ -113,23 +113,29 @@ spdk_iscsi_portal_create(const char *host, const char *port, const char *cpumask
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
core_mask = spdk_app_get_core_mask();
|
||||
core_mask = spdk_cpuset_alloc();
|
||||
if (!core_mask) {
|
||||
SPDK_ERRLOG("spdk_cpuset_alloc() failed for host\n");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (cpumask != NULL) {
|
||||
rc = spdk_app_parse_core_mask(cpumask, &p->cpumask);
|
||||
rc = spdk_app_parse_core_mask(cpumask, core_mask);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("cpumask (%s) is invalid\n", cpumask);
|
||||
goto error_out;
|
||||
}
|
||||
if (p->cpumask == 0) {
|
||||
SPDK_ERRLOG("cpumask (%s) does not contain core mask (0x%" PRIx64 ")\n",
|
||||
cpumask, core_mask);
|
||||
if (spdk_cpuset_count(core_mask) == 0) {
|
||||
SPDK_ERRLOG("cpumask (%s) does not contain core mask (0x%s)\n",
|
||||
cpumask, spdk_cpuset_fmt(spdk_app_get_core_mask()));
|
||||
goto error_out;
|
||||
}
|
||||
} else {
|
||||
p->cpumask = core_mask;
|
||||
spdk_cpuset_copy(core_mask, spdk_app_get_core_mask());
|
||||
}
|
||||
|
||||
p->cpumask = core_mask;
|
||||
|
||||
p->sock = -1;
|
||||
p->group = NULL; /* set at a later time by caller */
|
||||
p->acceptor_poller = NULL;
|
||||
@ -139,6 +145,7 @@ spdk_iscsi_portal_create(const char *host, const char *port, const char *cpumask
|
||||
return p;
|
||||
|
||||
error_out:
|
||||
spdk_cpuset_free(core_mask);
|
||||
free(p->port);
|
||||
free(p->host);
|
||||
free(p);
|
||||
@ -155,6 +162,7 @@ spdk_iscsi_portal_destroy(struct spdk_iscsi_portal *p)
|
||||
TAILQ_REMOVE(&g_spdk_iscsi.portal_head, p, g_tailq);
|
||||
free(p->host);
|
||||
free(p->port);
|
||||
spdk_cpuset_free(p->cpumask);
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,14 @@
|
||||
#define SPDK_PORTAL_GRP_H
|
||||
|
||||
#include "spdk/conf.h"
|
||||
#include "spdk/cpuset.h"
|
||||
|
||||
struct spdk_iscsi_portal {
|
||||
struct spdk_iscsi_portal_grp *group;
|
||||
char *host;
|
||||
char *port;
|
||||
int sock;
|
||||
uint64_t cpumask;
|
||||
struct spdk_cpuset *cpumask;
|
||||
struct spdk_poller *acceptor_poller;
|
||||
TAILQ_ENTRY(spdk_iscsi_portal) per_pg_tailq;
|
||||
TAILQ_ENTRY(spdk_iscsi_portal) g_tailq;
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
C_SRCS = bit_array.c crc16.c crc32.c crc32c.c crc32_ieee.c fd.c io_channel.c strerror_tls.c string.c
|
||||
C_SRCS = bit_array.c cpuset.c crc16.c crc32.c crc32c.c crc32_ieee.c fd.c io_channel.c strerror_tls.c string.c
|
||||
LIBNAME = util
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
||||
|
320
lib/util/cpuset.c
Normal file
320
lib/util/cpuset.c
Normal file
@ -0,0 +1,320 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 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 "spdk/cpuset.h"
|
||||
#include "spdk/log.h"
|
||||
|
||||
struct spdk_cpuset {
|
||||
char str[SPDK_CPUSET_SIZE / 4];
|
||||
uint8_t cpus[SPDK_CPUSET_SIZE / 8];
|
||||
};
|
||||
|
||||
struct spdk_cpuset *
|
||||
spdk_cpuset_alloc(void)
|
||||
{
|
||||
return (struct spdk_cpuset *)calloc(sizeof(struct spdk_cpuset), 1);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_free(struct spdk_cpuset *set)
|
||||
{
|
||||
free(set);
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
|
||||
{
|
||||
assert(set1 != NULL);
|
||||
assert(set2 != NULL);
|
||||
return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_copy(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
|
||||
{
|
||||
assert(set1 != NULL);
|
||||
assert(set2 != NULL);
|
||||
memcpy(&set1->cpus, &set2->cpus, sizeof(set2->cpus));
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_and(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
|
||||
{
|
||||
unsigned int i;
|
||||
assert(set1 != NULL);
|
||||
assert(set2 != NULL);
|
||||
for (i = 0; i < sizeof(set2->cpus); i++) {
|
||||
set1->cpus[i] &= set2->cpus[i];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_or(struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
|
||||
{
|
||||
unsigned int i;
|
||||
assert(set1 != NULL);
|
||||
assert(set2 != NULL);
|
||||
for (i = 0; i < sizeof(set2->cpus); i++) {
|
||||
set1->cpus[i] |= set2->cpus[i];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_zero(struct spdk_cpuset *set)
|
||||
{
|
||||
assert(set != NULL);
|
||||
memset(set->cpus, 0, sizeof(set->cpus));
|
||||
}
|
||||
|
||||
void
|
||||
spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
|
||||
{
|
||||
assert(set != NULL);
|
||||
assert(cpu < sizeof(set->cpus) * 8);
|
||||
if (state) {
|
||||
set->cpus[cpu / 8] |= (1U << (cpu % 8));
|
||||
} else {
|
||||
set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
|
||||
{
|
||||
assert(set != NULL);
|
||||
assert(cpu < sizeof(set->cpus) * 8);
|
||||
return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
spdk_cpuset_count(const struct spdk_cpuset *set)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint8_t n;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(set->cpus); i++) {
|
||||
n = set->cpus[i];
|
||||
while (n) {
|
||||
n &= (n - 1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char *
|
||||
spdk_cpuset_fmt(struct spdk_cpuset *set)
|
||||
{
|
||||
uint32_t lcore, lcore_max = 0;
|
||||
int val, i, n;
|
||||
char *ptr;
|
||||
static const char *hex = "0123456789abcdef";
|
||||
|
||||
assert(set != NULL);
|
||||
|
||||
for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
|
||||
if (spdk_cpuset_get_cpu(set, lcore)) {
|
||||
lcore_max = lcore;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = set->str;
|
||||
n = lcore_max / 8;
|
||||
val = set->cpus[n];
|
||||
|
||||
/* Store first number only if it is not leading zero */
|
||||
if ((val & 0xf0) != 0) {
|
||||
*(ptr++) = hex[(val & 0xf0) >> 4];
|
||||
}
|
||||
*(ptr++) = hex[val & 0x0f];
|
||||
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
val = set->cpus[i];
|
||||
*(ptr++) = hex[(val & 0xf0) >> 4];
|
||||
*(ptr++) = hex[val & 0x0f];
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
return set->str;
|
||||
}
|
||||
|
||||
static int
|
||||
hex_value(uint8_t c)
|
||||
{
|
||||
#define V(x, y) [x] = y + 1
|
||||
static const int8_t val[256] = {
|
||||
V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
|
||||
V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
|
||||
V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
|
||||
V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
|
||||
};
|
||||
#undef V
|
||||
|
||||
return val[c] - 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_list(const char *mask, struct spdk_cpuset *set)
|
||||
{
|
||||
char *end;
|
||||
const char *ptr = mask;
|
||||
uint32_t lcore;
|
||||
uint32_t lcore_min, lcore_max;
|
||||
|
||||
spdk_cpuset_zero(set);
|
||||
lcore_min = UINT32_MAX;
|
||||
|
||||
ptr++;
|
||||
end = (char *)ptr;
|
||||
do {
|
||||
while (isblank(*ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
|
||||
goto invalid_character;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
lcore = strtoul(ptr, &end, 10);
|
||||
if (errno) {
|
||||
SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lcore >= sizeof(set->cpus) * 8) {
|
||||
SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (isblank(*end)) {
|
||||
end++;
|
||||
}
|
||||
|
||||
if (*end == '-') {
|
||||
lcore_min = lcore;
|
||||
} else if (*end == ',' || *end == ']') {
|
||||
lcore_max = lcore;
|
||||
if (lcore_min == UINT32_MAX) {
|
||||
lcore_min = lcore;
|
||||
}
|
||||
if (lcore_min > lcore_max) {
|
||||
SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
|
||||
lcore_min, lcore_max);
|
||||
return -1;
|
||||
}
|
||||
for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
|
||||
spdk_cpuset_set_cpu(set, lcore, true);
|
||||
}
|
||||
lcore_min = UINT32_MAX;
|
||||
} else {
|
||||
goto invalid_character;
|
||||
}
|
||||
|
||||
ptr = end + 1;
|
||||
|
||||
} while (*end != ']');
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_character:
|
||||
if (*end == '\0') {
|
||||
SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
|
||||
} else {
|
||||
SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
|
||||
{
|
||||
int i, j;
|
||||
char c;
|
||||
int val;
|
||||
uint32_t lcore = 0;
|
||||
|
||||
if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
|
||||
mask += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
spdk_cpuset_zero(set);
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
c = mask[i];
|
||||
val = hex_value(c);
|
||||
if (val < 0) {
|
||||
/* Invalid character */
|
||||
SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
|
||||
return -1;
|
||||
}
|
||||
for (j = 0; j < 4 && lcore < sizeof(set->cpus); j++, lcore++) {
|
||||
if ((1 << j) & val) {
|
||||
spdk_cpuset_set_cpu(set, lcore, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
if (mask == NULL || set == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (isblank(*mask)) {
|
||||
mask++;
|
||||
}
|
||||
|
||||
len = strlen(mask);
|
||||
while (len > 0 && isblank(mask[len - 1])) {
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mask[0] == '[') {
|
||||
ret = parse_list(mask, set);
|
||||
} else {
|
||||
ret = parse_mask(mask, set, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -495,7 +495,7 @@ spdk_vhost_dev_find(const char *ctrlr_name)
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_vhost_parse_core_mask(const char *mask, uint64_t *cpumask)
|
||||
spdk_vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@ -504,21 +504,19 @@ spdk_vhost_parse_core_mask(const char *mask, uint64_t *cpumask)
|
||||
}
|
||||
|
||||
if (mask == NULL) {
|
||||
*cpumask = spdk_app_get_core_mask();
|
||||
spdk_cpuset_copy(cpumask, spdk_app_get_core_mask());
|
||||
return 0;
|
||||
}
|
||||
|
||||
*cpumask = 0;
|
||||
|
||||
rc = spdk_app_parse_core_mask(mask, cpumask);
|
||||
if (rc != 0) {
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("invalid cpumask %s\n", mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*cpumask == 0) {
|
||||
SPDK_ERRLOG("no cpu is selected among reactor mask(=%jx)\n",
|
||||
spdk_app_get_core_mask());
|
||||
if (spdk_cpuset_count(cpumask) == 0) {
|
||||
SPDK_ERRLOG("no cpu is selected among reactor mask(=%s)\n",
|
||||
spdk_cpuset_fmt(spdk_app_get_core_mask()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -532,7 +530,8 @@ spdk_vhost_dev_construct(struct spdk_vhost_dev *vdev, const char *name, const ch
|
||||
unsigned ctrlr_num;
|
||||
char path[PATH_MAX];
|
||||
struct stat file_stat;
|
||||
uint64_t cpumask;
|
||||
struct spdk_cpuset *cpumask;
|
||||
int rc;
|
||||
|
||||
assert(vdev);
|
||||
|
||||
@ -541,15 +540,23 @@ spdk_vhost_dev_construct(struct spdk_vhost_dev *vdev, const char *name, const ch
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (spdk_vhost_parse_core_mask(mask_str, &cpumask) != 0) {
|
||||
SPDK_ERRLOG("cpumask %s is invalid (app mask is 0x%jx)\n",
|
||||
mask_str, spdk_app_get_core_mask());
|
||||
return -EINVAL;
|
||||
cpumask = spdk_cpuset_alloc();
|
||||
if (!cpumask) {
|
||||
SPDK_ERRLOG("spdk_cpuset_alloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spdk_vhost_parse_core_mask(mask_str, cpumask) != 0) {
|
||||
SPDK_ERRLOG("cpumask %s is invalid (app mask is 0x%s)\n",
|
||||
mask_str, spdk_cpuset_fmt(spdk_app_get_core_mask()));
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (spdk_vhost_dev_find(name)) {
|
||||
SPDK_ERRLOG("vhost controller %s already exists.\n", name);
|
||||
return -EEXIST;
|
||||
rc = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (ctrlr_num = 0; ctrlr_num < MAX_VHOST_DEVICES; ctrlr_num++) {
|
||||
@ -560,13 +567,15 @@ spdk_vhost_dev_construct(struct spdk_vhost_dev *vdev, const char *name, const ch
|
||||
|
||||
if (ctrlr_num == MAX_VHOST_DEVICES) {
|
||||
SPDK_ERRLOG("Max controllers reached (%d).\n", MAX_VHOST_DEVICES);
|
||||
return -ENOSPC;
|
||||
rc = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s%s", dev_dirname, name) >= (int)sizeof(path)) {
|
||||
SPDK_ERRLOG("Resulting socket path for controller %s is too long: %s%s\n", name, dev_dirname,
|
||||
name);
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Register vhost driver to handle vhost messages. */
|
||||
@ -575,32 +584,37 @@ spdk_vhost_dev_construct(struct spdk_vhost_dev *vdev, const char *name, const ch
|
||||
SPDK_ERRLOG("Cannot create a domain socket at path \"%s\": "
|
||||
"The file already exists and is not a socket.\n",
|
||||
path);
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
} else if (unlink(path) != 0) {
|
||||
SPDK_ERRLOG("Cannot create a domain socket at path \"%s\": "
|
||||
"The socket already exists and failed to unlink.\n",
|
||||
path);
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (rte_vhost_driver_register(path, 0) != 0) {
|
||||
SPDK_ERRLOG("Could not register controller %s with vhost library\n", name);
|
||||
SPDK_ERRLOG("Check if domain socket %s already exists\n", path);
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
if (rte_vhost_driver_set_features(path, backend->virtio_features) ||
|
||||
rte_vhost_driver_disable_features(path, backend->disabled_features)) {
|
||||
SPDK_ERRLOG("Couldn't set vhost features for controller %s\n", name);
|
||||
|
||||
rte_vhost_driver_unregister(path);
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rte_vhost_driver_callback_register(path, &g_spdk_vhost_ops) != 0) {
|
||||
rte_vhost_driver_unregister(path);
|
||||
SPDK_ERRLOG("Couldn't register callbacks for controller %s\n", name);
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdev->name = strdup(name);
|
||||
@ -628,6 +642,10 @@ spdk_vhost_dev_construct(struct spdk_vhost_dev *vdev, const char *name, const ch
|
||||
|
||||
SPDK_NOTICELOG("Controller %s: new controller added\n", vdev->name);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
spdk_cpuset_free(cpumask);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
@ -662,6 +680,7 @@ spdk_vhost_dev_remove(struct spdk_vhost_dev *vdev)
|
||||
|
||||
free(vdev->name);
|
||||
free(vdev->path);
|
||||
spdk_cpuset_free(vdev->cpumask);
|
||||
g_spdk_vhost_devices[ctrlr_num] = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -687,15 +706,16 @@ spdk_vhost_dev_get_name(struct spdk_vhost_dev *vdev)
|
||||
return vdev->name;
|
||||
}
|
||||
|
||||
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 *cpumask)
|
||||
{
|
||||
assert(vdev != NULL);
|
||||
return vdev->cpumask;
|
||||
assert(cpumask != NULL);
|
||||
spdk_cpuset_copy(cpumask, vdev->cpumask);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
spdk_vhost_allocate_reactor(uint64_t cpumask)
|
||||
spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask)
|
||||
{
|
||||
uint32_t i, selected_core;
|
||||
uint32_t min_ctrlrs;
|
||||
@ -704,7 +724,7 @@ spdk_vhost_allocate_reactor(uint64_t cpumask)
|
||||
selected_core = spdk_env_get_first_core();
|
||||
|
||||
SPDK_ENV_FOREACH_CORE(i) {
|
||||
if (!((1ULL << i) & cpumask)) {
|
||||
if (!spdk_cpuset_get_cpu(cpumask, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ struct spdk_vhost_dev {
|
||||
int vid;
|
||||
int task_cnt;
|
||||
int32_t lcore;
|
||||
uint64_t cpumask;
|
||||
struct spdk_cpuset *cpumask;
|
||||
|
||||
enum spdk_vhost_dev_type type;
|
||||
const struct spdk_vhost_dev_backend *backend;
|
||||
|
@ -471,7 +471,7 @@ spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg)
|
||||
spdk_json_write_string(ctx->w, spdk_vhost_dev_get_name(vdev));
|
||||
|
||||
spdk_json_write_name(ctx->w, "cpumask");
|
||||
spdk_json_write_string_fmt(ctx->w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev));
|
||||
spdk_json_write_string_fmt(ctx->w, "0x%s", spdk_cpuset_fmt(vdev->cpumask));
|
||||
|
||||
spdk_json_write_name(ctx->w, "backend_specific");
|
||||
|
||||
|
@ -126,26 +126,34 @@ spdk_sock_close(int sock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
static struct spdk_cpuset *g_app_core_mask;
|
||||
|
||||
struct spdk_cpuset *
|
||||
spdk_app_get_core_mask(void)
|
||||
{
|
||||
return 0xFFFFFFFFFFFFFFFF;
|
||||
int i;
|
||||
if (!g_app_core_mask) {
|
||||
g_app_core_mask = spdk_cpuset_alloc();
|
||||
for (i = 0; i < SPDK_CPUSET_SIZE; i++) {
|
||||
spdk_cpuset_set_cpu(g_app_core_mask, i, true);
|
||||
}
|
||||
}
|
||||
return g_app_core_mask;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_app_parse_core_mask(const char *mask, uint64_t *cpumask)
|
||||
spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||
{
|
||||
char *end;
|
||||
int rc;
|
||||
|
||||
if (mask == NULL || cpumask == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*cpumask = strtoull(mask, &end, 16);
|
||||
if (*end != '\0' || errno) {
|
||||
rc = spdk_cpuset_parse(cpumask, mask);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -166,18 +166,25 @@ portal_create_from_configline_ipv4_normal_case(void)
|
||||
const char *string = "192.168.2.0:3260@1";
|
||||
const char *host_str = "192.168.2.0";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 1;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_cpuset_alloc();
|
||||
CU_ASSERT_FATAL(cpumask_val != NULL);
|
||||
|
||||
spdk_cpuset_set_cpu(cpumask_val, 0, true);
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
|
||||
spdk_cpuset_free(cpumask_val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -186,18 +193,25 @@ portal_create_from_configline_ipv6_normal_case(void)
|
||||
const char *string = "[2001:ad6:1234::]:3260@1";
|
||||
const char *host_str = "[2001:ad6:1234::]";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 1;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_cpuset_alloc();
|
||||
CU_ASSERT_FATAL(cpumask_val != NULL);
|
||||
|
||||
spdk_cpuset_set_cpu(cpumask_val, 0, true);
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
|
||||
spdk_cpuset_free(cpumask_val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -206,15 +220,17 @@ portal_create_from_configline_ipv4_skip_cpumask_case(void)
|
||||
const char *string = "192.168.2.0:3260";
|
||||
const char *host_str = "192.168.2.0";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 0xFFFFFFFFFFFFFFFF;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_app_get_core_mask();
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
@ -226,15 +242,17 @@ portal_create_from_configline_ipv6_skip_cpumask_case(void)
|
||||
const char *string = "[2001:ad6:1234::]:3260";
|
||||
const char *host_str = "[2001:ad6:1234::]";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 0xFFFFFFFFFFFFFFFF;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_app_get_core_mask();
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
@ -246,15 +264,17 @@ portal_create_from_configline_ipv4_skip_port_and_cpumask_case(void)
|
||||
const char *string = "192.168.2.0";
|
||||
const char *host_str = "192.168.2.0";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 0xFFFFFFFFFFFFFFFF;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_app_get_core_mask();
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
@ -266,15 +286,17 @@ portal_create_from_configline_ipv6_skip_port_and_cpumask_case(void)
|
||||
const char *string = "[2001:ad6:1234::]";
|
||||
const char *host_str = "[2001:ad6:1234::]";
|
||||
const char *port_str = "3260";
|
||||
uint64_t cpumask_val = 0xFFFFFFFFFFFFFFFF;
|
||||
struct spdk_cpuset *cpumask_val;
|
||||
struct spdk_iscsi_portal *p;
|
||||
int rc;
|
||||
|
||||
cpumask_val = spdk_app_get_core_mask();
|
||||
|
||||
rc = spdk_iscsi_portal_create_from_configline(string, &p, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(strcmp(p->host, host_str) == 0);
|
||||
CU_ASSERT(strcmp(p->port, port_str) == 0);
|
||||
CU_ASSERT(p->cpumask == cpumask_val);
|
||||
CU_ASSERT(spdk_cpuset_equal(p->cpumask, cpumask_val));
|
||||
|
||||
spdk_iscsi_portal_destroy(p);
|
||||
CU_ASSERT(TAILQ_EMPTY(&g_spdk_iscsi.portal_head));
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = bit_array.c crc16.c crc32_ieee.c crc32c.c io_channel.c string.c
|
||||
DIRS-y = bit_array.c cpuset.c crc16.c crc32_ieee.c crc32c.c io_channel.c string.c
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
1
test/unit/lib/util/cpuset.c/.gitignore
vendored
Normal file
1
test/unit/lib/util/cpuset.c/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
cpuset_ut
|
56
test/unit/lib/util/cpuset.c/Makefile
Normal file
56
test/unit/lib/util/cpuset.c/Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
|
||||
|
||||
SPDK_LIB_LIST = log
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib
|
||||
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = cpuset_ut
|
||||
C_SRCS = $(APP).c
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS) $(SPDK_LIB_FILES)
|
||||
$(LINK_C)
|
||||
|
||||
clean:
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
265
test/unit/lib/util/cpuset.c/cpuset_ut.c
Normal file
265
test/unit/lib/util/cpuset.c/cpuset_ut.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/cpuset.h"
|
||||
|
||||
#include "spdk_cunit.h"
|
||||
|
||||
#include "util/cpuset.c"
|
||||
|
||||
static int
|
||||
cpuset_check_range(struct spdk_cpuset *core_mask, uint32_t min, uint32_t max, bool isset)
|
||||
{
|
||||
uint32_t core;
|
||||
for (core = min; core <= max; core++) {
|
||||
if (isset != spdk_cpuset_get_cpu(core_mask, core)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_cpuset(void)
|
||||
{
|
||||
uint32_t cpu;
|
||||
struct spdk_cpuset *set = spdk_cpuset_alloc();
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(set != NULL);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 0);
|
||||
|
||||
/* Set cpu 0 */
|
||||
spdk_cpuset_set_cpu(set, 0, true);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true);
|
||||
CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 1, false) == 0);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 1);
|
||||
|
||||
/* Set last cpu (cpu 0 already set) */
|
||||
spdk_cpuset_set_cpu(set, SPDK_CPUSET_SIZE - 1, true);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true);
|
||||
CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 2);
|
||||
|
||||
/* Clear cpu 0 (last cpu already set) */
|
||||
spdk_cpuset_set_cpu(set, 0, false);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == false);
|
||||
CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 1);
|
||||
|
||||
/* Set middle cpu (last cpu already set) */
|
||||
cpu = (SPDK_CPUSET_SIZE - 1) / 2;
|
||||
spdk_cpuset_set_cpu(set, cpu, true);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, cpu) == true);
|
||||
CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true);
|
||||
CU_ASSERT(cpuset_check_range(set, 1, cpu - 1, false) == 0);
|
||||
CU_ASSERT(cpuset_check_range(set, cpu + 1, SPDK_CPUSET_SIZE - 2, false) == 0);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 2);
|
||||
|
||||
/* Set all cpus */
|
||||
for (cpu = 0; cpu < SPDK_CPUSET_SIZE; cpu++) {
|
||||
spdk_cpuset_set_cpu(set, cpu, true);
|
||||
}
|
||||
CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, true) == 0);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == SPDK_CPUSET_SIZE);
|
||||
|
||||
/* Clear all cpus */
|
||||
spdk_cpuset_zero(set);
|
||||
CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, false) == 0);
|
||||
CU_ASSERT(spdk_cpuset_count(set) == 0);
|
||||
|
||||
spdk_cpuset_free(set);
|
||||
}
|
||||
|
||||
static void
|
||||
test_cpuset_parse(void)
|
||||
{
|
||||
int rc;
|
||||
struct spdk_cpuset *core_mask;
|
||||
char buf[1024];
|
||||
|
||||
core_mask = spdk_cpuset_alloc();
|
||||
SPDK_CU_ASSERT_FATAL(core_mask != NULL);
|
||||
|
||||
/* Only core 0 should be set */
|
||||
rc = spdk_cpuset_parse(core_mask, "0x1");
|
||||
CU_ASSERT(rc >= 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 0, 0, true) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 1, SPDK_CPUSET_SIZE - 1, false) == 0);
|
||||
|
||||
/* Only core 1 should be set */
|
||||
rc = spdk_cpuset_parse(core_mask, "[1]");
|
||||
CU_ASSERT(rc >= 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 0, 0, false) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 1, 1, true) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 2, SPDK_CPUSET_SIZE - 1, false) == 0);
|
||||
|
||||
/* Set cores 0-10,12,128-254 */
|
||||
rc = spdk_cpuset_parse(core_mask, "[0-10,12,128-254]");
|
||||
CU_ASSERT(rc >= 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 0, 10, true) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 11, 11, false) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 12, 12, true) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 13, 127, false) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 128, 254, true) == 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 255, SPDK_CPUSET_SIZE - 1, false) == 0);
|
||||
|
||||
/* Set all cores */
|
||||
snprintf(buf, sizeof(buf), "[0-%d]", SPDK_CPUSET_SIZE - 1);
|
||||
rc = spdk_cpuset_parse(core_mask, buf);
|
||||
CU_ASSERT(rc >= 0);
|
||||
CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0);
|
||||
|
||||
/* Null parameters not allowed */
|
||||
rc = spdk_cpuset_parse(core_mask, NULL);
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(NULL, "[1]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
/* Wrong formated core lists */
|
||||
rc = spdk_cpuset_parse(core_mask, "");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[10--11]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[11-10]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[10-11,]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
rc = spdk_cpuset_parse(core_mask, "[,10-11]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
/* Out of range value */
|
||||
snprintf(buf, sizeof(buf), "[%d]", SPDK_CPUSET_SIZE + 1);
|
||||
rc = spdk_cpuset_parse(core_mask, buf);
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
/* Overflow value (UINT64_MAX * 10) */
|
||||
rc = spdk_cpuset_parse(core_mask, "[184467440737095516150]");
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
spdk_cpuset_free(core_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
test_cpuset_fmt(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t lcore;
|
||||
struct spdk_cpuset *core_mask = spdk_cpuset_alloc();
|
||||
char *hex_mask;
|
||||
char hex_mask_ref[SPDK_CPUSET_SIZE / 4 + 1];
|
||||
|
||||
/* Clear coremask. hex_mask should be "0" */
|
||||
spdk_cpuset_zero(core_mask);
|
||||
hex_mask = spdk_cpuset_fmt(core_mask);
|
||||
SPDK_CU_ASSERT_FATAL(hex_mask != NULL);
|
||||
CU_ASSERT(strcmp("0", hex_mask) == 0);
|
||||
|
||||
/* Set coremask 0x51234. Result should be "51234" */
|
||||
spdk_cpuset_zero(core_mask);
|
||||
spdk_cpuset_set_cpu(core_mask, 2, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 4, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 5, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 9, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 12, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 16, true);
|
||||
spdk_cpuset_set_cpu(core_mask, 18, true);
|
||||
hex_mask = spdk_cpuset_fmt(core_mask);
|
||||
SPDK_CU_ASSERT_FATAL(hex_mask != NULL);
|
||||
CU_ASSERT(strcmp("51234", hex_mask) == 0);
|
||||
|
||||
/* Set all cores */
|
||||
spdk_cpuset_zero(core_mask);
|
||||
for (lcore = 0; lcore < SPDK_CPUSET_SIZE; lcore++) {
|
||||
spdk_cpuset_set_cpu(core_mask, lcore, true);
|
||||
}
|
||||
for (i = 0; i < SPDK_CPUSET_SIZE / 4 - 1; i++) {
|
||||
hex_mask_ref[i] = 'f';
|
||||
}
|
||||
hex_mask_ref[SPDK_CPUSET_SIZE / 4 - 1] = '\0';
|
||||
|
||||
hex_mask = spdk_cpuset_fmt(core_mask);
|
||||
CU_ASSERT(hex_mask != NULL);
|
||||
if (hex_mask != NULL) {
|
||||
CU_ASSERT(strcmp(hex_mask_ref, hex_mask) == 0);
|
||||
}
|
||||
|
||||
spdk_cpuset_free(core_mask);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("cpuset", NULL, NULL);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "test_cpuset", test_cpuset) == NULL ||
|
||||
CU_add_test(suite, "test_cpuset_parse", test_cpuset_parse) == NULL ||
|
||||
CU_add_test(suite, "test_cpuset_fmt", test_cpuset_fmt) == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
|
||||
CU_basic_run_tests();
|
||||
|
||||
num_failures = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
|
||||
return num_failures;
|
||||
}
|
@ -46,8 +46,18 @@ DEFINE_STUB(spdk_event_allocate, struct spdk_event *,
|
||||
(uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL);
|
||||
DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
|
||||
DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
|
||||
DEFINE_STUB(spdk_app_get_core_mask, uint64_t, (void), 0);
|
||||
DEFINE_STUB(spdk_app_parse_core_mask, int, (const char *mask, uint64_t *cpumask), 0);
|
||||
|
||||
static struct spdk_cpuset *g_app_core_mask;
|
||||
struct spdk_cpuset *spdk_app_get_core_mask(void)
|
||||
{
|
||||
if (g_app_core_mask == NULL) {
|
||||
g_app_core_mask = spdk_cpuset_alloc();
|
||||
spdk_cpuset_set_cpu(g_app_core_mask, 0, true);
|
||||
}
|
||||
return g_app_core_mask;
|
||||
}
|
||||
|
||||
DEFINE_STUB(spdk_app_parse_core_mask, int, (const char *mask, struct spdk_cpuset *cpumask), 0);
|
||||
DEFINE_STUB(spdk_env_get_first_core, uint32_t, (void), 0);
|
||||
DEFINE_STUB(spdk_env_get_next_core, uint32_t, (uint32_t prev_core), 0);
|
||||
DEFINE_STUB(spdk_env_get_last_core, uint32_t, (void), 0);
|
||||
@ -205,7 +215,7 @@ create_controller_test(void)
|
||||
char long_name[PATH_MAX];
|
||||
struct spdk_vhost_dev_backend backend;
|
||||
|
||||
MOCK_SET(spdk_app_get_core_mask, uint64_t, 1);
|
||||
/* NOTE: spdk_app_get_core_mask stub always sets coremask 0x01 */
|
||||
|
||||
/* Create device with no name */
|
||||
vdev = alloc_vdev();
|
||||
|
Loading…
Reference in New Issue
Block a user