| /* 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]; | 
 | } |