-
Notifications
You must be signed in to change notification settings - Fork 321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SingleSource/Atomic] Add preliminary tests for atomic builtins. #94
Open
Logikable
wants to merge
2
commits into
llvm:main
Choose a base branch
from
Logikable:atomic_tests
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
add_subdirectory(C++11) | ||
add_subdirectory(Float) | ||
if(ARCH STREQUAL "Mips") | ||
add_subdirectory(Mips) | ||
endif() | ||
add_subdirectory(Float) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Link the Clang built libatomic. | ||
execute_process(COMMAND ${CMAKE_C_COMPILER} --print-file-name=libclang_rt.atomic.so | ||
OUTPUT_VARIABLE _path_to_libatomic | ||
OUTPUT_STRIP_TRAILING_WHITESPACE) | ||
if(NOT _path_to_libatomic STREQUAL "libclang_rt.atomic.so") | ||
get_directory_property(CURRENT_LINK_OPTIONS LINK_OPTIONS) | ||
get_filename_component(_libatomic_dir ${_path_to_libatomic} DIRECTORY) | ||
add_link_options("LINKER:${_path_to_libatomic},-rpath=${_libatomic_dir}") | ||
|
||
llvm_singlesource(PREFIX "libclang_rt-atomic-") | ||
set_directory_properties(LINK_OPTIONS ${CURRENT_LINK_OPTIONS}) | ||
endif() | ||
|
||
add_link_options("LINKER:-latomic") | ||
llvm_singlesource(PREFIX "latomic-") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Atomic runtime library tests | ||
|
||
======== | ||
|
||
These tests aim to capture real-world multithreaded use cases of atomic | ||
builtins. Each test focuses on a single atomic operation. Those using multiple | ||
operations can be compared with other tests using the same operations to isolate | ||
bugs to a single atomic operation. | ||
|
||
Each test consists of a "looper" body and a test script. The test script | ||
instantiates 10 threads, each running the looper. The loopers contend the same | ||
memory address, performing atomic operations on it. Each looper executes | ||
10^6 times for a total of 10^7 operations. The resultant value in the contended | ||
pointer is compared against a closed-form solution. It's expected that the two | ||
values equate. | ||
|
||
For example, a looper that increments the shared pointer is expected to end up | ||
with a value of 10^7. If its final value is not that, the test fails. | ||
|
||
Each test is performed on all relevant types. | ||
|
||
======== | ||
|
||
Future test writers should be aware that the set of all tests that appear to | ||
test atomicity is not the set of all tests that test atomicity. In fact, tests | ||
that may test atomicity on one processor may not test atomicity on a different | ||
processor. | ||
|
||
As such, test writers are encouraged to write nonatomic variants of their tests, | ||
and verify that they pass in a variety of scenarios. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
//===--- big_test.cc -- Testing big (17+ byte) objects ------------ C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file tests atomic operations on big objects with aligned memory | ||
// addresses. | ||
// | ||
// The types tested are: bigs. | ||
// The ops tested are: cmpxchg. | ||
// TODO: Test load/store, xchg. | ||
// | ||
// Please read the README before contributing. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <iostream> | ||
#include <thread> | ||
#include <vector> | ||
|
||
#include "util.h" | ||
|
||
// V >> 56 = 66, so to prevent 32-bit overflow, kExpected must be less than | ||
// 2^31 / 66 = 32 x 10^6. | ||
#ifdef SMALL_PROBLEM_SIZE | ||
static constexpr int kIterations = 1'000'000; | ||
#else | ||
static constexpr int kIterations = 3'000'000; | ||
#endif | ||
static constexpr int kExpected = kThreads * kIterations; | ||
static constexpr int kBigSize = 10; | ||
struct big_t { | ||
int v[kBigSize]; | ||
}; | ||
|
||
// The big struct cmpxchg test is identical to the numeric cmpxchg test, except | ||
// each element of the underlying array is incremented. | ||
void looper_big_cmpxchg(big_t *abig, int success_model, int fail_model) { | ||
for (int n = 0; n < kIterations; ++n) { | ||
big_t desired, expected = {}; | ||
do { | ||
desired = expected; | ||
for (int k = 0; k < kBigSize; ++k) | ||
desired.v[k]++; | ||
} while (!__atomic_compare_exchange(abig, &expected, &desired, true, | ||
success_model, fail_model)); | ||
} | ||
} | ||
|
||
void test_big_cmpxchg() { | ||
std::vector<std::thread> pool; | ||
for (int success_model : atomic_compare_exchange_models) { | ||
for (int fail_model : atomic_compare_exchange_models) { | ||
big_t abig = {}; | ||
for (int n = 0; n < kThreads; ++n) | ||
pool.emplace_back(looper_big_cmpxchg, &abig, success_model, fail_model); | ||
for (int n = 0; n < kThreads; ++n) | ||
pool[n].join(); | ||
pool.clear(); | ||
for (int n = 0; n < kBigSize; ++n) | ||
if (abig.v[n] != kExpected) | ||
fail(); | ||
} | ||
} | ||
} | ||
|
||
void test_big() { | ||
std::cout << "Testing big\n"; | ||
test_big_cmpxchg(); | ||
} | ||
|
||
int main() { | ||
test_big(); | ||
std::cout << "PASSED\n"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Testing big | ||
PASSED | ||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
//===--- float_test.cc -- Testing aligned floating point numbers -- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file tests atomic operations on floating point types with aligned | ||
// memory addresses. | ||
// | ||
// The types tested are: float, double, float128. | ||
// The ops tested are: xchg, cmpxchg. | ||
// | ||
// Please read the README before contributing. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <sys/stat.h> | ||
|
||
#include <iostream> | ||
#include <thread> | ||
#include <vector> | ||
|
||
#include "util.h" | ||
|
||
// There are 23-bits in the mantissa of a single-precision float. | ||
// Therefore, kExpected cannot exceed 2^24. | ||
static constexpr int kIterations = 1'500'000; | ||
static constexpr int kExpected = kThreads * kIterations; | ||
|
||
// See int_aligned_test.cc for an explanation of xchg tests. | ||
template <typename T> | ||
void looper_float_scalar_xchg(T *afloat, int model) { | ||
__int128_t error = 0; | ||
T next = *afloat + 1; | ||
T result; | ||
for (int n = 0; n < kIterations; ++n) { | ||
__atomic_exchange(afloat, &next, &result, model); | ||
error += | ||
static_cast<__int128_t>(next) - static_cast<__int128_t>(result + 1); | ||
next = result + 1; | ||
} | ||
__atomic_fetch_sub(afloat, static_cast<T>(error), model); | ||
} | ||
|
||
template <typename T> | ||
void test_float_scalar_xchg() { | ||
std::vector<std::thread> pool; | ||
for (int model : atomic_exchange_models) { | ||
T afloat = 0; | ||
for (int n = 0; n < kThreads; ++n) | ||
pool.emplace_back(looper_float_scalar_xchg<T>, &afloat, model); | ||
for (int n = 0; n < kThreads; ++n) | ||
pool[n].join(); | ||
pool.clear(); | ||
if (afloat != kExpected) | ||
fail(); | ||
} | ||
} | ||
|
||
// See int_aligned_test.cc for an explanation of cmpxchg tests. | ||
template <typename T> | ||
void looper_float_scalar_cmpxchg(T *afloat, int success_model, int fail_model) { | ||
for (int n = 0; n < kIterations; ++n) { | ||
T desired, expected = 0; | ||
do { | ||
desired = expected + 1; | ||
} while (!__atomic_compare_exchange(afloat, &expected, &desired, true, | ||
success_model, fail_model)); | ||
} | ||
} | ||
|
||
template <typename T> | ||
void test_float_scalar_cmpxchg() { | ||
std::vector<std::thread> pool; | ||
for (int success_model : atomic_compare_exchange_models) { | ||
for (int fail_model : atomic_compare_exchange_models) { | ||
T afloat = 0; | ||
for (int n = 0; n < kThreads; ++n) | ||
pool.emplace_back(looper_float_scalar_cmpxchg<T>, &afloat, | ||
success_model, fail_model); | ||
for (int n = 0; n < kThreads; ++n) | ||
pool[n].join(); | ||
pool.clear(); | ||
if (afloat != kExpected) | ||
fail(); | ||
} | ||
} | ||
} | ||
|
||
void test_floating_point() { | ||
std::cout << "Testing float\n"; | ||
test_float_scalar_xchg<float>(); | ||
test_float_scalar_cmpxchg<float>(); | ||
|
||
std::cout << "Testing double\n"; | ||
test_float_scalar_xchg<double>(); | ||
test_float_scalar_cmpxchg<double>(); | ||
|
||
std::cout << "Testing float128\n"; | ||
test_float_scalar_xchg<__float128>(); | ||
test_float_scalar_cmpxchg<__float128>(); | ||
} | ||
|
||
int main() { | ||
test_floating_point(); | ||
std::cout << "PASSED\n"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Testing float | ||
Testing double | ||
Testing float128 | ||
PASSED | ||
exit 0 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That library isn't built by default, so almost nobody will have a copy. I assume we need to have some conditionals here to skip testing if the library isn't present?
Potentially we should additionally integration-test against
-latomic
(even if that comes via GCC), since that's what real users actually specify.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I'm not great with CMake -- what are better ways to do what I have here?