aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgomp/config
diff options
context:
space:
mode:
authorAndrew Hsieh <andrewhsieh@google.com>2014-05-14 17:46:52 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2014-05-14 17:47:56 +0800
commit18927802fc8b991c35d7703427a53807e3c6d8c7 (patch)
tree39f882d1b632f47604c264b684fc7dcd4c91f37d /gcc-4.9/libgomp/config
parent5cd97bdbf2d97af4b0e4301f5f2b6c2a4301baf9 (diff)
downloadtoolchain_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.h4
-rw-r--r--gcc-4.9/libgomp/config/linux/mips/futex.h5
-rw-r--r--gcc-4.9/libgomp/config/linux/proc.c193
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;