diff options
author | Andrew Hsieh <andrewhsieh@google.com> | 2014-05-14 17:46:52 +0800 |
---|---|---|
committer | Andrew Hsieh <andrewhsieh@google.com> | 2014-05-14 17:47:56 +0800 |
commit | 18927802fc8b991c35d7703427a53807e3c6d8c7 (patch) | |
tree | 39f882d1b632f47604c264b684fc7dcd4c91f37d /gcc-4.9/libgomp/config | |
parent | 5cd97bdbf2d97af4b0e4301f5f2b6c2a4301baf9 (diff) | |
download | toolchain_gcc-18927802fc8b991c35d7703427a53807e3c6d8c7.tar.gz toolchain_gcc-18927802fc8b991c35d7703427a53807e3c6d8c7.tar.bz2 toolchain_gcc-18927802fc8b991c35d7703427a53807e3c6d8c7.zip |
[4.9] Fix openmp support
See the following CLs for 4.8
c27bd5a265e6aeecefa6bfebe52fcf26b08298cd # Support OpenMP
b6c94ff8e836a01ad3598135d19c49c9eb01a173 # needed OpenMP: Better CPU count detection for Linux
d88e126b2b303c95d94b939c21f8672637871dbd # Fix openmp support to use libgomp/config/linux
Change-Id: Ib85a23669c03bcdc9dd5f83b9a0f18e5cad6033d
Diffstat (limited to 'gcc-4.9/libgomp/config')
-rw-r--r-- | gcc-4.9/libgomp/config/linux/futex.h | 4 | ||||
-rw-r--r-- | gcc-4.9/libgomp/config/linux/mips/futex.h | 5 | ||||
-rw-r--r-- | gcc-4.9/libgomp/config/linux/proc.c | 193 |
3 files changed, 199 insertions, 3 deletions
diff --git a/gcc-4.9/libgomp/config/linux/futex.h b/gcc-4.9/libgomp/config/linux/futex.h index 63334c7c9..f96cd2a5c 100644 --- a/gcc-4.9/libgomp/config/linux/futex.h +++ b/gcc-4.9/libgomp/config/linux/futex.h @@ -38,6 +38,10 @@ #pragma GCC visibility pop +#if !defined(SYS_futex) +#define SYS_futex __NR_futex +#endif + static inline void futex_wait (int *addr, int val) { diff --git a/gcc-4.9/libgomp/config/linux/mips/futex.h b/gcc-4.9/libgomp/config/linux/mips/futex.h index ae32b8056..641308cab 100644 --- a/gcc-4.9/libgomp/config/linux/mips/futex.h +++ b/gcc-4.9/libgomp/config/linux/mips/futex.h @@ -25,6 +25,11 @@ /* Provide target-specific access to the futex system call. */ #include <sys/syscall.h> + +#if !defined(SYS_futex) +#define SYS_futex __NR_futex +#endif + #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 diff --git a/gcc-4.9/libgomp/config/linux/proc.c b/gcc-4.9/libgomp/config/linux/proc.c index fa89f1d15..a6a5e9900 100644 --- a/gcc-4.9/libgomp/config/linux/proc.c +++ b/gcc-4.9/libgomp/config/linux/proc.c @@ -31,8 +31,11 @@ #include "libgomp.h" #include "proc.h" #include <errno.h> -#include <stdlib.h> #include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> #ifdef HAVE_GETLOADAVG # ifdef HAVE_SYS_LOADAVG_H # include <sys/loadavg.h> @@ -73,6 +76,186 @@ gomp_cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp) } #endif +/* Read the content of a file. + * Return the length of the data, or -1 on error. Does *not* + * zero-terminate the content. Will not read more + * than 'buffsize' bytes. + */ +static int +read_file(const char* pathname, char* buffer, size_t buffsize) +{ + int fd, len; + + fd = open(pathname, O_RDONLY); + if (fd < 0) + return -1; + + do { + len = read(fd, buffer, buffsize); + } while (len < 0 && errno == EINTR); + + close(fd); + + return len; +} + + +/* Parse a decimal integer starting from 'input', but not going further + * than 'limit'. Return the value into '*result'. + * + * NOTE: Does not skip over leading spaces, or deal with sign characters. + * NOTE: Ignores overflows. + * + * The function returns NULL in case of error (bad format), or the new + * position after the decimal number in case of success (which will always + * be <= 'limit'). + */ +static const char* +parse_decimal(const char* input, const char* limit, int* result) +{ + const char* p = input; + int val = 0; + while (p < limit) { + int d = (*p - '0'); + if ((unsigned)d >= 10U) + break; + val = val*10 + d; + p++; + } + if (p == input) + return NULL; + + *result = val; + return p; +} + + +/* This data type is used to represent a CPU list / mask, as read + * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt + */ +typedef struct { + int mask; +} cpuList; + +/* Returns Actual CPUs (total installed CPUs) */ +static int +cpuList_count (cpuList* list) { + return list->mask ; +} + +/* Parse a textual list of cpus and store the result inside a cpuList object. + * Input format is the following: + * - comma-separated list of items (no spaces) + * - each item is either a single decimal number (cpu index), or a range made + * of two numbers separated by a single dash (-). Ranges are inclusive. + * Examples: + * 0 + * 2,4-127,128-143 + * 0-1 + */ +static void +cpuList_parse (cpuList* list, const char* line, int line_len) +{ + const char* p = line; + const char* end = p + line_len; + const char* q; + + /* NOTE: the input line coming from sysfs typically contains a + * trailing newline, so take care of it in the code below + */ + while (p < end && *p != '\n') + { + int val, start_value, end_value; + + /* Find the end of current item, and put it into 'q' */ + q = memchr(p, ',', end-p); + if (q == NULL) { + q = end; + } + + /* Get first value */ + p = parse_decimal(p, q, &start_value); + if (p == NULL) + goto BAD_FORMAT; + + end_value = start_value; + + /* If we're not at the end of the item, expect a dash and + * and integer; extract end value. + */ + if (p < q && *p == '-') { + p = parse_decimal(p+1, q, &end_value); + if (p == NULL) + goto BAD_FORMAT; + } + + /* Set CPU list */ + for (val = start_value; val <= end_value; val++) { + list->mask++; + } + + /* Jump to next item */ + p = q; + if (p < end) + p++; + } + +BAD_FORMAT: + ; +} + + +/* Read a CPU list from one sysfs file + * The below is CPU related sys interface by CPU topologoy. + */ +static void +cpuList_read_from (cpuList* list, const char* filename) +{ + char file[64]; + int filelen; + + list->mask = 0; + + filelen = read_file(filename, file, sizeof file); + if (filelen < 0) { + fprintf(stderr,"Could not read %s: %s\n", filename, strerror(errno)); + return; + } + + cpuList_parse(list, file, filelen); +} + + +/* Probe the number of actual CPUs on devices (e.g. Android devices) using + * CPU-Hotplug and CPU-DVFS to optimize battery life. + * Return the number of CPUs present on a given device. + * See http://www.kernel.org/doc/Documentation/cputopology.txt + */ +static int +sc_nprocessors_actu () +{ + char buffer[256]; + int buffer_len; + int cpuCount = 1; + cpuList cpus_present[1]; + char file_name[64] = "/sys/devices/system/cpu/present"; + + buffer_len = read_file(file_name, buffer, sizeof buffer); + + if (buffer_len < 0) /* should not happen */ { + fprintf(stderr,"Could not find %s: %s\n", file_name, strerror(errno)); + return 1; + } + + /* Count the CPU cores, the value may be 0 for single-core CPUs */ + cpuList_read_from(cpus_present, file_name); + cpuCount = cpuList_count(cpus_present); + if (cpuCount == 0) { + cpuCount = 1; + } + return cpuCount; +} + /* At startup, determine the default number of threads. It would seem this should be related to the number of cpus online. */ @@ -138,7 +321,9 @@ gomp_init_num_threads (void) free (gomp_cpusetp); gomp_cpusetp = NULL; #endif -#ifdef _SC_NPROCESSORS_ONLN +#if defined(__ANDROID__) + gomp_global_icv.nthreads_var = sc_nprocessors_actu (); +#elif defined(_SC_NPROCESSORS_ONLN) gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN); #endif } @@ -169,7 +354,9 @@ get_num_procs (void) return gomp_available_cpus; } #endif -#ifdef _SC_NPROCESSORS_ONLN +#if defined(__ANDROID__) + return sc_nprocessors_actu (); +#elif defined(_SC_NPROCESSORS_ONLN) return sysconf (_SC_NPROCESSORS_ONLN); #else return gomp_icv (false)->nthreads_var; |