Merge changes I80c0a510,I11ea200f,Ibc48e838

* changes:
  bionic: add vdso clock_getres
  bionic: benchmark: add clock_getres performance tests
  bionic: benchmark: additional clock_gettime performance tests
diff --git a/benchmarks/suites/vdso.xml b/benchmarks/suites/vdso.xml
new file mode 100644
index 0000000..1f5958c
--- /dev/null
+++ b/benchmarks/suites/vdso.xml
@@ -0,0 +1,51 @@
+<fn>
+  <name>BM_time_clock_getres</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_BOOTTIME</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_MONOTONIC_COARSE</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_MONOTONIC_RAW</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_REALTIME</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_REALTIME_COARSE</name>
+</fn>
+<fn>
+  <name>BM_time_clock_getres_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_BOOTTIME</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_MONOTONIC_COARSE</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_MONOTONIC_RAW</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_REALTIME</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_REALTIME_COARSE</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_time</name>
+</fn>
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
index 33e506e..3020c27 100644
--- a/benchmarks/tests/interface_test.cpp
+++ b/benchmarks/tests/interface_test.cpp
@@ -435,7 +435,19 @@
     "BM_string_strstr/32768/0/0/iterations:1\n"
     "BM_string_strstr/65536/0/0/iterations:1\n"
     "BM_string_strstr/131072/0/0/iterations:1\n"
+    "BM_time_clock_getres/iterations:1\n"
+    "BM_time_clock_getres_BOOTTIME/iterations:1\n"
+    "BM_time_clock_getres_MONOTONIC_COARSE/iterations:1\n"
+    "BM_time_clock_getres_MONOTONIC_RAW/iterations:1\n"
+    "BM_time_clock_getres_REALTIME/iterations:1\n"
+    "BM_time_clock_getres_REALTIME_COARSE/iterations:1\n"
+    "BM_time_clock_getres_syscall/iterations:1\n"
     "BM_time_clock_gettime/iterations:1\n"
