Thread cleanup handlers (#866)

This commit is contained in:
Nikolay Igotti
2017-09-19 14:58:33 +03:00
committed by GitHub
parent 1d26d30521
commit cf462965f5
4 changed files with 59 additions and 3 deletions
+50
View File
@@ -22,6 +22,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if !KONAN_NO_THREADS
#include <pthread.h>
#endif
#include <unistd.h>
#if KONAN_WINDOWS
#include <windows.h>
@@ -90,6 +93,53 @@ void consolePrintf(const char* format, ...) {
}
// Thread execution.
#if !KONAN_NO_THREADS
pthread_key_t terminationKey;
pthread_once_t terminationKeyOnceControl = PTHREAD_ONCE_INIT;
typedef void (*destructor_t)();
struct DestructorRecord {
struct DestructorRecord* next;
destructor_t destructor;
};
static void onThreadExitCallback(void* value) {
DestructorRecord* record = reinterpret_cast<DestructorRecord*>(value);
while (record != nullptr) {
record->destructor();
auto next = record->next;
free(record);
record = next;
}
}
static void onThreadExitInit() {
pthread_key_create(&terminationKey, onThreadExitCallback);
}
#endif // !KONAN_NO_THREADS
void onThreadExit(void (*destructor)()) {
#if KONAN_NO_THREADS
#ifdef KONAN_WASM
// No way to do that.
#else
::atexit(destructor);
#endif
#else // !KONAN_NO_THREADS
// We cannot use pthread_cleanup_push() as it is lexical scope bound.
pthread_once(&terminationKeyOnceControl, onThreadExitInit);
DestructorRecord* destructorRecord = (DestructorRecord*)calloc(1, sizeof(DestructorRecord));
destructorRecord->destructor = destructor;
destructorRecord->next =
reinterpret_cast<DestructorRecord*>(pthread_getspecific(terminationKey));
pthread_setspecific(terminationKey, destructorRecord);
#endif // !KONAN_NO_THREADS
}
// Process execution.
void abort() {
::abort();
+3
View File
@@ -33,6 +33,9 @@ uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes);
void abort();
void exit(int32_t status);
// Thread control.
void onThreadExit(void (*destructor)());
// String/byte operations.
// memcpy/memmove/memcmp are not here intentionally, as frequently implemented/optimized
// by C compiler.
+4 -3
View File
@@ -14,8 +14,6 @@
* limitations under the License.
*/
#include <stdio.h>
#include "Alloc.h"
#include "Exceptions.h"
#include "Memory.h"
@@ -82,8 +80,11 @@ void DeinitRuntime(RuntimeState* state) {
}
void Kotlin_initRuntimeIfNeeded() {
if (runtimeState == nullptr)
if (runtimeState == nullptr) {
runtimeState = InitRuntime();
// Register runtime deinit function at thread cleanup.
konan::onThreadExit(Kotlin_deinitRuntimeIfNeeded);
}
}
void Kotlin_deinitRuntimeIfNeeded() {
+2
View File
@@ -26,6 +26,8 @@ extern "C" {
RuntimeState* InitRuntime();
void DeinitRuntime(RuntimeState* state);
void Kotlin_initRuntimeIfNeeded();
void Kotlin_deinitRuntimeIfNeeded();
// Appends given node to an initializer list.
void AppendToInitializersTail(struct InitNode*);