Merge "Specify .cpu cortex-a15"
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index 00250a5..f163463 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -32,7 +32,6 @@
benchmark_src_files = \
benchmark_main.cpp \
math_benchmark.cpp \
- property_benchmark.cpp \
pthread_benchmark.cpp \
semaphore_benchmark.cpp \
stdio_benchmark.cpp \
@@ -41,7 +40,8 @@
unistd_benchmark.cpp \
# Build benchmarks for the device (with bionic's .so). Run with:
-# adb shell bionic-benchmarks
+# adb shell bionic-benchmarks32
+# adb shell bionic-benchmarks64
include $(CLEAR_VARS)
LOCAL_MODULE := bionic-benchmarks
LOCAL_MODULE_STEM_32 := bionic-benchmarks32
@@ -49,10 +49,29 @@
LOCAL_MULTILIB := both
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CFLAGS += $(benchmark_c_flags)
-LOCAL_SRC_FILES := $(benchmark_src_files)
+LOCAL_SRC_FILES := $(benchmark_src_files) property_benchmark.cpp
LOCAL_CXX_STL := libc++
include $(BUILD_EXECUTABLE)
+# We don't build a static benchmark executable because it's not usually
+# useful. If you're trying to run the current benchmarks on an older
+# release, it's (so far at least) always because you want to measure the
+# performance of the old release's libc, and a static benchmark isn't
+# going to let you do that.
+
+# Build benchmarks for the host (against glibc!). Run with:
+include $(CLEAR_VARS)
+LOCAL_MODULE := bionic-benchmarks-glibc
+LOCAL_MODULE_STEM_32 := bionic-benchmarks-glibc32
+LOCAL_MODULE_STEM_64 := bionic-benchmarks-glibc64
+LOCAL_MULTILIB := both
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_CFLAGS += $(benchmark_c_flags)
+LOCAL_LDFLAGS += -lrt
+LOCAL_SRC_FILES := $(benchmark_src_files)
+LOCAL_CXX_STL := libc++
+include $(BUILD_HOST_EXECUTABLE)
+
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
ifeq ($(TARGET_ARCH),x86)
LINKER = linker
@@ -63,13 +82,13 @@
endif
bionic-benchmarks-run-on-host: bionic-benchmarks $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
- if [ ! -d /system -o ! -d /system/bin ]; then \
- echo "Attempting to create /system/bin"; \
- sudo mkdir -p -m 0777 /system/bin; \
+ if [ ! -d /system ]; then \
+ echo "Attempting to create /system"; \
+ sudo mkdir -p -m 0777 /system; \
fi
mkdir -p $(TARGET_OUT_DATA)/local/tmp
- cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin
- cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
+ ln -fs `realpath $(TARGET_OUT)/bin` /system/
+ ln -fs `realpath $(TARGET_OUT)/etc` /system/
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
diff --git a/benchmarks/benchmark_main.cpp b/benchmarks/benchmark_main.cpp
index d60670b..815d56b 100644
--- a/benchmarks/benchmark_main.cpp
+++ b/benchmarks/benchmark_main.cpp
@@ -19,6 +19,7 @@
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <string>
#include <map>
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index 11db56d..92e5998 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -80,7 +80,7 @@
static void BM_pthread_mutex_lock_ERRORCHECK(int iters) {
StopBenchmarkTiming();
- pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+ pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@@ -94,7 +94,7 @@
static void BM_pthread_mutex_lock_RECURSIVE(int iters) {
StopBenchmarkTiming();
- pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+ pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index e899df7..386ea04 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -25,14 +25,19 @@
Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
-static void BM_stdio_fread(int iters, int chunk_size) {
+template <typename Fn>
+static void ReadWriteTest(int iters, int chunk_size, Fn f, bool buffered) {
StopBenchmarkTiming();
FILE* fp = fopen("/dev/zero", "rw");
char* buf = new char[chunk_size];
StartBenchmarkTiming();
+ if (!buffered) {
+ setvbuf(fp, 0, _IONBF, 0);
+ }
+
for (int i = 0; i < iters; ++i) {
- fread(buf, chunk_size, 1, fp);
+ f(buf, chunk_size, 1, fp);
}
StopBenchmarkTiming();
@@ -40,22 +45,23 @@
delete[] buf;
fclose(fp);
}
+
+static void BM_stdio_fread(int iters, int chunk_size) {
+ ReadWriteTest(iters, chunk_size, fread, true);
+}
BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
-
static void BM_stdio_fwrite(int iters, int chunk_size) {
- StopBenchmarkTiming();
- FILE* fp = fopen("/dev/zero", "rw");
- char* buf = new char[chunk_size];
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
- fwrite(buf, chunk_size, 1, fp);
- }
-
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
- delete[] buf;
- fclose(fp);
+ ReadWriteTest(iters, chunk_size, fwrite, true);
}
BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
+
+static void BM_stdio_fread_unbuffered(int iters, int chunk_size) {
+ ReadWriteTest(iters, chunk_size, fread, false);
+}
+BENCHMARK(BM_stdio_fread_unbuffered)->AT_COMMON_SIZES;
+
+static void BM_stdio_fwrite_unbuffered(int iters, int chunk_size) {
+ ReadWriteTest(iters, chunk_size, fwrite, false);
+}
+BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES;
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 22f6e8e..f093ec1 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -16,7 +16,9 @@
#include "benchmark.h"
+#include <unistd.h>
#include <sys/syscall.h>
+#include <sys/time.h>
#include <time.h>
static void BM_time_clock_gettime(int iters) {
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index 7e2ac30..94be1dd 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -41,6 +41,8 @@
}
BENCHMARK(BM_unistd_getpid_syscall);
+#if defined(__BIONIC__)
+
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
@@ -55,6 +57,8 @@
}
BENCHMARK(BM_unistd_gettid);
+#endif
+
static void BM_unistd_gettid_syscall(int iters) {
StartBenchmarkTiming();
diff --git a/libc/Android.mk b/libc/Android.mk
index ef1fb9b..13fc297 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -98,6 +98,7 @@
bionic/chown.cpp \
bionic/clearenv.cpp \
bionic/clock.cpp \
+ bionic/clock_getcpuclockid.cpp \
bionic/clock_nanosleep.cpp \
bionic/clone.cpp \
bionic/__cmsg_nxthdr.cpp \
diff --git a/libc/bionic/clock_getcpuclockid.cpp b/libc/bionic/clock_getcpuclockid.cpp
new file mode 100644
index 0000000..5511eb4
--- /dev/null
+++ b/libc/bionic/clock_getcpuclockid.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <time.h>
+
+#include "private/ErrnoRestorer.h"
+
+int clock_getcpuclockid(pid_t pid, clockid_t* clockid) {
+ ErrnoRestorer errno_restorer;
+
+ // The tid is stored in the top bits, but negated.
+ clockid_t result = ~static_cast<clockid_t>(pid) << 3;
+ // Bits 0 and 1: clock type (0 = CPUCLOCK_PROF, 1 = CPUCLOCK_VIRT, 2 = CPUCLOCK_SCHED).
+ result |= 2;
+ // Bit 2: thread (set) or process (clear). Bit 2 already 0.
+
+ timespec ts;
+ if (clock_getres(result, &ts) == -1) {
+ return ESRCH;
+ }
+
+ *clockid = result;
+ return 0;
+}
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
index 82e2b59..d1c4ad0 100644
--- a/libc/bionic/pthread_atfork.cpp
+++ b/libc/bionic/pthread_atfork.cpp
@@ -44,7 +44,7 @@
atfork_t* last;
};
-static pthread_mutex_t g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+static pthread_mutex_t g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static atfork_list_t g_atfork_list = { NULL, NULL };
void __bionic_atfork_run_prepare() {
@@ -73,7 +73,7 @@
}
}
- g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+ g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
}
void __bionic_atfork_run_parent() {
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index f27e4e5..90daf30 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -18,7 +18,9 @@
#define __ANDROID_DLEXT_H__
#include <stddef.h>
+#include <stdint.h>
#include <sys/cdefs.h>
+#include <sys/types.h> /* for off64_t */
__BEGIN_DECLS
diff --git a/libc/include/fts.h b/libc/include/fts.h
index da26a88..cde0349 100644
--- a/libc/include/fts.h
+++ b/libc/include/fts.h
@@ -35,6 +35,8 @@
#ifndef _FTS_H_
#define _FTS_H_
+#include <sys/types.h>
+
typedef struct {
struct _ftsent *fts_cur; /* current node */
struct _ftsent *fts_child; /* linked list of children */
@@ -111,8 +113,6 @@
char fts_name[1]; /* file name */
} FTSENT;
-#include <sys/cdefs.h>
-
__BEGIN_DECLS
FTSENT *fts_children(FTS *, int);
int fts_close(FTS *);
diff --git a/libc/include/machine/posix_limits.h b/libc/include/machine/posix_limits.h
index e5a299b..939a1de 100644
--- a/libc/include/machine/posix_limits.h
+++ b/libc/include/machine/posix_limits.h
@@ -41,7 +41,7 @@
#define _POSIX_CHILD_MAX 25
#define _POSIX_CHOWN_RESTRICTED 1 /* yes, chown requires appropriate privileges */
#define _POSIX_CLOCK_SELECTION 200809L
-#define _POSIX_CPUTIME -1 /* clock_getcpuclockid() not implemented */
+#define _POSIX_CPUTIME 200809L
#define _POSIX_DELAYTIMER_MAX 32
#define _POSIX_FSYNC 200809L /* fdatasync() supported */
#define _POSIX_HOST_NAME_MAX 255
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 24dba1b..2178789 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -53,9 +53,13 @@
#define __PTHREAD_RECURSIVE_MUTEX_INIT_VALUE 0x4000
#define __PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE 0x8000
-#define PTHREAD_MUTEX_INITIALIZER {__PTHREAD_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
-#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {__PTHREAD_RECURSIVE_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
-#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {__PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
+#define PTHREAD_MUTEX_INITIALIZER {__PTHREAD_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP {__PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {__PTHREAD_RECURSIVE_MUTEX_INIT_VALUE __RESERVED_INITIALIZER}
+
+/* TODO: remove this namespace pollution. */
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
enum {
PTHREAD_MUTEX_NORMAL = 0,
diff --git a/libc/include/sys/user.h b/libc/include/sys/user.h
index 0e36825..b370add 100644
--- a/libc/include/sys/user.h
+++ b/libc/include/sys/user.h
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <limits.h> /* For PAGE_SIZE. */
+#include <stddef.h> /* For size_t. */
__BEGIN_DECLS
diff --git a/libc/include/time.h b/libc/include/time.h
index e34eb34..1b0f6a1 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -85,6 +85,8 @@
extern clock_t clock(void) __LIBC_ABI_PUBLIC__;
+extern int clock_getcpuclockid(pid_t, clockid_t*) __LIBC_ABI_PUBLIC__;
+
extern int clock_getres(clockid_t, struct timespec*) __LIBC_ABI_PUBLIC__;
extern int clock_gettime(clockid_t, struct timespec*) __LIBC_ABI_PUBLIC__;
extern int clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) __LIBC_ABI_PUBLIC__;
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 2486e02..57b2c23 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -29,7 +29,7 @@
/* This file hijacks the symbols stubbed out in libdl.so. */
-static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static const char* __bionic_set_dlerror(char* new_value) {
char** dlerror_slot = &reinterpret_cast<char**>(__get_tls())[TLS_SLOT_DLERROR];
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index e0231b1..691d8ff 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -23,6 +23,7 @@
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#include "ScopedSignalHandler.h"
@@ -458,6 +459,34 @@
ASSERT_LT(t1 - t0, CLOCKS_PER_SEC / 1000);
}
+pid_t GetInvalidPid() {
+ FILE* fp = fopen("/proc/sys/kernel/pid_max", "r");
+ long pid_max;
+ fscanf(fp, "%ld", &pid_max);
+ pid_t invalid_pid = static_cast<pid_t>(pid_max + 1);
+ fclose(fp);
+ return invalid_pid;
+}
+
+TEST(time, clock_getcpuclockid) {
+ // For current process.
+ clockid_t clockid;
+ ASSERT_EQ(0, clock_getcpuclockid(getpid(), &clockid));
+
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(clockid, &ts));
+
+ // For parent process.
+ ASSERT_EQ(0, clock_getcpuclockid(getppid(), &clockid));
+ ASSERT_EQ(0, clock_gettime(clockid, &ts));
+
+ // For invalid process.
+ // We can't use -1 for invalid pid here, because clock_getcpuclockid() can't detect it.
+ errno = 0;
+ ASSERT_EQ(ESRCH, clock_getcpuclockid(GetInvalidPid(), &clockid));
+ ASSERT_EQ(0, errno);
+}
+
TEST(time, clock_settime) {
errno = 0;
timespec ts;
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f0aeb09..34b7bf3 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -529,6 +529,7 @@
EXPECT_GT(_POSIX_CHILD_MAX, 0);
EXPECT_NE(_POSIX_CHOWN_RESTRICTED, -1);
EXPECT_EQ(_POSIX_VERSION, _POSIX_CLOCK_SELECTION);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_CPUTIME);
EXPECT_GT(_POSIX_DELAYTIMER_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_FSYNC);
EXPECT_GT(_POSIX_HOST_NAME_MAX, 0);
@@ -614,7 +615,6 @@
EXPECT_EQ(-1, _POSIX_ADVISORY_INFO);
EXPECT_EQ(-1, _POSIX_ASYNCHRONOUS_IO);
EXPECT_EQ(-1, _POSIX_BARRIERS);
- EXPECT_EQ(-1, _POSIX_CPUTIME);
EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING);
EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO);
EXPECT_EQ(-1, _POSIX_REALTIME_SIGNALS);
@@ -665,6 +665,7 @@
VERIFY_SYSCONF_POSITIVE(_SC_CHILD_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_CLK_TCK);
VERIFY_SYSCONF_POSITIVE(_SC_COLL_WEIGHTS_MAX);
+ VERIFY_SYSCONF_POSIX_VERSION(_SC_CPUTIME);
VERIFY_SYSCONF_POSITIVE(_SC_EXPR_NEST_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_LINE_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_NGROUPS_MAX);
@@ -775,7 +776,6 @@
VERIFY_SYSCONF_NOT_SUPPORT(_SC_ADVISORY_INFO);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_ASYNCHRONOUS_IO);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_BARRIERS);
- VERIFY_SYSCONF_NOT_SUPPORT(_SC_CPUTIME);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_MESSAGE_PASSING);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_PRIORITIZED_IO);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_REALTIME_SIGNALS);