Kernel/LibC: Allocate thread stacks in userspace

This adds support for pthread function for stack manipulation.

Also keep track of main threads stack in the uthread
This commit is contained in:
2026-07-02 19:43:55 +03:00
parent 7bdd9d19d0
commit 0dc74beb0f
5 changed files with 51 additions and 25 deletions

View File

@@ -7,6 +7,7 @@
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/auxv.h>
#include <sys/futex.h>
#include <sys/mman.h>
#include <sys/syscall.h>
@@ -36,6 +37,7 @@ static void _init_pthread()
uthread->id = syscall(SYS_THREAD_GETID);
uthread->attr = s_default_pthread_attr;
uthread->errno_ = 0;
uthread->libc_owns_stack = false;
uthread->cancel_type = PTHREAD_CANCEL_DEFERRED;
uthread->cancel_state = PTHREAD_CANCEL_ENABLE;
uthread->canceled = false;
@@ -43,6 +45,11 @@ static void _init_pthread()
memset(uthread->specific_keys, 0, sizeof(uthread->specific_keys));
memset(uthread->specific_vals, 0, sizeof(uthread->specific_vals));
if (auto value = getauxval(AT_STACK_BASE))
uthread->attr.stackaddr = reinterpret_cast<void*>(value);
if (auto value = getauxval(AT_STACK_SIZE))
uthread->attr.stacksize = value;
signal(SIGCANCEL, &_pthread_cancel_handler);
}
@@ -120,6 +127,9 @@ static void free_uthread(uthread* uthread)
munmap(reinterpret_cast<void*>(uthread->dtv[i]), size);
}
if (uthread->libc_owns_stack)
munmap(static_cast<uint8_t*>(uthread->attr.stackaddr) - uthread->attr.guardsize, uthread->attr.guardsize + uthread->attr.stacksize);
uint8_t* tls_addr = reinterpret_cast<uint8_t*>(uthread) - uthread->master_tls_size;
const size_t tls_size = uthread->master_tls_size + sizeof(struct uthread);
munmap(tls_addr, tls_size);
@@ -288,6 +298,8 @@ int pthread_attr_getguardsize(const pthread_attr_t* __restrict attr, size_t* __r
int pthread_attr_setguardsize(pthread_attr_t* attr, size_t guardsize)
{
if (auto rem = guardsize % getpagesize())
guardsize += getpagesize() - rem;
attr->guardsize = guardsize;
return 0;
}
@@ -364,20 +376,22 @@ int pthread_attr_setscope(pthread_attr_t* attr, int contentionscope)
int pthread_attr_getstack(const pthread_attr_t* __restrict attr, void** __restrict stackaddr, size_t* __restrict stacksize)
{
(void)attr;
(void)stackaddr;
(void)stacksize;
dwarnln("TODO: pthread_attr_getstack");
return ENOTSUP;
*stackaddr = attr->stackaddr;
*stacksize = attr->stacksize;
return 0;
}
int pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize)
{
(void)attr;
(void)stackaddr;
(void)stacksize;
dwarnln("TODO: pthread_attr_setstack");
return ENOTSUP;
if (stacksize < PTHREAD_STACK_MIN)
return EINVAL;
if (reinterpret_cast<uintptr_t>(stackaddr) % getpagesize())
return EINVAL;
if (stacksize % getpagesize())
return EINVAL;
attr->stackaddr = stackaddr;
attr->stacksize = stacksize;
return 0;
}
int pthread_attr_getstacksize(const pthread_attr_t* __restrict attr, size_t* __restrict stacksize)
@@ -433,6 +447,7 @@ int pthread_create(pthread_t* __restrict thread, const pthread_attr_t* __restric
.id = -1,
.attr = attr ? *attr : s_default_pthread_attr,
.errno_ = 0,
.libc_owns_stack = false,
.cancel_type = PTHREAD_CANCEL_DEFERRED,
.cancel_state = PTHREAD_CANCEL_ENABLE,
.canceled = 0,
@@ -442,6 +457,21 @@ int pthread_create(pthread_t* __restrict thread, const pthread_attr_t* __restric
.dtv = { self->dtv[0] }
};
if (uthread->attr.stackaddr == nullptr)
{
ASSERT(uthread->attr.stacksize % getpagesize() == 0);
ASSERT(uthread->attr.guardsize % getpagesize() == 0);
void* stack_addr = mmap(nullptr, uthread->attr.guardsize + uthread->attr.stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (stack_addr == nullptr)
goto pthread_create_error;
uthread->attr.stackaddr = static_cast<uint8_t*>(stack_addr) + uthread->attr.guardsize;
uthread->libc_owns_stack = true;
if (uthread->attr.guardsize != 0 && mprotect(stack_addr, uthread->attr.guardsize, PROT_NONE) == -1)
goto pthread_create_error;
}
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
const uintptr_t uthread_addr = reinterpret_cast<uintptr_t>(uthread);
for (size_t i = 1; i <= self->master_tls_module_count; i++)
@@ -451,7 +481,7 @@ int pthread_create(pthread_t* __restrict thread, const pthread_attr_t* __restric
result = uthread;
}
if (syscall(SYS_THREAD_CREATE, _pthread_trampoline, info) == -1)
if (syscall(SYS_THREAD_CREATE, _pthread_trampoline, info, info->uthread->attr.stackaddr, info->uthread->attr.stacksize) == -1)
goto pthread_create_error;
if (thread)