[K/N][Runtime] Fix deadlock in file initialization
Issue #KT-50491 Fixed
This commit is contained in:
@@ -24,8 +24,14 @@
|
||||
#include "ObjCExportInit.h"
|
||||
#include "Porting.h"
|
||||
#include "Runtime.h"
|
||||
#include "RuntimePrivate.hpp"
|
||||
#include "Worker.h"
|
||||
|
||||
using kotlin::internal::FILE_NOT_INITIALIZED;
|
||||
using kotlin::internal::FILE_BEING_INITIALIZED;
|
||||
using kotlin::internal::FILE_INITIALIZED;
|
||||
using kotlin::internal::FILE_FAILED_TO_INITIALIZE;
|
||||
|
||||
typedef void (*Initializer)(int initialize, MemoryState* memory);
|
||||
struct InitNode {
|
||||
Initializer init;
|
||||
@@ -410,11 +416,6 @@ RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeededFromKotlin() {
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr int FILE_NOT_INITIALIZED = 0;
|
||||
static constexpr int FILE_BEING_INITIALIZED = 1;
|
||||
static constexpr int FILE_INITIALIZED = 2;
|
||||
static constexpr int FILE_FAILED_TO_INITIALIZE = 3;
|
||||
|
||||
void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
||||
int localState = *state;
|
||||
if (localState == FILE_INITIALIZED) return;
|
||||
@@ -423,10 +424,13 @@ void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
||||
int threadId = konan::currentThreadId();
|
||||
if ((localState & 3) == FILE_BEING_INITIALIZED) {
|
||||
if ((localState & ~3) != (threadId << 2)) {
|
||||
// Switch to the native state to avoid dead-locks.
|
||||
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
|
||||
do {
|
||||
localState = *state;
|
||||
if (localState == FILE_FAILED_TO_INITIALIZE)
|
||||
ThrowFileFailedToInitializeException();
|
||||
// Call of a Kotlin function.
|
||||
kotlin::CallWithThreadState<kotlin::ThreadState::kRunnable>(ThrowFileFailedToInitializeException);
|
||||
} while (localState != FILE_INITIALIZED);
|
||||
}
|
||||
return;
|
||||
@@ -445,10 +449,13 @@ void CallInitGlobalPossiblyLock(int volatile* state, void (*init)()) {
|
||||
#endif
|
||||
*state = FILE_INITIALIZED;
|
||||
} else {
|
||||
// Switch to the native state to avoid dead-locks.
|
||||
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
|
||||
do {
|
||||
localState = *state;
|
||||
if (localState == FILE_FAILED_TO_INITIALIZE)
|
||||
ThrowFileFailedToInitializeException();
|
||||
// Call of a Kotlin function.
|
||||
kotlin::CallWithThreadState<kotlin::ThreadState::kRunnable>(ThrowFileFailedToInitializeException);
|
||||
} while (localState != FILE_INITIALIZED);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user