summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPirama Arumuga Nainar <pirama@google.com>2019-03-29 09:18:05 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-03-29 09:18:05 -0700
commit9fcdb3edafc261c67f1dc4f6de0b3337065e1e1f (patch)
treee7e6104b77f645ccf393e963aa8839084261ea48
parente6eff58534482daf2330129c1da72466a34f27f7 (diff)
parent41cb9915b20d3029cd195a6a9b3152eabf4daeea (diff)
downloadextras-9fcdb3edafc261c67f1dc4f6de0b3337065e1e1f.tar.gz
Merge changes from topic "coverage_flush"
am: 41cb9915b2 Change-Id: I8da9aa6f78d7f30f4dbbb52a804058accfef6905
-rw-r--r--toolchain-extras/Android.bp41
-rw-r--r--toolchain-extras/profile-extras-test.cpp59
-rw-r--r--toolchain-extras/profile-extras.cpp94
-rw-r--r--toolchain-extras/profile-extras.h19
4 files changed, 213 insertions, 0 deletions
diff --git a/toolchain-extras/Android.bp b/toolchain-extras/Android.bp
new file mode 100644
index 00000000..727f9795
--- /dev/null
+++ b/toolchain-extras/Android.bp
@@ -0,0 +1,41 @@
+cc_defaults {
+ name: "libprofile-defaults",
+ srcs: [
+ "profile-extras.cpp",
+ ],
+ native_coverage: false,
+}
+
+cc_library_static {
+ name: "libprofile-extras",
+ defaults: ["libprofile-defaults",],
+
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ recovery_available: true,
+
+ stl: "none",
+ system_shared_libs: [],
+ header_libs: ["libc_headers"],
+}
+
+cc_library_static {
+ name: "libprofile-extras_ndk",
+ defaults: ["libprofile-defaults",],
+
+ sdk_version: "minimum",
+}
+
+cc_test {
+ name: "libprofile-extras-test",
+ srcs: [
+ "profile-extras-test.cpp"
+ ],
+ static_libs: [
+ "libprofile-extras",
+ ],
+ ldflags: ["-uinit_profile_extras"],
+ native_coverage: false,
+}
diff --git a/toolchain-extras/profile-extras-test.cpp b/toolchain-extras/profile-extras-test.cpp
new file mode 100644
index 00000000..0cc4cef8
--- /dev/null
+++ b/toolchain-extras/profile-extras-test.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <sys/system_properties.h>
+
+#include "profile-extras.h"
+
+static int flush_count = 0;
+
+extern "C" {
+void __gcov_flush() {
+ flush_count++;
+}
+}
+
+static const char kCoveragePropName[] = "coverage.flush";
+
+TEST(profile_extras, smoke) {
+ flush_count = 0;
+
+ ASSERT_EQ(0, flush_count);
+ kill(getpid(), GCOV_FLUSH_SIGNAL);
+ sleep(2);
+ ASSERT_EQ(1, flush_count);
+
+ // kCoveragePropName from "0" -> "1" -> "0" -> "1" should trigger two flushes.
+ // transition 1
+ __system_property_set(kCoveragePropName, "0");
+ sleep(2);
+ ASSERT_EQ(1, flush_count);
+
+ __system_property_set(kCoveragePropName, "1");
+ sleep(2);
+ ASSERT_EQ(2, flush_count);
+
+ // transition 2
+ __system_property_set(kCoveragePropName, "0");
+ sleep(2);
+ ASSERT_EQ(2, flush_count);
+
+ __system_property_set(kCoveragePropName, "1");
+ sleep(2);
+ ASSERT_EQ(3, flush_count);
+}
diff --git a/toolchain-extras/profile-extras.cpp b/toolchain-extras/profile-extras.cpp
new file mode 100644
index 00000000..3af46a10
--- /dev/null
+++ b/toolchain-extras/profile-extras.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+
+// Use _system_properties.h to use __system_property_wait_any()
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#include "profile-extras.h"
+
+extern "C" {
+
+void __gcov_flush(void);
+
+static void gcov_signal_handler(__unused int signum) {
+ __gcov_flush();
+}
+
+static const char kCoveragePropName[] = "coverage.flush";
+
+// In a loop, wait for any change to sysprops and trigger a __gcov_flush when
+// <kCoveragePropName> sysprop transistions to "1" after a transistion to "0".
+void *property_watch_loop(__unused void *arg) {
+ uint32_t serial = 0;
+
+ // __gcov_flush is called on a state transition from 0 to 1. Initialize state
+ // to 1 so a process spinning up when the sysprop is already set does not
+ // immediately dump its coverage.
+ int previous_state = 1;
+
+ while (true) {
+ // Use deprecated __system_property_wait_any for backward compatibility.
+ serial = __system_property_wait_any(serial);
+ const struct prop_info *pi = __system_property_find(kCoveragePropName);
+ if (!pi)
+ continue;
+
+ char value[PROP_VALUE_MAX];
+ __system_property_read(pi, nullptr, value);
+ if (strcmp(value, "0") == 0) {
+ previous_state = 0;
+ } else if (strcmp(value, "1") == 0) {
+ if (previous_state == 0) {
+ __gcov_flush();
+ }
+ previous_state = 1;
+ }
+ }
+}
+
+// Initialize libprofile-extras:
+// - Install a signal handler that triggers __gcov_flush on <GCOV_FLUSH_SIGNAL>.
+// - Create a thread that calls __gcov_flush when <kCoveragePropName> sysprop
+// transistions to "1" after a transistion to "0".
+//
+// We want this initiazlier to run during load time.
+//
+// Just marking init_profile_extras() with __attribute__((constructor)) isn't
+// enough since the linker drops it from its output since no other symbol from
+// this static library is referenced.
+//
+// We force the linker to include init_profile_extras() by passing
+// '-uinit_profile_extras' to the linker (in build/soong).
+__attribute__((constructor)) int init_profile_extras(void) {
+ sighandler_t ret1 = signal(GCOV_FLUSH_SIGNAL, gcov_signal_handler);
+ if (ret1 == SIG_ERR) {
+ return -1;
+ }
+
+ pthread_t thread;
+ int error = pthread_create(&thread, nullptr, property_watch_loop, nullptr);
+ if (error != 0) {
+ return -1;
+ }
+ return 0;
+}
+}
diff --git a/toolchain-extras/profile-extras.h b/toolchain-extras/profile-extras.h
new file mode 100644
index 00000000..3e217eaf
--- /dev/null
+++ b/toolchain-extras/profile-extras.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <signal.h>
+
+#define GCOV_FLUSH_SIGNAL (__SIGRTMIN + 5)