[K/N][runtime][codegen] Fixed a problem with synchronization
During globals initialization proper synchronization is required for ARM cpus #KT-53243 Fixed
This commit is contained in:
+1
-2
@@ -2421,9 +2421,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val bbExit = basicBlock("label_continue", null)
|
val bbExit = basicBlock("label_continue", null)
|
||||||
moveBlockAfterEntry(bbExit)
|
moveBlockAfterEntry(bbExit)
|
||||||
moveBlockAfterEntry(bbInit)
|
moveBlockAfterEntry(bbInit)
|
||||||
// TODO: Is it ok to use non-volatile read here since once value is FILE_INITIALIZED, it is no longer change?
|
|
||||||
val state = load(statePtr)
|
val state = load(statePtr)
|
||||||
LLVMSetVolatile(state, 1)
|
LLVMSetOrdering(state, LLVMAtomicOrdering.LLVMAtomicOrderingAcquire)
|
||||||
condBr(icmpEq(state, Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
condBr(icmpEq(state, Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
||||||
positionAtEnd(bbInit)
|
positionAtEnd(bbInit)
|
||||||
call(context.llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr),
|
call(context.llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr),
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "Worker.h"
|
#include "Worker.h"
|
||||||
#include "KString.h"
|
#include "KString.h"
|
||||||
#include "std_support/New.hpp"
|
#include "std_support/New.hpp"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#ifndef KONAN_NO_THREADS
|
#ifndef KONAN_NO_THREADS
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@@ -471,7 +472,10 @@ RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeededFromKotlin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void callInitGlobalPossiblyLockImpl(int volatile* state, void (*init)()) {
|
||||||
int localState = *state;
|
int localState = *state;
|
||||||
if (localState == FILE_INITIALIZED) return;
|
if (localState == FILE_INITIALIZED) return;
|
||||||
if (localState == FILE_FAILED_TO_INITIALIZE)
|
if (localState == FILE_FAILED_TO_INITIALIZE)
|
||||||
@@ -502,6 +506,7 @@ void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
std::atomic_thread_fence(std::memory_order_release);
|
||||||
*state = FILE_INITIALIZED;
|
*state = FILE_INITIALIZED;
|
||||||
} else {
|
} else {
|
||||||
// Switch to the native state to avoid dead-locks.
|
// Switch to the native state to avoid dead-locks.
|
||||||
@@ -514,6 +519,16 @@ void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
|||||||
} while (localState != FILE_INITIALIZED);
|
} while (localState != FILE_INITIALIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
NO_INLINE void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
||||||
|
callInitGlobalPossiblyLockImpl(state, init);
|
||||||
|
// Ensure proper synchronization around reading/writing of [state] (release barrier defined in callInitGlobalPossiblyLockImpl),
|
||||||
|
// also there is an acquire load of [state] in IrToBitcode.kt::evaluateFileGlobalInitializerCall.
|
||||||
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
void CallInitThreadLocal(int volatile* globalState, int* localState, void (*init)()) {
|
void CallInitThreadLocal(int volatile* globalState, int* localState, void (*init)()) {
|
||||||
if (*localState == FILE_FAILED_TO_INITIALIZE || (globalState != nullptr && *globalState == FILE_FAILED_TO_INITIALIZE))
|
if (*localState == FILE_FAILED_TO_INITIALIZE || (globalState != nullptr && *globalState == FILE_FAILED_TO_INITIALIZE))
|
||||||
|
|||||||
Reference in New Issue
Block a user