blob: 8cb32ea107fe10bd60e9313b5adeeb8685184407 [file] [log] [blame]
/* Copyright (c) 2015 Google Inc
* Davide Libenzi <dlibenzi@google.com>
* See LICENSE for details.
*/
#include <ros/arch/arch.h>
#include <ros/common.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <parlib/parlib.h>
#include <parlib/core_set.h>
static const unsigned int llcores[] = {
0
};
void parlib_get_ll_core_set(struct core_set *cores)
{
parlib_get_none_core_set(cores);
for (size_t i = 0; i < COUNT_OF(llcores); i++)
parlib_set_core(cores, llcores[i]);
}
size_t parlib_nr_ll_cores(void)
{
return COUNT_OF(llcores);
}
static int guess_nr_cores(void)
{
return max_vcores() + parlib_nr_ll_cores();
}
static int get_vars_nr_cores(void)
{
int fd, ret;
char buf[10];
fd = open("#vars/num_cores!dw", O_READ);
if (fd < 0)
return -1;
if (read(fd, buf, sizeof(buf)) <= 0) {
close(fd);
return -1;
}
ret = atoi(buf);
return ret;
}
static int nr_cores;
static void set_nr_cores(void *arg)
{
nr_cores = get_vars_nr_cores();
if (nr_cores == -1)
nr_cores = guess_nr_cores();
}
size_t parlib_nr_total_cores(void)
{
static parlib_once_t once = PARLIB_ONCE_INIT;
parlib_run_once(&once, set_nr_cores, NULL);
return nr_cores;
}
void parlib_parse_cores(const char *str, struct core_set *cores)
{
unsigned int fcpu, ncpu;
char *dstr = strdup(str);
char *sptr = NULL;
char *tok, *sptr2;
if (!dstr) {
perror("Duplicating a string");
exit(1);
}
ZERO_DATA(*cores);
for (tok = strtok_r(dstr, ",", &sptr); tok;
tok = strtok_r(NULL, ",", &sptr)) {
if (strchr(tok, '-')) {
if (sscanf(tok, "%u-%u", &fcpu, &ncpu) != 2) {
fprintf(stderr, "Invalid CPU range: %s\n", tok);
exit(1);
}
if (fcpu >= parlib_nr_total_cores()) {
fprintf(stderr, "CPU number out of bound: %u\n",
fcpu);
exit(1);
}
if (ncpu >= parlib_nr_total_cores()) {
fprintf(stderr, "CPU number out of bound: %u\n",
ncpu);
exit(1);
}
if (fcpu > ncpu) {
fprintf(stderr,
"CPU range is backwards: %u-%u\n",
fcpu, ncpu);
exit(1);
}
for (; fcpu <= ncpu; fcpu++)
parlib_set_core(cores, fcpu);
} else {
fcpu = atoi(tok);
if (fcpu >= parlib_nr_total_cores()) {
fprintf(stderr, "CPU number out of bound: %u\n",
fcpu);
exit(1);
}
parlib_set_core(cores, fcpu);
}
}
free(dstr);
}
void parlib_get_all_core_set(struct core_set *cores)
{
size_t max_cores = parlib_nr_total_cores();
memset(cores->core_set, 0xff, DIV_ROUND_UP(max_cores, CHAR_BIT));
}
void parlib_get_none_core_set(struct core_set *cores)
{
size_t max_cores = parlib_nr_total_cores();
memset(cores->core_set, 0, DIV_ROUND_UP(max_cores, CHAR_BIT));
}
void parlib_not_core_set(struct core_set *dcs)
{
size_t max_cores = parlib_nr_total_cores();
for (size_t i = 0; (max_cores > 0) && (i < sizeof(dcs->core_set)); i++)
{
size_t nb = (max_cores >= CHAR_BIT) ? CHAR_BIT : max_cores;
dcs->core_set[i] = (~dcs->core_set[i]) & ((1 << nb) - 1);
max_cores -= nb;
}
}
void parlib_and_core_sets(struct core_set *dcs, const struct core_set *scs)
{
for (size_t i = 0; i < sizeof(dcs->core_set); i++)
dcs->core_set[i] &= scs->core_set[i];
}
void parlib_or_core_sets(struct core_set *dcs, const struct core_set *scs)
{
for (size_t i = 0; i < sizeof(dcs->core_set); i++)
dcs->core_set[i] |= scs->core_set[i];
}