Blame lib/resctrl_alloc.c

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
}