summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2014-08-26 15:29:50 +1000
committerJan Schmidt <jan@centricular.com>2014-08-26 15:32:02 +1000
commitdfcc456c2b31deab21501e889c89bd168a50a411 (patch)
treeddc9bb43f1e270e59f77bb9b2c51cd66e76a04b9
parent3c7cb2d3029628454eb22c7f4bc3451197462779 (diff)
downloadorc-dfcc456c2b31deab21501e889c89bd168a50a411.tar.gz
Add fallback CPU feature detection for Android
On Android, /proc/self/auxv might not be readable (except when debuggable=true in the build, annoyingly), so do what the android cpufeatures detection code does and fall back to /proc/cpuinfo string matching. Without this, release builds run really slowly, due to ORC always doing emulation.
-rw-r--r--orc/orccpu-arm.c143
1 files changed, 76 insertions, 67 deletions
diff --git a/orc/orccpu-arm.c b/orc/orccpu-arm.c
index 9c32c98..0087c60 100644
--- a/orc/orccpu-arm.c
+++ b/orc/orccpu-arm.c
@@ -71,6 +71,7 @@ orc_check_neon_proc_auxv (void)
fd = open("/proc/self/auxv", O_RDONLY);
if (fd < 0) {
+ ORC_LOG ("Failed to open /proc/self/auxv");
return 0;
}
@@ -99,39 +100,7 @@ orc_check_neon_proc_auxv (void)
}
#endif
-#ifdef unused
-static void
-orc_cpu_arm_getflags_cpuinfo (char *cpuinfo)
-{
- char *cpuinfo_flags;
- char **flags;
- char **f;
-
- cpuinfo_flags = get_cpuinfo_line(cpuinfo, "Features");
- if (cpuinfo_flags == NULL) {
- free (cpuinfo);
- return;
- }
-
- flags = strsplit(cpuinfo_flags, ' ');
- for (f = flags; *f; f++) {
-#if 0
- if (strcmp (*f, "edsp") == 0) {
- ORC_DEBUG ("cpu feature %s", *f);
- orc_cpu_flags |= ORC_CPU_FLAG_EDSP;
- }
- if (strcmp (*f, "vfp") == 0) {
- ORC_DEBUG ("cpu feature %s", *f);
- orc_cpu_flags |= ORC_CPU_FLAG_VFP;
- }
-#endif
-
- free (*f);
- }
- free (flags);
- free (cpuinfo_flags);
-}
-
+#ifdef ANDROID
static char *
get_proc_cpuinfo (void)
{
@@ -160,56 +129,96 @@ get_proc_cpuinfo (void)
return cpuinfo;
}
-#endif
-unsigned long
-orc_arm_get_cpu_flags (void)
+static char *
+get_cpuinfo_line (char *cpuinfo, const char *tag)
{
- unsigned long neon_flags = 0;
+ char *flags;
+ char *end;
+ char *colon;
-#ifdef __linux__
- neon_flags = orc_check_neon_proc_auxv ();
-#endif
-#ifdef unused
-#ifdef __linux__
- int arm_implementer = 0;
+ flags = strstr(cpuinfo,tag);
+ if (flags == NULL) return NULL;
+
+ end = strchr(flags, '\n');
+ if (end == NULL) return NULL;
+ colon = strchr (flags, ':');
+ if (colon == NULL) return NULL;
+ colon++;
+ if(colon >= end) return NULL;
+
+ return _strndup (colon, end-colon);
+}
+
+static unsigned long
+orc_cpu_arm_getflags_cpuinfo ()
+{
+ unsigned long ret = 0;
char *cpuinfo;
- char *s;
+ char *cpuinfo_line;
+ char **flags;
+ char **f;
cpuinfo = get_proc_cpuinfo();
- if (cpuinfo == NULL) return;
+ if (cpuinfo == NULL) {
+ ORC_DEBUG ("Failed to read /proc/cpuinfo");
+ return 0;
+ }
+
+ cpuinfo_line = get_cpuinfo_line(cpuinfo, "CPU architecture");
+ if (cpuinfo_line) {
+ int arm_arch = strtoul (cpuinfo_line, NULL, 0);
+ if (arm_arch >= 8L) {
+ /* Armv8 always supports these, but they won't be listed
+ * in the CPU info optional features */
+ ret = ORC_TARGET_ARM_EDSP | ORC_TARGET_NEON_NEON;
+ goto out;
+ }
- s = get_cpuinfo_line(cpuinfo, "CPU implementer");
- if (s) {
- arm_implementer = strtoul (s, NULL, 0);
- free(s);
+ free(cpuinfo_line);
}
- switch(arm_implementer) {
- case 0x69: /* Intel */
- case 0x41: /* ARM */
- /* ARM chips are known to not have timestamping available from
- * user space */
- break;
- default:
- break;
+ cpuinfo_line = get_cpuinfo_line(cpuinfo, "Features");
+ if (cpuinfo_line == NULL) {
+ free (cpuinfo);
+ return 0;
}
-#if 0
- s = get_cpuinfo_line(cpuinfo, "CPU architecture");
- if (s) {
- int arm_arch;
- arm_arch = strtoul (s, NULL, 0);
- if (arm_arch >= 6)
- orc_cpu_flags |= ORC_CPU_FLAG_ARM6;
- free(s);
+ flags = strsplit(cpuinfo_line, ' ');
+ for (f = flags; *f; f++) {
+ if (strcmp (*f, "edsp") == 0)
+ ret |= ORC_TARGET_ARM_EDSP;
+ else if (strcmp (*f, "neon") == 0)
+ ret |= ORC_TARGET_NEON_NEON;
+ free (*f);
}
-#endif
- orc_cpu_arm_getflags_cpuinfo (cpuinfo);
+ free (flags);
+
+out:
+ free (cpuinfo_line);
free (cpuinfo);
+
+ return ret;
+}
#endif
+
+unsigned long
+orc_arm_get_cpu_flags (void)
+{
+ unsigned long neon_flags = 0;
+
+#ifdef __linux__
+ neon_flags = orc_check_neon_proc_auxv ();
#endif
+#ifdef ANDROID
+ if (!neon_flags) {
+ /* On ARM, /proc/self/auxv might not be accessible.
+ * Fall back to /proc/cpuinfo */
+ neon_flags = orc_cpu_arm_getflags_cpuinfo ();
+ }
+#endif
+
if (orc_compiler_flag_check ("-neon")) {
neon_flags &= ~ORC_TARGET_NEON_NEON;
}