|
Packit Service |
5befb9 |
/*
|
|
Packit Service |
5befb9 |
* BSD LICENSE
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* Copyright(c) 2017-2018 Intel Corporation. All rights reserved.
|
|
Packit Service |
5befb9 |
* All rights reserved.
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
5befb9 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
5befb9 |
* are met:
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* * Redistributions of source code must retain the above copyright
|
|
Packit Service |
5befb9 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit Service |
5befb9 |
* * Redistributions in binary form must reproduce the above copyright
|
|
Packit Service |
5befb9 |
* notice, this list of conditions and the following disclaimer in
|
|
Packit Service |
5befb9 |
* the documentation and/or other materials provided with the
|
|
Packit Service |
5befb9 |
* distribution.
|
|
Packit Service |
5befb9 |
* * Neither the name of Intel Corporation nor the names of its
|
|
Packit Service |
5befb9 |
* contributors may be used to endorse or promote products derived
|
|
Packit Service |
5befb9 |
* from this software without specific prior written permission.
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit Service |
5befb9 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit Service |
5befb9 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit Service |
5befb9 |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit Service |
5befb9 |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit Service |
5befb9 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit Service |
5befb9 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit Service |
5befb9 |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit Service |
5befb9 |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit Service |
5befb9 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit Service |
5befb9 |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
#include <stdlib.h>
|
|
Packit Service |
5befb9 |
#include <string.h>
|
|
Packit Service |
5befb9 |
#include <ctype.h>
|
|
Packit Service |
5befb9 |
#include <errno.h>
|
|
Packit Service |
5befb9 |
#include <dirent.h>
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
#include "log.h"
|
|
Packit Service |
5befb9 |
#include "types.h"
|
|
Packit Service |
5befb9 |
#include "resctrl_alloc.h"
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
* Local data structures
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static const struct pqos_cap *m_cap = NULL;
|
|
Packit Service |
5befb9 |
static const struct pqos_cpuinfo *m_cpu = NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/*
|
|
Packit Service |
5befb9 |
* COS file names on resctrl file system
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static const char *rctl_cpus = "cpus";
|
|
Packit Service |
5befb9 |
static const char *rctl_schemata = "schemata";
|
|
Packit Service |
5befb9 |
static const char *rctl_tasks = "tasks";
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
if (cpu == NULL || cap == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_PARAM;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
m_cap = cap;
|
|
Packit Service |
5befb9 |
m_cpu = cpu;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_fini(void)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
m_cap = NULL;
|
|
Packit Service |
5befb9 |
m_cpu = NULL;
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_get_grps_num(const struct pqos_cap *cap, unsigned *grps_num)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
unsigned i;
|
|
Packit Service |
5befb9 |
unsigned max_rctl_grps = 0;
|
|
Packit Service |
5befb9 |
int ret = PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(cap != NULL);
|
|
Packit Service |
5befb9 |
ASSERT(grps_num != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/*
|
|
Packit Service |
5befb9 |
* Loop through all caps that have OS support
|
|
Packit Service |
5befb9 |
* Find max COS supported by all
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
for (i = 0; i < cap->num_cap; i++) {
|
|
Packit Service |
5befb9 |
unsigned num_cos = 0;
|
|
Packit Service |
5befb9 |
const struct pqos_capability *p_cap = &cap->capabilities[i];
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (!p_cap->os_support)
|
|
Packit Service |
5befb9 |
continue;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* get L3 CAT COS num */
|
|
Packit Service |
5befb9 |
if (p_cap->type == PQOS_CAP_TYPE_L3CA) {
|
|
Packit Service |
5befb9 |
ret = pqos_l3ca_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (max_rctl_grps == 0)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
else if (num_cos < max_rctl_grps)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
/* get L2 CAT COS num */
|
|
Packit Service |
5befb9 |
if (p_cap->type == PQOS_CAP_TYPE_L2CA) {
|
|
Packit Service |
5befb9 |
ret = pqos_l2ca_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (max_rctl_grps == 0)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
else if (num_cos < max_rctl_grps)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
/* get MBA COS num */
|
|
Packit Service |
5befb9 |
if (p_cap->type == PQOS_CAP_TYPE_MBA) {
|
|
Packit Service |
5befb9 |
ret = pqos_mba_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (max_rctl_grps == 0)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
else if (num_cos < max_rctl_grps)
|
|
Packit Service |
5befb9 |
max_rctl_grps = num_cos;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
*grps_num = max_rctl_grps;
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Converts string into 64-bit unsigned number.
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* Numbers can be in decimal or hexadecimal format.
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @param [in] s string to be converted into 64-bit unsigned number
|
|
Packit Service |
5befb9 |
* @param [in] base Numerical base
|
|
Packit Service |
5befb9 |
* @param [out] Numeric value of the string representing the number
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @return Operational status
|
|
Packit Service |
5befb9 |
* @retval PQOS_RETVAL_OK on success
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static int
|
|
Packit Service |
5befb9 |
strtouint64(const char *s, int base, uint64_t *value)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
char *endptr = NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(s != NULL);
|
|
Packit Service |
5befb9 |
if (strncasecmp(s, "0x", 2) == 0) {
|
|
Packit Service |
5befb9 |
base = 16;
|
|
Packit Service |
5befb9 |
s += 2;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
*value = strtoull(s, &endptr, base);
|
|
Packit Service |
5befb9 |
if (!(*s != '\0' && (*endptr == '\0' || *endptr == '\n')))
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Opens COS file in resctl filesystem
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @param [in] class_id COS id
|
|
Packit Service |
5befb9 |
* @param [in] name File name
|
|
Packit Service |
5befb9 |
* @param [in] mode fopen mode
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @return Pointer to the stream
|
|
Packit Service |
5befb9 |
* @retval Pointer on success
|
|
Packit Service |
5befb9 |
* @retval NULL on error
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static FILE *
|
|
Packit Service |
5befb9 |
resctrl_alloc_fopen(const unsigned class_id, const char *name, const char *mode)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
char buf[128];
|
|
Packit Service |
5befb9 |
int result;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(name != NULL);
|
|
Packit Service |
5befb9 |
ASSERT(mode != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
5befb9 |
if (class_id == 0)
|
|
Packit Service |
5befb9 |
result = snprintf(buf, sizeof(buf) - 1,
|
|
Packit Service |
5befb9 |
"%s/%s", RESCTRL_PATH, name);
|
|
Packit Service |
5befb9 |
else
|
|
Packit Service |
5befb9 |
result = snprintf(buf, sizeof(buf) - 1, "%s/COS%u/%s",
|
|
Packit Service |
5befb9 |
RESCTRL_PATH, class_id, name);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (result < 0)
|
|
Packit Service |
5befb9 |
return NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
fd = fopen(buf, mode);
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
LOG_ERROR("Could not open %s file %s for COS %u\n",
|
|
Packit Service |
5befb9 |
name, buf, class_id);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return fd;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Closes COS file in resctl filesystem
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @param[in] fd File descriptor
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @return Operational status
|
|
Packit Service |
5befb9 |
* @retval PQOS_RETVAL_OK on success
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static int
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(FILE *fd)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_PARAM;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (fclose(fd) == 0)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
switch (errno) {
|
|
Packit Service |
5befb9 |
case EBADF:
|
|
Packit Service |
5befb9 |
LOG_ERROR("Invalid file descriptor!\n");
|
|
Packit Service |
5befb9 |
break;
|
|
Packit Service |
5befb9 |
case EINVAL:
|
|
Packit Service |
5befb9 |
LOG_ERROR("Invalid file arguments!\n");
|
|
Packit Service |
5befb9 |
break;
|
|
Packit Service |
5befb9 |
default:
|
|
Packit Service |
5befb9 |
LOG_ERROR("Error closing file!\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/*
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
* CPU mask structures and utility functions
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_cpumask_write(const unsigned class_id,
|
|
Packit Service |
5befb9 |
const struct resctrl_cpumask *mask)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret = PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_cpus, "w");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_cpumask_write(fd, mask);
|
|
Packit Service |
5befb9 |
if (ret == PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
else
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_cpumask_read(const unsigned class_id,
|
|
Packit Service |
5befb9 |
struct resctrl_cpumask *mask)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_cpus, "r");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_cpumask_read(fd, mask);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (resctrl_alloc_fclose(fd) != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/*
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
* Schemata structures and utility functions
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
void
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_fini(struct resctrl_alloc_schemata *schemata)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
if (schemata->l2ca != NULL) {
|
|
Packit Service |
5befb9 |
free(schemata->l2ca);
|
|
Packit Service |
5befb9 |
schemata->l2ca = NULL;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
if (schemata->l3ca != NULL) {
|
|
Packit Service |
5befb9 |
free(schemata->l3ca);
|
|
Packit Service |
5befb9 |
schemata->l3ca = NULL;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
if (schemata->mba != NULL) {
|
|
Packit Service |
5befb9 |
free(schemata->mba);
|
|
Packit Service |
5befb9 |
schemata->mba = NULL;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_init(const unsigned class_id,
|
|
Packit Service |
5befb9 |
const struct pqos_cap *cap,
|
|
Packit Service |
5befb9 |
const struct pqos_cpuinfo *cpu,
|
|
Packit Service |
5befb9 |
struct resctrl_alloc_schemata *schemata)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret = PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
int retval;
|
|
Packit Service |
5befb9 |
unsigned num_cos, num_ids, i;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(schemata != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
memset(schemata, 0, sizeof(struct resctrl_alloc_schemata));
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L2 */
|
|
Packit Service |
5befb9 |
retval = pqos_l2ca_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (retval == PQOS_RETVAL_OK && class_id < num_cos) {
|
|
Packit Service |
5befb9 |
unsigned *l2ids = NULL;
|
|
Packit Service |
5befb9 |
int cdp_enabled;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
l2ids = pqos_cpu_get_l2ids(cpu, &num_ids);
|
|
Packit Service |
5befb9 |
if (l2ids == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
free(l2ids);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
schemata->l2ca_num = num_ids;
|
|
Packit Service |
5befb9 |
schemata->l2ca = calloc(num_ids, sizeof(struct pqos_l2ca));
|
|
Packit Service |
5befb9 |
if (schemata->l2ca == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = pqos_l2ca_cdp_enabled(cap, NULL, &cdp_enabled);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* fill class_id */
|
|
Packit Service |
5befb9 |
for (i = 0; i < num_ids; i++) {
|
|
Packit Service |
5befb9 |
schemata->l2ca[i].class_id = class_id;
|
|
Packit Service |
5befb9 |
schemata->l2ca[i].cdp = cdp_enabled;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L3 */
|
|
Packit Service |
5befb9 |
retval = pqos_l3ca_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (retval == PQOS_RETVAL_OK && class_id < num_cos) {
|
|
Packit Service |
5befb9 |
unsigned *sockets = NULL;
|
|
Packit Service |
5befb9 |
int cdp_enabled;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
sockets = pqos_cpu_get_sockets(cpu, &num_ids);
|
|
Packit Service |
5befb9 |
if (sockets == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
free(sockets);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
schemata->l3ca_num = num_ids;
|
|
Packit Service |
5befb9 |
schemata->l3ca = calloc(num_ids, sizeof(struct pqos_l3ca));
|
|
Packit Service |
5befb9 |
if (schemata->l3ca == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = pqos_l3ca_cdp_enabled(cap, NULL, &cdp_enabled);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* fill class_id and cdp values */
|
|
Packit Service |
5befb9 |
for (i = 0; i < num_ids; i++) {
|
|
Packit Service |
5befb9 |
schemata->l3ca[i].class_id = class_id;
|
|
Packit Service |
5befb9 |
schemata->l3ca[i].cdp = cdp_enabled;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* MBA */
|
|
Packit Service |
5befb9 |
retval = pqos_mba_get_cos_num(cap, &num_cos);
|
|
Packit Service |
5befb9 |
if (retval == PQOS_RETVAL_OK && class_id < num_cos) {
|
|
Packit Service |
5befb9 |
unsigned *sockets = NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
sockets = pqos_cpu_get_sockets(cpu, &num_ids);
|
|
Packit Service |
5befb9 |
if (sockets == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
free(sockets);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
schemata->mba_num = num_ids;
|
|
Packit Service |
5befb9 |
schemata->mba = calloc(num_ids, sizeof(struct pqos_mba));
|
|
Packit Service |
5befb9 |
if (schemata->mba == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_init_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* fill class_id */
|
|
Packit Service |
5befb9 |
for (i = 0; i < num_ids; i++) {
|
|
Packit Service |
5befb9 |
schemata->mba[i].class_id = class_id;
|
|
Packit Service |
5befb9 |
schemata->mba[i].mb_rate = 100;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_init_exit:
|
|
Packit Service |
5befb9 |
/* Deallocate memory in case of error */
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_fini(schemata);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Schemata type
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
enum resctrl_alloc_schemata_type {
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_NONE, /**< unknown */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L2, /**< L2 CAT without CDP */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L2CODE, /**< L2 CAT code */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L2DATA, /**< L2 CAT data */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L3, /**< L3 CAT without CDP */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L3CODE, /**< L3 CAT code */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_L3DATA, /**< L3 CAT data */
|
|
Packit Service |
5befb9 |
RESCTRL_ALLOC_SCHEMATA_TYPE_MB, /**< MBA data */
|
|
Packit Service |
5befb9 |
};
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Determine allocation type
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @param [in] str resctrl label
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @return Allocation type
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static int
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_type_get(const char *str)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int type = RESCTRL_ALLOC_SCHEMATA_TYPE_NONE;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (strcasecmp(str, "L2") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L2;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "L2CODE") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L2CODE;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "L2DATA") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L2DATA;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "L3") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L3;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "L3CODE") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L3CODE;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "L3DATA") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_L3DATA;
|
|
Packit Service |
5befb9 |
else if (strcasecmp(str, "MB") == 0)
|
|
Packit Service |
5befb9 |
type = RESCTRL_ALLOC_SCHEMATA_TYPE_MB;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return type;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* @brief Fill schemata structure
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @param [in] res_id Resource id
|
|
Packit Service |
5befb9 |
* @param [in] value Ways mask/Memory B/W rate
|
|
Packit Service |
5befb9 |
* @param [in] type Schemata type
|
|
Packit Service |
5befb9 |
* @param [out] schemata Schemata structure
|
|
Packit Service |
5befb9 |
*
|
|
Packit Service |
5befb9 |
* @return Operational status
|
|
Packit Service |
5befb9 |
* @retval PQOS_RETVAL_OK on success
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
static int
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_set(const unsigned res_id,
|
|
Packit Service |
5befb9 |
const uint64_t value,
|
|
Packit Service |
5befb9 |
const int type,
|
|
Packit Service |
5befb9 |
struct resctrl_alloc_schemata *schemata)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L2) {
|
|
Packit Service |
5befb9 |
if (schemata->l2ca_num <= res_id)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l2ca[res_id].u.ways_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L2CODE) {
|
|
Packit Service |
5befb9 |
if (schemata->l2ca_num <= res_id || !schemata->l2ca[res_id].cdp)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l2ca[res_id].u.s.code_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L2DATA) {
|
|
Packit Service |
5befb9 |
if (schemata->l2ca_num <= res_id || !schemata->l2ca[res_id].cdp)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l2ca[res_id].u.s.data_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L3) {
|
|
Packit Service |
5befb9 |
if (schemata->l3ca_num <= res_id || schemata->l3ca[res_id].cdp)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l3ca[res_id].u.ways_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L3CODE) {
|
|
Packit Service |
5befb9 |
if (schemata->l3ca_num <= res_id || !schemata->l3ca[res_id].cdp)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l3ca[res_id].u.s.code_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_L3DATA) {
|
|
Packit Service |
5befb9 |
if (schemata->l3ca_num <= res_id || !schemata->l3ca[res_id].cdp)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->l3ca[res_id].u.s.data_mask = value;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
} else if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_MB) {
|
|
Packit Service |
5befb9 |
if (schemata->mba_num <= res_id)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
schemata->mba[res_id].mb_rate = value;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_read(const unsigned class_id,
|
|
Packit Service |
5befb9 |
struct resctrl_alloc_schemata *schemata)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret = PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
FILE *fd = NULL;
|
|
Packit Service |
5befb9 |
int type = RESCTRL_ALLOC_SCHEMATA_TYPE_NONE;
|
|
Packit Service |
5befb9 |
char *p = NULL, *q = NULL, *saveptr = NULL;
|
|
Packit Service |
5befb9 |
const size_t buf_size = 16 * 1024;
|
|
Packit Service |
5befb9 |
char *buf = calloc(buf_size, sizeof(*buf));
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (buf == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(schemata != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_schemata, "r");
|
|
Packit Service |
5befb9 |
if (fd == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if ((schemata->l3ca_num > 0 && schemata->l3ca == NULL)
|
|
Packit Service |
5befb9 |
|| (schemata->l2ca_num > 0 && schemata->l2ca == NULL)) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
while (fgets(buf, buf_size, fd) != NULL) {
|
|
Packit Service |
5befb9 |
q = buf;
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* Trim white spaces
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
while (isspace(*q))
|
|
Packit Service |
5befb9 |
q++;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* Determine allocation type
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
p = strchr(q, ':');
|
|
Packit Service |
5befb9 |
if (p == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
break;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
*p = '\0';
|
|
Packit Service |
5befb9 |
type = resctrl_alloc_schemata_type_get(q);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Skip unknown label */
|
|
Packit Service |
5befb9 |
if (type == RESCTRL_ALLOC_SCHEMATA_TYPE_NONE)
|
|
Packit Service |
5befb9 |
continue;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* Parse COS masks
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
for (++p; ; p = NULL) {
|
|
Packit Service |
5befb9 |
char *token = NULL;
|
|
Packit Service |
5befb9 |
uint64_t id = 0;
|
|
Packit Service |
5befb9 |
uint64_t value = 0;
|
|
Packit Service |
5befb9 |
unsigned base = (type == RESCTRL_ALLOC_SCHEMATA_TYPE_MB
|
|
Packit Service |
5befb9 |
? 10 : 16);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
token = strtok_r(p, ";", &saveptr);
|
|
Packit Service |
5befb9 |
if (token == NULL)
|
|
Packit Service |
5befb9 |
break;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
q = strchr(token, '=');
|
|
Packit Service |
5befb9 |
if (q == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
*q = '\0';
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = strtouint64(token, 10, &id;;
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = strtouint64(q + 1, base, &value);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_schemata_set(id,
|
|
Packit Service |
5befb9 |
value,
|
|
Packit Service |
5befb9 |
type,
|
|
Packit Service |
5befb9 |
schemata);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_read_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_read_exit:
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (buf != NULL)
|
|
Packit Service |
5befb9 |
free(buf);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* check if error occured */
|
|
Packit Service |
5befb9 |
if (ret == PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
else if (fd)
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_write(const unsigned class_id,
|
|
Packit Service |
5befb9 |
const struct resctrl_alloc_schemata *schemata)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret = PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
unsigned i;
|
|
Packit Service |
5befb9 |
FILE *fd = NULL;
|
|
Packit Service |
5befb9 |
const size_t buf_size = 16 * 1024;
|
|
Packit Service |
5befb9 |
char *buf = calloc(buf_size, sizeof(*buf));
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (buf == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_write_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(schemata != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_schemata, "w");
|
|
Packit Service |
5befb9 |
if (fd == NULL) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_write_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Enable fully buffered output. File won't be flushed until 16kB
|
|
Packit Service |
5befb9 |
* buffer is full */
|
|
Packit Service |
5befb9 |
if (setvbuf(fd, buf, _IOFBF, buf_size) != 0) {
|
|
Packit Service |
5befb9 |
ret = PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_schemata_write_exit;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L2 without CDP */
|
|
Packit Service |
5befb9 |
if (schemata->l2ca_num > 0 && !schemata->l2ca[0].cdp) {
|
|
Packit Service |
5befb9 |
fprintf(fd, "L2:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l2ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l2ca[i].u.ways_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L2 with CDP */
|
|
Packit Service |
5befb9 |
if (schemata->l2ca_num > 0 && schemata->l2ca[0].cdp) {
|
|
Packit Service |
5befb9 |
fprintf(fd, "L2CODE:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l2ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l2ca[i].u.s.code_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\nL2DATA:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l2ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l2ca[i].u.s.data_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L3 without CDP */
|
|
Packit Service |
5befb9 |
if (schemata->l3ca_num > 0 && !schemata->l3ca[0].cdp) {
|
|
Packit Service |
5befb9 |
fprintf(fd, "L3:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l3ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l3ca[i].u.ways_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* L3 with CDP */
|
|
Packit Service |
5befb9 |
if (schemata->l3ca_num > 0 && schemata->l3ca[0].cdp) {
|
|
Packit Service |
5befb9 |
fprintf(fd, "L3CODE:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l3ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l3ca[i].u.s.code_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\nL3DATA:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->l3ca_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%llx", i, (unsigned long long)
|
|
Packit Service |
5befb9 |
schemata->l3ca[i].u.s.data_mask);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* MBA */
|
|
Packit Service |
5befb9 |
if (schemata->mba_num > 0) {
|
|
Packit Service |
5befb9 |
fprintf(fd, "MB:");
|
|
Packit Service |
5befb9 |
for (i = 0; i < schemata->mba_num; i++) {
|
|
Packit Service |
5befb9 |
if (i > 0)
|
|
Packit Service |
5befb9 |
fprintf(fd, ";");
|
|
Packit Service |
5befb9 |
fprintf(fd, "%u=%u", i, schemata->mba[i].mb_rate);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
fprintf(fd, "\n");
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
resctrl_alloc_schemata_write_exit:
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* check if error occured */
|
|
Packit Service |
5befb9 |
if (ret == PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
else if (fd)
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* setvbuf buffer should be freed after fclose */
|
|
Packit Service |
5befb9 |
if (buf != NULL)
|
|
Packit Service |
5befb9 |
free(buf);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
* Task utility functions
|
|
Packit Service |
5befb9 |
* ---------------------------------------
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_validate(const pid_t task)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
DIR *dir;
|
|
Packit Service |
5befb9 |
char buf[64];
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
5befb9 |
snprintf(buf, sizeof(buf)-1, "/proc/%d", (int)task);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
dir = opendir(buf);
|
|
Packit Service |
5befb9 |
if (dir == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
closedir(dir);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (access(buf, F_OK) != 0)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_write(const unsigned class_id, const pid_t task)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Check if task exists */
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_task_validate(task);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK) {
|
|
Packit Service |
5befb9 |
LOG_ERROR("Task %d does not exist!\n", (int)task);
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_PARAM;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Open resctrl tasks file */
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_tasks, "w");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Write task ID to file */
|
|
Packit Service |
5befb9 |
if (fprintf(fd, "%d\n", task) < 0) {
|
|
Packit Service |
5befb9 |
LOG_ERROR("Failed to write to task %d to file!\n", (int) task);
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
unsigned *
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_read(unsigned class_id, unsigned *count)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
unsigned *tasks = NULL, idx = 0;
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
char buf[128];
|
|
Packit Service |
5befb9 |
struct linked_list {
|
|
Packit Service |
5befb9 |
uint64_t task_id;
|
|
Packit Service |
5befb9 |
struct linked_list *next;
|
|
Packit Service |
5befb9 |
} head, *current = NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Open resctrl tasks file */
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_tasks, "r");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
head.next = NULL;
|
|
Packit Service |
5befb9 |
current = &head;
|
|
Packit Service |
5befb9 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
5befb9 |
while (fgets(buf, sizeof(buf), fd) != NULL) {
|
|
Packit Service |
5befb9 |
uint64_t tmp;
|
|
Packit Service |
5befb9 |
struct linked_list *p = NULL;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = strtouint64(buf, 10, &tmp);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_task_read_exit_clean;
|
|
Packit Service |
5befb9 |
p = malloc(sizeof(head));
|
|
Packit Service |
5befb9 |
if (p == NULL)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_task_read_exit_clean;
|
|
Packit Service |
5befb9 |
p->task_id = tmp;
|
|
Packit Service |
5befb9 |
p->next = NULL;
|
|
Packit Service |
5befb9 |
current->next = p;
|
|
Packit Service |
5befb9 |
current = p;
|
|
Packit Service |
5befb9 |
idx++;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* if no pids found then allocate empty buffer to be returned */
|
|
Packit Service |
5befb9 |
if (idx == 0)
|
|
Packit Service |
5befb9 |
tasks = (unsigned *) calloc(1, sizeof(tasks[0]));
|
|
Packit Service |
5befb9 |
else
|
|
Packit Service |
5befb9 |
tasks = (unsigned *) malloc(idx * sizeof(tasks[0]));
|
|
Packit Service |
5befb9 |
if (tasks == NULL)
|
|
Packit Service |
5befb9 |
goto resctrl_alloc_task_read_exit_clean;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
*count = idx;
|
|
Packit Service |
5befb9 |
current = head.next;
|
|
Packit Service |
5befb9 |
idx = 0;
|
|
Packit Service |
5befb9 |
while (current != NULL) {
|
|
Packit Service |
5befb9 |
tasks[idx++] = current->task_id;
|
|
Packit Service |
5befb9 |
current = current->next;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_read_exit_clean:
|
|
Packit Service |
5befb9 |
resctrl_alloc_fclose(fd);
|
|
Packit Service |
5befb9 |
current = head.next;
|
|
Packit Service |
5befb9 |
while (current != NULL) {
|
|
Packit Service |
5befb9 |
struct linked_list *tmp = current->next;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
free(current);
|
|
Packit Service |
5befb9 |
current = tmp;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
return tasks;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_search(unsigned *class_id,
|
|
Packit Service |
5befb9 |
const struct pqos_cap *cap,
|
|
Packit Service |
5befb9 |
const pid_t task)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
unsigned i, max_cos = 0;
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Check if task exists */
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_task_validate(task);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK) {
|
|
Packit Service |
5befb9 |
LOG_ERROR("Task %d does not exist!\n", (int)task);
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_PARAM;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Get number of COS */
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_get_grps_num(cap, &max_cos);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/**
|
|
Packit Service |
5befb9 |
* Starting at highest COS - search all COS tasks files for task ID
|
|
Packit Service |
5befb9 |
*/
|
|
Packit Service |
5befb9 |
for (i = (max_cos - 1); (int)i >= 0; i--) {
|
|
Packit Service |
5befb9 |
uint64_t tid = 0;
|
|
Packit Service |
5befb9 |
char buf[128];
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Open resctrl tasks file */
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(i, rctl_tasks, "r");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Search tasks file for specified task ID */
|
|
Packit Service |
5befb9 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
5befb9 |
while (fgets(buf, sizeof(buf), fd) != NULL) {
|
|
Packit Service |
5befb9 |
ret = strtouint64(buf, 10, &tid;;
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
continue;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (task == (pid_t)tid) {
|
|
Packit Service |
5befb9 |
*class_id = i;
|
|
Packit Service |
5befb9 |
if (resctrl_alloc_fclose(fd) != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
if (resctrl_alloc_fclose(fd) != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
/* If not found in any COS group - return error */
|
|
Packit Service |
5befb9 |
LOG_ERROR("Failed to get association for task %d!\n", (int)task);
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_task_file_check(const unsigned class_id, unsigned *found)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
FILE *fd;
|
|
Packit Service |
5befb9 |
char buf[128];
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Open resctrl tasks file */
|
|
Packit Service |
5befb9 |
fd = resctrl_alloc_fopen(class_id, rctl_tasks, "r");
|
|
Packit Service |
5befb9 |
if (fd == NULL)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
/* Search tasks file for any task ID */
|
|
Packit Service |
5befb9 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
5befb9 |
if (fgets(buf, sizeof(buf), fd) != NULL)
|
|
Packit Service |
5befb9 |
*found = 1;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (resctrl_alloc_fclose(fd) != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_ERROR;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_assoc_set(const unsigned lcore, const unsigned class_id)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
struct resctrl_cpumask mask;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_cpumask_read(class_id, &mask);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
resctrl_cpumask_set(lcore, &mask);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_cpumask_write(class_id, &mask);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_assoc_get(const unsigned lcore, unsigned *class_id)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
int ret;
|
|
Packit Service |
5befb9 |
unsigned grps;
|
|
Packit Service |
5befb9 |
unsigned i;
|
|
Packit Service |
5befb9 |
struct resctrl_cpumask mask;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ASSERT(m_cap != NULL);
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_get_grps_num(m_cap, &grps);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
for (i = 0; i < grps; i++) {
|
|
Packit Service |
5befb9 |
ret = resctrl_alloc_cpumask_read(i, &mask);
|
|
Packit Service |
5befb9 |
if (ret != PQOS_RETVAL_OK)
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
if (resctrl_cpumask_get(lcore, &mask)) {
|
|
Packit Service |
5befb9 |
*class_id = i;
|
|
Packit Service |
5befb9 |
return PQOS_RETVAL_OK;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
return ret;
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_assoc_set_pid(const pid_t task, const unsigned class_id)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
/* Write to tasks file */
|
|
Packit Service |
5befb9 |
return resctrl_alloc_task_write(class_id, task);
|
|
Packit Service |
5befb9 |
}
|
|
Packit Service |
5befb9 |
|
|
Packit Service |
5befb9 |
int
|
|
Packit Service |
5befb9 |
resctrl_alloc_assoc_get_pid(const pid_t task, unsigned *class_id)
|
|
Packit Service |
5befb9 |
{
|
|
Packit Service |
5befb9 |
/* Search tasks files */
|
|
Packit Service |
5befb9 |
return resctrl_alloc_task_search(class_id, m_cap, task);
|
|
Packit Service |
5befb9 |
}
|