|  | /* 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 <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <limits.h> | 
|  | #include <unistd.h> | 
|  | #include <parlib/parlib.h> | 
|  | #include <parlib/core_set.h> | 
|  | #include <parlib/stdio.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]; | 
|  | } |