Merge "Do not resolve to real/absolute link in GCC 4.6 / 4.7"
diff --git a/sources/android/cpufeatures/cpu-features.c b/sources/android/cpufeatures/cpu-features.c
index 02ea74f..b941cdd 100644
--- a/sources/android/cpufeatures/cpu-features.c
+++ b/sources/android/cpufeatures/cpu-features.c
@@ -28,6 +28,8 @@
/* ChangeLog for this library:
*
+ * NDK r??: Add android_setCpu().
+ *
* NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
* VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt.
*
@@ -66,6 +68,7 @@
#include <errno.h>
static pthread_once_t g_once;
+static int g_inited;
static AndroidCpuFamily g_cpuFamily;
static uint64_t g_cpuFeatures;
static int g_cpuCount;
@@ -477,14 +480,30 @@
}
static void
+android_cpuInitFamily(void)
+{
+#if defined(__ARM_ARCH__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
+#elif defined(__i386__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86;
+#elif defined(_MIPS_ARCH)
+ g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
+#else
+ g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
+#endif
+}
+
+static void
android_cpuInit(void)
{
char* cpuinfo = NULL;
int cpuinfo_len;
- g_cpuFamily = DEFAULT_CPU_FAMILY;
+ android_cpuInitFamily();
+
g_cpuFeatures = 0;
g_cpuCount = 1;
+ g_inited = 1;
cpuinfo_len = get_file_size("/proc/cpuinfo");
if (cpuinfo_len < 0) {
@@ -650,8 +669,6 @@
#endif /* __ARM_ARCH__ */
#ifdef __i386__
- g_cpuFamily = ANDROID_CPU_FAMILY_X86;
-
int regs[4];
/* According to http://en.wikipedia.org/wiki/CPUID */
@@ -676,10 +693,6 @@
}
#endif
-#ifdef _MIPS_ARCH
- g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
-#endif /* _MIPS_ARCH */
-
free(cpuinfo);
}
@@ -707,6 +720,26 @@
return g_cpuCount;
}
+static void
+android_cpuInitDummy(void)
+{
+ g_inited = 1;
+}
+
+int
+android_setCpu(int cpu_count, uint64_t cpu_features)
+{
+ /* Fail if the library was already initialized. */
+ if (g_inited)
+ return 0;
+
+ android_cpuInitFamily();
+ g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
+ g_cpuFeatures = cpu_features;
+ pthread_once(&g_once, android_cpuInitDummy);
+
+ return 1;
+}
/*
* Technical note: Making sense of ARM's FPU architecture versions.
diff --git a/sources/android/cpufeatures/cpu-features.h b/sources/android/cpufeatures/cpu-features.h
index b6bf2ac..f8553e8 100644
--- a/sources/android/cpufeatures/cpu-features.h
+++ b/sources/android/cpufeatures/cpu-features.h
@@ -177,6 +177,19 @@
/* Return the number of CPU cores detected on this device. */
extern int android_getCpuCount(void);
+/* The following is used to force the CPU count and features
+ * mask in sandboxed processes. Under 4.1 and higher, these processes
+ * cannot access /proc, which is the only way to get information from
+ * the kernel about the current hardware (at least on ARM).
+ *
+ * It _must_ be called only once, and before any android_getCpuXXX
+ * function, any other case will fail.
+ *
+ * This function return 1 on success, and 0 on failure.
+ */
+extern int android_setCpu(int cpu_count,
+ uint64_t cpu_features);
+
__END_DECLS
#endif /* CPU_FEATURES_H */
diff --git a/tests/device/test-cpufeatures/jni/Android.mk b/tests/device/test-cpufeatures/jni/Android.mk
index 340f4dd..bc56410 100644
--- a/tests/device/test-cpufeatures/jni/Android.mk
+++ b/tests/device/test-cpufeatures/jni/Android.mk
@@ -6,4 +6,16 @@
LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_EXECUTABLE)
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_android_setCpu_1
+LOCAL_SRC_FILES := test_android_setCpu_1.c
+LOCAL_STATIC_LIBRARIES := cpufeatures
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_android_setCpu_2
+LOCAL_SRC_FILES := test_android_setCpu_2.c
+LOCAL_STATIC_LIBRARIES := cpufeatures
+include $(BUILD_EXECUTABLE)
+
$(call import-module,android/cpufeatures)
diff --git a/tests/device/test-cpufeatures/jni/test_android_setCpu_1.c b/tests/device/test-cpufeatures/jni/test_android_setCpu_1.c
new file mode 100644
index 0000000..cb51a5c
--- /dev/null
+++ b/tests/device/test-cpufeatures/jni/test_android_setCpu_1.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cpu-features.h"
+
+static void panic(const char* msg) {
+ fprintf(stderr, "ERROR: %s\n", msg);
+ exit(1);
+}
+
+int main(void) {
+ int count, cpu_count = 10;
+ uint64_t features, cpu_features = 0xaabdedf012934839ULL;
+
+ // Check that android_setCpu() can be called at program startup
+ // and that android_getCpuCount() and android_getCpuFeatures()
+ // will return the corresponding values.
+ //
+ printf("Setting cpu_count=%d, features=%08llx\n",
+ cpu_count,
+ cpu_features);
+ if (!android_setCpu(cpu_count, cpu_features))
+ panic("Cannot call android_setCpu() at program startup!");
+
+ count = android_getCpuCount();
+ features = android_getCpuFeatures();
+
+ printf("Retrieved cpu_count=%d, features=%08llx\n",
+ count, features);
+
+ if (count != cpu_count)
+ panic("android_getCpuCount() didn't return expected value!");
+
+ if (features != cpu_features)
+ panic("android_getCpuFeatures() didn't return expected value!");
+
+ // Once one of the android_getXXX functions has been called,
+ // android_setCpu() should always fail.
+ if (android_setCpu(cpu_count, cpu_features))
+ panic("android_setCpu() could be called twice!");
+
+ printf("Second call to android_setCpu() failed as expected.\n");
+ return 0;
+}
+
diff --git a/tests/device/test-cpufeatures/jni/test_android_setCpu_2.c b/tests/device/test-cpufeatures/jni/test_android_setCpu_2.c
new file mode 100644
index 0000000..2466066
--- /dev/null
+++ b/tests/device/test-cpufeatures/jni/test_android_setCpu_2.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cpu-features.h"
+
+static void panic(const char* msg) {
+ fprintf(stderr, "ERROR: %s\n", msg);
+ exit(1);
+}
+
+int main(void) {
+ int count, cpu_count = 10;
+ uint64_t features, cpu_features = 0xaabdedf012934839ULL;
+
+ count = android_getCpuCount();
+ features = android_getCpuFeatures();
+
+ printf("Retrieved cpu_count=%d, features=%08llx\n",
+ count, features);
+
+ // Check that android_setCpu() will fail when it is called after
+ // android_getCpuCount / android_getCpuFeatures.
+ //
+ printf("Trying to set cpu_count=%d, features=%08llx\n",
+ cpu_count,
+ cpu_features);
+
+ if (android_setCpu(cpu_count, cpu_features))
+ panic("android_setCpu() call should have failed!");
+
+ printf("android_setCpu() call fail as expected.\n");
+ return 0;
+}
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index bc931bd..48ba4ef 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -576,24 +576,42 @@
local PROGRAMS=
local PROGRAM
# Do not run the test if BROKEN_RUN is defined
- if [ -f "$TEST/BROKEN_RUN" -o -f "$TEST/BROKEN_BUILD" ] ; then
- if [ -z "$RUN_TESTS" ]; then
- dump "Skipping NDK device test run: `basename $TEST`"
- return 0
- fi
+ if [ -z "$RUN_TESTS" ]; then
+ if [ -f "$TEST/BROKEN_BUILD" ] ; then
+ dump "Skipping NDK device test not built: $TEST_NAME"
+ return 0
+ fi
+ if [ -f "$TEST/BROKEN_RUN" ] ; then
+ if [ ! -s "$TEST/BROKEN_RUN" ] ; then
+ # skip all
+ dump "Skipping NDK device test run: $TEST_NAME"
+ return 0
+ else
+ # only skip listed in file
+ SKIPPED_EXECUTABLES=`cat $TEST/BROKEN_RUN | tr '\n' ' '`
+ dump "Skipping NDK device test run: $TEST_NAME ($SKIPPED_EXECUTABLES)"
+ fi
+ fi
fi
SRCDIR="$BUILD_DIR/`basename $TEST`/libs/$CPU_ABI"
if [ ! -d "$SRCDIR" ]; then
- dump "Skipping NDK device test run (no $CPU_ABI binaries): `basename $TEST`"
+ dump "Skipping NDK device test run (no $CPU_ABI binaries): $TEST_NAME"
return 0
fi
- # First, copy all files to the device, except for gdbserver or gdb.setup.
+ # First, copy all files to the device, except for gdbserver, gdb.setup, and
+ # those declared in $TEST/BROKEN_RUN
adb_shell_mkdir "$DEVICE" $DSTDIR
for SRCFILE in `ls $SRCDIR`; do
DSTFILE=`basename $SRCFILE`
if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then
continue
fi
+ if [ -z "$RUN_TESTS" -a -f "$TEST/BROKEN_RUN" ]; then
+ grep -q -w -e "$DSTFILE" "$TEST/BROKEN_RUN"
+ if [ $? = 0 ] ; then
+ continue
+ fi
+ fi
SRCFILE="$SRCDIR/$SRCFILE"
if [ $HOST_OS = cygwin ]; then
SRCFILE=`cygpath -m $SRCFILE`