|
Packit |
bcb633 |
/*
|
|
Packit |
bcb633 |
* BSD LICENSE
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* Copyright(c) 2018 Intel Corporation. All rights reserved.
|
|
Packit |
bcb633 |
* All rights reserved.
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
bcb633 |
* modification, are permitted provided that the following conditions
|
|
Packit |
bcb633 |
* are met:
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* * Redistributions of source code must retain the above copyright
|
|
Packit |
bcb633 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit |
bcb633 |
* * Redistributions in binary form must reproduce the above copyright
|
|
Packit |
bcb633 |
* notice, this list of conditions and the following disclaimer in
|
|
Packit |
bcb633 |
* the documentation and/or other materials provided with the
|
|
Packit |
bcb633 |
* distribution.
|
|
Packit |
bcb633 |
* * Neither the name of Intel Corporation nor the names of its
|
|
Packit |
bcb633 |
* contributors may be used to endorse or promote products derived
|
|
Packit |
bcb633 |
* from this software without specific prior written permission.
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
bcb633 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
bcb633 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
bcb633 |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
bcb633 |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
bcb633 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
bcb633 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
bcb633 |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
bcb633 |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
bcb633 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
bcb633 |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
*/
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
#include <stdlib.h>
|
|
Packit |
bcb633 |
#include <unistd.h>
|
|
Packit |
bcb633 |
#include <sys/file.h>
|
|
Packit |
bcb633 |
#include <signal.h>
|
|
Packit |
bcb633 |
#include <sys/mount.h>
|
|
Packit |
bcb633 |
#include <errno.h>
|
|
Packit |
bcb633 |
#include <string.h>
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
#include "pqos.h"
|
|
Packit |
bcb633 |
#include "log.h"
|
|
Packit |
bcb633 |
#include "types.h"
|
|
Packit |
bcb633 |
#include "resctrl.h"
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
static int resctrl_lock_fd = -1; /**< File descriptor to the lockfile */
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/**
|
|
Packit |
bcb633 |
* @brief Handle SIGALRM
|
|
Packit |
bcb633 |
*/
|
|
Packit |
bcb633 |
static void
|
|
Packit |
bcb633 |
resctrl_lock_signalhandler(int signal)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
UNUSED_PARAM(signal);
|
|
Packit |
bcb633 |
/* File lock timeout */
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/**
|
|
Packit |
bcb633 |
* @brief Obtain lock on resctrl filesystem
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* @param[in] type type of lock
|
|
Packit |
bcb633 |
*
|
|
Packit |
bcb633 |
* @return Operational status
|
|
Packit |
bcb633 |
* @retval PQOS_RETVAL_OK on success
|
|
Packit |
bcb633 |
*/
|
|
Packit |
bcb633 |
static int
|
|
Packit |
bcb633 |
resctrl_lock(const int type)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
struct sigaction sa;
|
|
Packit |
bcb633 |
int ret = PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
ASSERT(type == LOCK_SH || type == LOCK_EX);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
resctrl_lock_fd = open(RESCTRL_PATH, O_DIRECTORY);
|
|
Packit |
bcb633 |
if (resctrl_lock_fd < 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Could not open %s directory\n", RESCTRL_PATH);
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* Handle SIGALRM */
|
|
Packit |
bcb633 |
sigaction(SIGALRM, NULL, &sa);
|
|
Packit |
bcb633 |
sa.sa_handler = resctrl_lock_signalhandler;
|
|
Packit |
bcb633 |
sa.sa_flags = 0;
|
|
Packit |
bcb633 |
sigaction(SIGALRM, &sa, NULL);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* Set alarm when 100ms timeout occurs */
|
|
Packit |
bcb633 |
ualarm(100000, 0);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (flock(resctrl_lock_fd, type) == 0) {
|
|
Packit |
bcb633 |
ret = PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
goto resctrl_lock_exit;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (errno == EINTR)
|
|
Packit |
bcb633 |
LOG_ERROR("Failed to acquire lock on resctrl filesystem - "
|
|
Packit |
bcb633 |
"timeout occured\n");
|
|
Packit |
bcb633 |
else
|
|
Packit |
bcb633 |
LOG_ERROR("Failed to acquire lock on resctrl filesystem - "
|
|
Packit |
bcb633 |
"%m\n");
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
close(resctrl_lock_fd);
|
|
Packit |
bcb633 |
resctrl_lock_fd = -1;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
resctrl_lock_exit:
|
|
Packit |
bcb633 |
/* disable alarm */
|
|
Packit |
bcb633 |
ualarm(0, 0);
|
|
Packit |
bcb633 |
sa.sa_handler = SIG_DFL;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return ret;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_lock_shared(void)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
return resctrl_lock(LOCK_SH);
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_lock_exclusive(void)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
return resctrl_lock(LOCK_EX);
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_lock_release(void)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
if (resctrl_lock_fd < 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Resctrl filesystem not locked\n");
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (flock(resctrl_lock_fd, LOCK_UN) != 0)
|
|
Packit |
bcb633 |
LOG_WARN("Failed to release lock on resctrl filesystem\n");
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
close(resctrl_lock_fd);
|
|
Packit |
bcb633 |
resctrl_lock_fd = -1;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_mount(const enum pqos_cdp_config l3_cdp_cfg,
|
|
Packit |
bcb633 |
const enum pqos_cdp_config l2_cdp_cfg)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
const char *cdp_option = NULL; /**< cdp_off default */
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
ASSERT(l3_cdp_cfg == PQOS_REQUIRE_CDP_ON ||
|
|
Packit |
bcb633 |
l3_cdp_cfg == PQOS_REQUIRE_CDP_OFF);
|
|
Packit |
bcb633 |
ASSERT(l2_cdp_cfg == PQOS_REQUIRE_CDP_ON ||
|
|
Packit |
bcb633 |
l2_cdp_cfg == PQOS_REQUIRE_CDP_OFF);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* cdp mount options */
|
|
Packit |
bcb633 |
if (l3_cdp_cfg == PQOS_REQUIRE_CDP_ON &&
|
|
Packit |
bcb633 |
l2_cdp_cfg == PQOS_REQUIRE_CDP_ON)
|
|
Packit |
bcb633 |
cdp_option = "cdp,cdpl2"; /**< both L3 CDP and L2 CDP on */
|
|
Packit |
bcb633 |
else if (l3_cdp_cfg == PQOS_REQUIRE_CDP_ON)
|
|
Packit |
bcb633 |
cdp_option = "cdp"; /**< L3 CDP on */
|
|
Packit |
bcb633 |
else if (l2_cdp_cfg == PQOS_REQUIRE_CDP_ON)
|
|
Packit |
bcb633 |
cdp_option = "cdpl2"; /**< L2 CDP on */
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (mount("resctrl", RESCTRL_PATH, "resctrl", 0, cdp_option) != 0)
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_umount(void)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
if (umount2(RESCTRL_PATH, 0) != 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Could not umount resctrl filesystem!\n");
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/*
|
|
Packit |
bcb633 |
* ---------------------------------------
|
|
Packit |
bcb633 |
* CPU mask structures and utility functions
|
|
Packit |
bcb633 |
* ---------------------------------------
|
|
Packit |
bcb633 |
*/
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
void
|
|
Packit |
bcb633 |
resctrl_cpumask_set(const unsigned lcore, struct resctrl_cpumask *mask)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
/* index in mask table */
|
|
Packit |
bcb633 |
const unsigned item = (sizeof(mask->tab) - 1) - (lcore / CHAR_BIT);
|
|
Packit |
bcb633 |
const unsigned bit = lcore % CHAR_BIT;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* Set lcore bit in mask table item */
|
|
Packit |
bcb633 |
mask->tab[item] = mask->tab[item] | (1 << bit);
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_cpumask_get(const unsigned lcore, const struct resctrl_cpumask *mask)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
/* index in mask table */
|
|
Packit |
bcb633 |
const unsigned item = (sizeof(mask->tab) - 1) - (lcore / CHAR_BIT);
|
|
Packit |
bcb633 |
const unsigned bit = lcore % CHAR_BIT;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* Check if lcore bit is set in mask table item */
|
|
Packit |
bcb633 |
return (mask->tab[item] >> bit) & 0x1;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_cpumask_write(FILE *fd, const struct resctrl_cpumask *mask)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
unsigned i;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
ASSERT(fd != NULL);
|
|
Packit |
bcb633 |
ASSERT(mask != NULL);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
for (i = 0; i < sizeof(mask->tab); i++) {
|
|
Packit |
bcb633 |
const unsigned value = (unsigned) mask->tab[i];
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (fprintf(fd, "%02x", value) < 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Failed to write cpu mask\n");
|
|
Packit |
bcb633 |
break;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
if ((i + 1) % 4 == 0)
|
|
Packit |
bcb633 |
if (fprintf(fd, ",") < 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Failed to write cpu mask\n");
|
|
Packit |
bcb633 |
break;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/* check if error occured in loop */
|
|
Packit |
bcb633 |
if (i < sizeof(mask->tab))
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
int
|
|
Packit |
bcb633 |
resctrl_cpumask_read(FILE *fd, struct resctrl_cpumask *mask)
|
|
Packit |
bcb633 |
{
|
|
Packit |
bcb633 |
int i, hex_offset, idx;
|
|
Packit |
bcb633 |
size_t num_chars = 0;
|
|
Packit |
bcb633 |
char cpus[RESCTRL_MAX_CPUS / CHAR_BIT];
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
ASSERT(fd != NULL);
|
|
Packit |
bcb633 |
ASSERT(mask != NULL);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
memset(mask, 0, sizeof(struct resctrl_cpumask));
|
|
Packit |
bcb633 |
memset(cpus, 0, sizeof(cpus));
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/** Read the entire file into memory. */
|
|
Packit |
bcb633 |
num_chars = fread(cpus, sizeof(char), sizeof(cpus), fd);
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (ferror(fd) != 0) {
|
|
Packit |
bcb633 |
LOG_ERROR("Error reading CPU file\n");
|
|
Packit |
bcb633 |
return PQOS_RETVAL_ERROR;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
cpus[sizeof(cpus) - 1] = '\0'; /** Just to be safe. */
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
/**
|
|
Packit |
bcb633 |
* Convert the cpus array into hex, skip any non hex chars.
|
|
Packit |
bcb633 |
* Store the hex values in the mask tab.
|
|
Packit |
bcb633 |
*/
|
|
Packit |
bcb633 |
for (i = num_chars - 1, hex_offset = 0, idx = sizeof(mask->tab) - 1;
|
|
Packit |
bcb633 |
i >= 0; i--) {
|
|
Packit |
bcb633 |
const char c = cpus[i];
|
|
Packit |
bcb633 |
int hex_num;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if ('0' <= c && c <= '9')
|
|
Packit |
bcb633 |
hex_num = c - '0';
|
|
Packit |
bcb633 |
else if ('a' <= c && c <= 'f')
|
|
Packit |
bcb633 |
hex_num = 10 + c - 'a';
|
|
Packit |
bcb633 |
else if ('A' <= c && c <= 'F')
|
|
Packit |
bcb633 |
hex_num = 10 + c - 'A';
|
|
Packit |
bcb633 |
else
|
|
Packit |
bcb633 |
continue;
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
if (!hex_offset)
|
|
Packit |
bcb633 |
mask->tab[idx] = (uint8_t) hex_num;
|
|
Packit |
bcb633 |
else {
|
|
Packit |
bcb633 |
mask->tab[idx] |= (uint8_t) (hex_num << 4);
|
|
Packit |
bcb633 |
idx--;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
hex_offset ^= 1;
|
|
Packit |
bcb633 |
}
|
|
Packit |
bcb633 |
|
|
Packit |
bcb633 |
return PQOS_RETVAL_OK;
|
|
Packit |
bcb633 |
}
|