diff options
author | Pirama Arumuga Nainar <pirama@google.com> | 2019-03-29 09:32:11 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-03-29 09:32:11 -0700 |
commit | 2f3beb5690279b2fa48fc488b4a55b817d5d82ef (patch) | |
tree | a869b1372367db17fb31f1720ca221436ce59153 | |
parent | 60655630e813976d85750ab6a6b3b433aa1cf5cf (diff) | |
parent | 101b4d5d0e0cda4430150a1772daaf3635d1603d (diff) | |
download | extras-2f3beb5690279b2fa48fc488b4a55b817d5d82ef.tar.gz |
Merge changes from topic "coverage_flush" am: 41cb9915b2 am: 9fcdb3edaf
am: 101b4d5d0e
Change-Id: I3e205b4883c90d1f85ac7fe5c5aed1d751c778ba
-rw-r--r-- | toolchain-extras/Android.bp | 41 | ||||
-rw-r--r-- | toolchain-extras/profile-extras-test.cpp | 59 | ||||
-rw-r--r-- | toolchain-extras/profile-extras.cpp | 94 | ||||
-rw-r--r-- | toolchain-extras/profile-extras.h | 19 |
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) |