+    "BM_time_clock_gettime_BOOTTIME/iterations:1\n"
+    "BM_time_clock_gettime_MONOTONIC_COARSE/iterations:1\n"
+    "BM_time_clock_gettime_MONOTONIC_RAW/iterations:1\n"
+    "BM_time_clock_gettime_REALTIME/iterations:1\n"
+    "BM_time_clock_gettime_REALTIME_COARSE/iterations:1\n"
     "BM_time_clock_gettime_syscall/iterations:1\n"
     "BM_time_gettimeofday/iterations:1\n"
     "BM_time_gettimeofday_syscall/iterations:1\n"
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 4c6d5dd..437dc78 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -23,6 +23,7 @@
 #include "util.h"
 
 static void BM_time_clock_gettime(benchmark::State& state) {
+  // CLOCK_MONOTONIC is required supported in vdso
   timespec t;
   while (state.KeepRunning()) {
     clock_gettime(CLOCK_MONOTONIC, &t);
@@ -31,6 +32,7 @@
 BIONIC_BENCHMARK(BM_time_clock_gettime);
 
 static void BM_time_clock_gettime_syscall(benchmark::State& state) {
+  // CLOCK_MONOTONIC is required supported in vdso
   timespec t;
   while (state.KeepRunning()) {
     syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
@@ -38,6 +40,114 @@
 }
 BIONIC_BENCHMARK(BM_time_clock_gettime_syscall);
 
+static void BM_time_clock_gettime_MONOTONIC_COARSE(benchmark::State& state) {
+  // CLOCK_MONOTONIC_COARSE is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_gettime(CLOCK_MONOTONIC_COARSE, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_gettime_MONOTONIC_COARSE);
+
+static void BM_time_clock_gettime_MONOTONIC_RAW(benchmark::State& state) {
+  // CLOCK_MONOTONIC_RAW is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_gettime(CLOCK_MONOTONIC_RAW, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_gettime_MONOTONIC_RAW);
+
+static void BM_time_clock_gettime_REALTIME(benchmark::State& state) {
+  // CLOCK_REALTIME is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_gettime(CLOCK_REALTIME, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_gettime_REALTIME);
+
+static void BM_time_clock_gettime_REALTIME_COARSE(benchmark::State& state) {
+  // CLOCK_REALTIME_COARSE is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_gettime(CLOCK_REALTIME_COARSE, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_gettime_REALTIME_COARSE);
+
+static void BM_time_clock_gettime_BOOTTIME(benchmark::State& state) {
+  // CLOCK_BOOTTIME is optionally supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_gettime(CLOCK_BOOTTIME, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_gettime_BOOTTIME);
+
+static void BM_time_clock_getres(benchmark::State& state) {
+  // CLOCK_MONOTONIC is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_MONOTONIC, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres);
+
+static void BM_time_clock_getres_syscall(benchmark::State& state) {
+  // CLOCK_MONOTONIC is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    syscall(__NR_clock_getres, CLOCK_MONOTONIC, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_syscall);
+
+static void BM_time_clock_getres_MONOTONIC_COARSE(benchmark::State& state) {
+  // CLOCK_MONOTONIC_COARSE is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_MONOTONIC_COARSE, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_MONOTONIC_COARSE);
+
+static void BM_time_clock_getres_MONOTONIC_RAW(benchmark::State& state) {
+  // CLOCK_MONOTONIC_RAW is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_MONOTONIC_RAW, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_MONOTONIC_RAW);
+
+static void BM_time_clock_getres_REALTIME(benchmark::State& state) {
+  // CLOCK_REALTIME is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_REALTIME, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_REALTIME);
+
+static void BM_time_clock_getres_REALTIME_COARSE(benchmark::State& state) {
+  // CLOCK_REALTIME_COARSE is required supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_REALTIME_COARSE, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_REALTIME_COARSE);
+
+static void BM_time_clock_getres_BOOTTIME(benchmark::State& state) {
+  // CLOCK_BOOTTIME is optionally supported in vdso
+  timespec t;
+  while (state.KeepRunning()) {
+    clock_getres(CLOCK_BOOTTIME, &t);
+  }
+}
+BIONIC_BENCHMARK(BM_time_clock_getres_BOOTTIME);
+
 static void BM_time_gettimeofday(benchmark::State& state) {
   timeval tv;
   while (state.KeepRunning()) {
diff --git a/libc/arch-arm/syscalls/clock_getres.S b/libc/arch-arm/syscalls/__clock_getres.S
similarity index 82%
rename from libc/arch-arm/syscalls/clock_getres.S
rename to libc/arch-arm/syscalls/__clock_getres.S
index e101127..a81cf00 100644
--- a/libc/arch-arm/syscalls/clock_getres.S
+++ b/libc/arch-arm/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     mov     ip, r7
     .cfi_register r7, ip
     ldr     r7, =__NR_clock_getres
@@ -13,4 +13,5 @@
     bxls    lr
     neg     r0, r0
     b       __set_errno_internal
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/arch-arm64/syscalls/clock_getres.S b/libc/arch-arm64/syscalls/__clock_getres.S
similarity index 78%
rename from libc/arch-arm64/syscalls/clock_getres.S
rename to libc/arch-arm64/syscalls/__clock_getres.S
index 33fda8f..9d0deaa 100644
--- a/libc/arch-arm64/syscalls/clock_getres.S
+++ b/libc/arch-arm64/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     mov     x8, __NR_clock_getres
     svc     #0
 
@@ -11,4 +11,5 @@
     b.hi    __set_errno_internal
 
     ret
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/arch-mips/syscalls/clock_getres.S b/libc/arch-mips/syscalls/__clock_getres.S
similarity index 81%
rename from libc/arch-mips/syscalls/clock_getres.S
rename to libc/arch-mips/syscalls/__clock_getres.S
index 153f629..c5eed97 100644
--- a/libc/arch-mips/syscalls/clock_getres.S
+++ b/libc/arch-mips/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     .set noreorder
     .cpload $t9
     li $v0, __NR_clock_getres
@@ -16,4 +16,5 @@
     j $t9
     nop
     .set reorder
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/arch-mips64/syscalls/clock_getres.S b/libc/arch-mips64/syscalls/__clock_getres.S
similarity index 85%
rename from libc/arch-mips64/syscalls/clock_getres.S
rename to libc/arch-mips64/syscalls/__clock_getres.S
index 32fac1a..fb871c9 100644
--- a/libc/arch-mips64/syscalls/clock_getres.S
+++ b/libc/arch-mips64/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     .set push
     .set noreorder
     li $v0, __NR_clock_getres
@@ -22,4 +22,5 @@
     j $t9
     move $ra, $t0
     .set pop
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/arch-x86/syscalls/clock_getres.S b/libc/arch-x86/syscalls/__clock_getres.S
similarity index 90%
rename from libc/arch-x86/syscalls/clock_getres.S
rename to libc/arch-x86/syscalls/__clock_getres.S
index 9466e08..b8c5374 100644
--- a/libc/arch-x86/syscalls/clock_getres.S
+++ b/libc/arch-x86/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
@@ -31,4 +31,5 @@
     popl    %ecx
     popl    %ebx
     ret
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/arch-x86_64/syscalls/clock_getres.S b/libc/arch-x86_64/syscalls/__clock_getres.S
similarity index 80%
rename from libc/arch-x86_64/syscalls/clock_getres.S
rename to libc/arch-x86_64/syscalls/__clock_getres.S
index f65d127..aff974e 100644
--- a/libc/arch-x86_64/syscalls/clock_getres.S
+++ b/libc/arch-x86_64/syscalls/__clock_getres.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_getres)
+ENTRY(__clock_getres)
     movl    $__NR_clock_getres, %eax
     syscall
     cmpq    $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
     call    __set_errno_internal
 1:
     ret
-END(clock_getres)
+END(__clock_getres)
+.hidden __clock_getres
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
index 969c39f..00d6490 100644
--- a/libc/bionic/vdso.cpp
+++ b/libc/bionic/vdso.cpp
@@ -42,6 +42,15 @@
   return __clock_gettime(clock_id, tp);
 }
 
+int clock_getres(int clock_id, timespec* tp) {
+  auto vdso_clock_getres = reinterpret_cast<decltype(&clock_getres)>(
+    __libc_globals->vdso[VDSO_CLOCK_GETRES].fn);
+  if (__predict_true(vdso_clock_getres)) {
+    return vdso_return(vdso_clock_getres(clock_id, tp));
+  }
+  return __clock_getres(clock_id, tp);
+}
+
 int gettimeofday(timeval* tv, struct timezone* tz) {
   auto vdso_gettimeofday = reinterpret_cast<decltype(&gettimeofday)>(
     __libc_globals->vdso[VDSO_GETTIMEOFDAY].fn);
@@ -54,6 +63,7 @@
 void __libc_init_vdso(libc_globals* globals, KernelArgumentBlock& args) {
   auto&& vdso = globals->vdso;
   vdso[VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, nullptr };
+  vdso[VDSO_CLOCK_GETRES] = { VDSO_CLOCK_GETRES_SYMBOL, nullptr };
   vdso[VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, nullptr };
 
   // Do we have a vdso?
diff --git a/libc/private/bionic_vdso.h b/libc/private/bionic_vdso.h
index 2d11cd6..ed11501 100644
--- a/libc/private/bionic_vdso.h
+++ b/libc/private/bionic_vdso.h
@@ -33,13 +33,16 @@
 
 #if defined(__aarch64__)
 #define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
+#define VDSO_CLOCK_GETRES_SYMBOL  "__kernel_clock_getres"
 #define VDSO_GETTIMEOFDAY_SYMBOL  "__kernel_gettimeofday"
 #else
 #define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
+#define VDSO_CLOCK_GETRES_SYMBOL  "__vdso_clock_getres"
 #define VDSO_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
 #endif
 
 extern "C" int __clock_gettime(int, timespec*);
+extern "C" int __clock_getres(int, timespec*);
 extern "C" int __gettimeofday(timeval*, struct timezone*);
 
 struct vdso_entry {
@@ -49,6 +52,7 @@
 
 enum {
   VDSO_CLOCK_GETTIME = 0,
+  VDSO_CLOCK_GETRES,
   VDSO_GETTIMEOFDAY,
   VDSO_END
 };