fix: update template, prevent double-spaced persisted kernel logs
This commit is contained in:
@@ -44,8 +44,22 @@ namespace montauk {
|
||||
ThreadEntry user_entry;
|
||||
void* user_arg;
|
||||
void* stack_base;
|
||||
int tid;
|
||||
ThreadCtx* next;
|
||||
};
|
||||
|
||||
inline ThreadCtx* g_thread_records = nullptr;
|
||||
inline volatile uint32_t g_thread_records_lock = 0;
|
||||
|
||||
inline void records_lock() {
|
||||
while (__atomic_exchange_n(&g_thread_records_lock, 1, __ATOMIC_ACQUIRE) != 0)
|
||||
montauk::yield();
|
||||
}
|
||||
|
||||
inline void records_unlock() {
|
||||
__atomic_store_n(&g_thread_records_lock, 0, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
// Userspace trampoline: bridges from the raw entry the kernel jumps
|
||||
// to into the typed entry, then funnels into SYS_THREAD_EXIT. We
|
||||
// route the exit through libc rather than relying on a kernel-side
|
||||
@@ -53,21 +67,24 @@ namespace montauk {
|
||||
// memory on this path.
|
||||
//
|
||||
// The thread's stack itself is intentionally not freed here: we are
|
||||
// still running on it. It is reclaimed when the process exits, or
|
||||
// the joiner may free it explicitly after thread_join.
|
||||
// still running on it. It is reclaimed by a successful thread_join,
|
||||
// or as part of whole-process teardown if the thread is never joined.
|
||||
[[noreturn]] inline void thread_trampoline(detail::ThreadCtx* ctx) {
|
||||
// A sibling CPU can start the thread before thread_spawn has
|
||||
// returned its TID. Wait until the parent has published the record
|
||||
// needed by thread_join to reclaim this stack.
|
||||
while (__atomic_load_n(&ctx->tid, __ATOMIC_ACQUIRE) == 0)
|
||||
montauk::yield();
|
||||
int code = ctx->user_entry(ctx->user_arg);
|
||||
montauk::mfree(ctx);
|
||||
thread_exit(code);
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn a new thread that begins executing `entry(arg)`. Returns the
|
||||
// new TID on success, or -1 on failure. The thread's stack is
|
||||
// allocated from the user heap; it is leaked on thread exit (the
|
||||
// thread itself cannot free the stack it is running on). The kernel
|
||||
// reclaims it on process exit. Callers that need to spawn many short-
|
||||
// lived threads should pool stacks themselves.
|
||||
// allocated from the user heap. The exiting thread cannot free the stack
|
||||
// it is running on, so thread_join reclaims both it and the trampoline
|
||||
// context after the kernel has reaped the sibling.
|
||||
inline int thread_spawn(ThreadEntry entry, void* arg,
|
||||
uint64_t stack_bytes = 0) {
|
||||
if (entry == nullptr) return -1;
|
||||
@@ -84,6 +101,8 @@ namespace montauk {
|
||||
ctx->user_entry = entry;
|
||||
ctx->user_arg = arg;
|
||||
ctx->stack_base = stack;
|
||||
ctx->tid = 0;
|
||||
ctx->next = nullptr;
|
||||
|
||||
uint64_t stack_top = ((uint64_t)stack + stack_bytes) & ~0xFULL;
|
||||
int tid = (int)syscall3(montauk::abi::SYS_THREAD_SPAWN,
|
||||
@@ -94,6 +113,11 @@ namespace montauk {
|
||||
montauk::mfree(stack);
|
||||
return -1;
|
||||
}
|
||||
detail::records_lock();
|
||||
ctx->next = detail::g_thread_records;
|
||||
detail::g_thread_records = ctx;
|
||||
__atomic_store_n(&ctx->tid, tid, __ATOMIC_RELEASE);
|
||||
detail::records_unlock();
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -101,8 +125,22 @@ namespace montauk {
|
||||
// success (with the thread's exit code in *out_code if non-null) or
|
||||
// -1 if `tid` is not a joinable sibling.
|
||||
inline int thread_join(int tid, int* out_code = nullptr) {
|
||||
return (int)syscall2(montauk::abi::SYS_THREAD_JOIN,
|
||||
(uint64_t)tid, (uint64_t)out_code);
|
||||
int result = (int)syscall2(montauk::abi::SYS_THREAD_JOIN,
|
||||
(uint64_t)tid, (uint64_t)out_code);
|
||||
if (result == 0) {
|
||||
detail::records_lock();
|
||||
detail::ThreadCtx** link = &detail::g_thread_records;
|
||||
while (*link != nullptr && (*link)->tid != tid)
|
||||
link = &(*link)->next;
|
||||
detail::ThreadCtx* ctx = *link;
|
||||
if (ctx != nullptr) *link = ctx->next;
|
||||
detail::records_unlock();
|
||||
if (ctx != nullptr) {
|
||||
montauk::mfree(ctx->stack_base);
|
||||
montauk::mfree(ctx);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return the calling thread's TID (== getpid() for the main thread).
|
||||
|
||||
Reference in New Issue
Block a user