diff options
| author | Ryan Prichard <rprichard@google.com> | 2020-02-04 15:46:15 -0800 |
|---|---|---|
| committer | Ryan Prichard <rprichard@google.com> | 2020-03-09 14:23:24 -0700 |
| commit | 58cbfd9e7a8b59918164209faa1b4ef53d4f8eee (patch) | |
| tree | 7b9428a231ad5d6af10abea554a77c928741b5df /tests | |
| parent | 1082315ddf69e5bcb8ad0e95e1fd55d86e375e64 (diff) | |
Rewrite __cxa_atexit / __cxa_finalize
Simplify:
- Use a single memory-mapped region to hold the table of destructors.
Double its capacity each time it is expanded.
- Add a recompaction pass at the end of __cxa_finalize that shifts
entries forward and uses madvise to clean pages.
Bug: http://b/148055738
Test: bionic-unit-tests
Change-Id: Ieb9da2b88640a8a5277d217b43826b5b7e246781
(cherry picked from commit afa983c8d44400d45c1f0e2b8e90a8be04acf6f7)
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Android.bp | 1 | ||||
| -rw-r--r-- | tests/__cxa_atexit_test.cpp | 77 |
2 files changed, 78 insertions, 0 deletions
diff --git a/tests/Android.bp b/tests/Android.bp index 4bd96ad00..8b1eebc3f 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -79,6 +79,7 @@ cc_test_library { defaults: ["bionic_tests_defaults"], srcs: [ "__aeabi_read_tp_test.cpp", + "__cxa_atexit_test.cpp", "alloca_test.cpp", "android_get_device_api_level.cpp", "arpa_inet_test.cpp", diff --git a/tests/__cxa_atexit_test.cpp b/tests/__cxa_atexit_test.cpp new file mode 100644 index 000000000..6a122d1cb --- /dev/null +++ b/tests/__cxa_atexit_test.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 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 <cxxabi.h> +#include <gtest/gtest.h> + +TEST(__cxa_atexit, simple) { + int counter = 0; + + __cxxabiv1::__cxa_atexit([](void* arg) { ++*static_cast<int*>(arg); }, &counter, &counter); + + __cxxabiv1::__cxa_finalize(&counter); + ASSERT_EQ(counter, 1); + + // The handler won't be called twice. + __cxxabiv1::__cxa_finalize(&counter); + ASSERT_EQ(counter, 1); +} + +TEST(__cxa_atexit, order) { + static std::vector<int> actual; + + char handles[2]; + + auto append_to_actual = [](void* arg) { + int* idx = static_cast<int*>(arg); + actual.push_back(*idx); + delete idx; + }; + + for (int i = 0; i < 500; ++i) { + __cxxabiv1::__cxa_atexit(append_to_actual, new int{i}, &handles[i % 2]); + } + + __cxxabiv1::__cxa_finalize(&handles[0]); + + for (int i = 500; i < 750; ++i) { + __cxxabiv1::__cxa_atexit(append_to_actual, new int{i}, &handles[1]); + } + + __cxxabiv1::__cxa_finalize(&handles[1]); + + std::vector<int> expected; + for (int i = 498; i >= 0; i -= 2) expected.push_back(i); + for (int i = 749; i >= 500; --i) expected.push_back(i); + for (int i = 499; i >= 1; i -= 2) expected.push_back(i); + + ASSERT_EQ(expected.size(), actual.size()); + for (size_t i = 0; i < expected.size(); ++i) { + ASSERT_EQ(expected[i], actual[i]) << "index=" << i; + } +} |
