Kotlin machine scheduling primitives. (#1677)

This commit is contained in:
Nikolay Igotti
2018-06-09 16:08:42 +03:00
committed by GitHub
parent 35043d4699
commit f4ac18b780
4 changed files with 82 additions and 0 deletions
+11
View File
@@ -1103,6 +1103,17 @@ void DeinitMemory(MemoryState* memoryState) {
::memoryState = nullptr;
}
MemoryState* SuspendMemory() {
auto result = ::memoryState;
::memoryState = nullptr;
return result;
}
void ResumeMemory(MemoryState* state) {
RuntimeAssert(::memoryState == nullptr, "Cannot schedule on existing state");
::memoryState = state;
}
OBJ_GETTER(AllocInstance, const TypeInfo* type_info) {
RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object");
if (isArenaSlot(OBJ_RESULT)) {
+3
View File
@@ -379,6 +379,9 @@ struct MemoryState;
MemoryState* InitMemory();
void DeinitMemory(MemoryState*);
MemoryState* SuspendMemory();
void ResumeMemory(MemoryState* state);
//
// Object allocation.
//
+52
View File
@@ -23,6 +23,7 @@
struct RuntimeState {
MemoryState* memoryState;
volatile int executionStatus;
};
typedef void (*Initializer)(int initialize);
@@ -42,6 +43,24 @@ enum {
DEINIT_GLOBALS = 2
};
enum {
SUSPENDED = 0,
RUNNING,
DESTROYING
};
bool updateStatusIf(RuntimeState* state, int oldStatus, int newStatus) {
#if KONAN_NO_THREADS
if (state->executionStatus == oldStatus) {
state->executionStatus = newStatus;
return true;
}
return false;
#else
return __sync_bool_compare_and_swap(&state->executionStatus, oldStatus, newStatus);
#endif
}
void InitOrDeinitGlobalVariables(int initialize) {
InitNode *currNode = initHeadNode;
while (currNode != nullptr) {
@@ -74,6 +93,7 @@ void deinitRuntime(RuntimeState* state) {
DeinitMemory(state->memoryState);
konanDestructInstance(state);
}
} // namespace
extern "C" {
@@ -91,6 +111,7 @@ void AppendToInitializersTail(InitNode *next) {
void Kotlin_initRuntimeIfNeeded() {
if (runtimeState == nullptr) {
runtimeState = initRuntime();
RuntimeCheck(updateStatusIf(runtimeState, SUSPENDED, RUNNING), "Cannot transition state to RUNNING for init");
// Register runtime deinit function at thread cleanup.
konan::onThreadExit(Kotlin_deinitRuntimeIfNeeded);
}
@@ -98,9 +119,40 @@ void Kotlin_initRuntimeIfNeeded() {
void Kotlin_deinitRuntimeIfNeeded() {
if (runtimeState != nullptr) {
RuntimeCheck(updateStatusIf(runtimeState, RUNNING, DESTROYING), "Cannot transition state to DESTROYING");
deinitRuntime(runtimeState);
runtimeState = nullptr;
}
}
RuntimeState* Kotlin_createRuntime() {
return initRuntime();
}
void Kotlin_destroyRuntime(RuntimeState* state) {
RuntimeCheck(updateStatusIf(state, SUSPENDED, DESTROYING), "Cannot transition state to DESTROYING");
deinitRuntime(state);
}
RuntimeState* Kotlin_suspendRuntime() {
RuntimeCheck(::runtimeState != nullptr, "Runtime must be active on the current thread");
auto result = ::runtimeState;
RuntimeCheck(updateStatusIf(result, RUNNING, SUSPENDED), "Cannot transition state to SUSPENDED for suspend");
result->memoryState = SuspendMemory();
::runtimeState = nullptr;
return result;
}
void Kotlin_resumeRuntime(RuntimeState* state) {
RuntimeCheck(::runtimeState == nullptr, "Runtime must not be active on the current thread");
RuntimeCheck(updateStatusIf(state, SUSPENDED, RUNNING), "Cannot transition state to RUNNING for resume");
::runtimeState = state;
ResumeMemory(state->memoryState);
}
RuntimeState* RUNTIME_USED Kotlin_getRuntime() {
RuntimeCheck(::runtimeState != nullptr, "Runtime must be active on the current thread");
return ::runtimeState;
}
} // extern "C"
+16
View File
@@ -29,6 +29,22 @@ extern "C" {
void RUNTIME_USED Kotlin_initRuntimeIfNeeded();
void RUNTIME_USED Kotlin_deinitRuntimeIfNeeded();
// Operations below allow flexible runtime scheduling on different threads.
// Created runtime is in SUSPENDED state, and need to be resumed for actual execution.
RuntimeState* RUNTIME_USED Kotlin_createRuntime();
// Runtime must be in SUSPENDED state, before it could be destroyed.
void RUNTIME_USED Kotlin_destroyRuntime(RuntimeState*);
// Transition current runtime from RUNNING to SUSPENDED state, and clearing thread local variable caching
// the runtime. After suspension, runtime could be rescheduled to a different thread.
RuntimeState* RUNTIME_USED Kotlin_suspendRuntime();
// Transition runtime from SUSPENDED to RUNNING state, and sets thread local variable caching
// the runtime. After resume, current thread could be used for executing Kotlin code.
void RUNTIME_USED Kotlin_resumeRuntime(RuntimeState*);
// Gets currently active runtime, nullptr if no runtime is currently available.
RuntimeState* RUNTIME_USED Kotlin_getRuntime();
// Appends given node to an initializer list.
void AppendToInitializersTail(struct InitNode*);