Bug 1803322 - Use non-inlinable thread-local helpers in TestNativeNt and TestSafeThreadLocal. r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D163487
This commit is contained in:
Yannis Juglaret 2022-12-01 14:13:29 +00:00
parent 8b95e44d5b
commit 40af2563e6
2 changed files with 22 additions and 10 deletions

View file

@ -25,10 +25,16 @@ MOZ_NEVER_INLINE PVOID SwapThreadLocalStoragePointer(PVOID aNewValue) {
static mozilla::freestanding::SafeThreadLocal<int*> gTheStorage;
// Need non-inline functions to bypass compiler optimization that the thread
// local storage pointer is cached in a register before accessing a thread-local
// variable. See bug 1803322 for a motivating example.
MOZ_NEVER_INLINE int* getTheStorage() { return gTheStorage.get(); }
MOZ_NEVER_INLINE void setTheStorage(int* p) { gTheStorage.set(p); }
static unsigned int __stdcall TestNonMainThread(void* aArg) {
for (int i = 0; i < 100; ++i) {
gTheStorage.set(&i);
if (gTheStorage.get() != &i) {
setTheStorage(&i);
if (getTheStorage() != &i) {
printf(
"TEST-FAILED | TestSafeThreadLocal | "
"A value is not correctly stored in the thread-local storage.\n");
@ -43,7 +49,7 @@ extern "C" int wmain(int argc, wchar_t* argv[]) {
auto origHead = SwapThreadLocalStoragePointer(nullptr);
// Setting gTheStorage when TLS is null.
gTheStorage.set(&dummy);
setTheStorage(&dummy);
SwapThreadLocalStoragePointer(origHead);
nsAutoHandle handles[8];
@ -53,7 +59,7 @@ extern "C" int wmain(int argc, wchar_t* argv[]) {
}
for (int i = 0; i < 100; ++i) {
if (gTheStorage.get() != &dummy) {
if (getTheStorage() != &dummy) {
printf(
"TEST-FAILED | TestSafeThreadLocal | "
"A value is not correctly stored in the global scope.\n");

View file

@ -28,6 +28,12 @@ const wchar_t kPrefixedHex16[] = L"Pabcdef0123456789.dll";
const uint32_t kTlsDataValue = 1234;
static MOZ_THREAD_LOCAL(uint32_t) sTlsData;
// Need non-inline functions to bypass compiler optimization that the thread
// local storage pointer is cached in a register before accessing a thread-local
// variable. See bug 1803322 for a motivating example.
MOZ_NEVER_INLINE uint32_t getTlsData() { return sTlsData.get(); }
MOZ_NEVER_INLINE void setTlsData(uint32_t x) { sTlsData.set(x); }
const char kFailFmt[] =
"TEST-FAILED | NativeNt | %s(%s) should have returned %s but did not\n";
@ -419,13 +425,13 @@ int wmain(int argc, wchar_t* argv[]) {
bool isExceptionThrown = false;
// Touch sTlsData.get() several times to prevent the call to sTlsData.set()
// from being optimized out in PGO build.
printf("sTlsData#1 = %08x\n", sTlsData.get());
printf("sTlsData#1 = %08x\n", getTlsData());
MOZ_SEH_TRY {
// Need to call SwapThreadLocalStoragePointer inside __try to make sure
// accessing sTlsData is caught by SEH. This is due to clang's design.
// https://bugs.llvm.org/show_bug.cgi?id=44174.
origTlsHead = SwapThreadLocalStoragePointer(nullptr);
sTlsData.set(~kTlsDataValue);
setTlsData(~kTlsDataValue);
}
MOZ_SEH_EXCEPT(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER
@ -433,10 +439,10 @@ int wmain(int argc, wchar_t* argv[]) {
isExceptionThrown = true;
}
SwapThreadLocalStoragePointer(origTlsHead);
printf("sTlsData#2 = %08x\n", sTlsData.get());
sTlsData.set(kTlsDataValue);
printf("sTlsData#3 = %08x\n", sTlsData.get());
if (!isExceptionThrown || sTlsData.get() != kTlsDataValue) {
printf("sTlsData#2 = %08x\n", getTlsData());
setTlsData(kTlsDataValue);
printf("sTlsData#3 = %08x\n", getTlsData());
if (!isExceptionThrown || getTlsData() != kTlsDataValue) {
printf(
"TEST-FAILED | NativeNt | RtlGetThreadLocalStoragePointer() is "
"broken\n");