[K/N][Runtime] Fix deadlock in file initialization

Issue #KT-50491 Fixed
This commit is contained in:
Ilya Matveev
2021-12-22 19:40:18 +07:00
committed by Space
parent fd63fed8b4
commit 2f32214106
4 changed files with 103 additions and 7 deletions
+14 -7
View File
@@ -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);
}
}