summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2026-03-08 12:32:39 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2026-03-11 17:41:59 -0700
commit764a245ef9e305a515a8be54b87c8b7b3ac45af0 (patch)
tree4e7b8724a8e7547770a40efc5933416fcc55f129
parent21f2bbf322e955b1e393365d6190eaa38bdfc356 (diff)
Fix M:N threads under OpenBSD
OpenBSD requires MAP_STACK for memory regions used as thread stacks. However it seems to error with "Invalid argument" unless the permissions include both PROT_READ | PROT_WRITE. We should be able to satisft this by re-mmapping over our reserved stack region to get the MAP_STACK flag. As a (very minor) bonus, this applies MAP_STACK only to the machine stack region, not the VM region. Co-authored-by: Jeremy Evans <code@jeremyevans.net>
-rw-r--r--thread_pthread_mn.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/thread_pthread_mn.c b/thread_pthread_mn.c
index 569def6c0c..9651baf51f 100644
--- a/thread_pthread_mn.c
+++ b/thread_pthread_mn.c
@@ -189,12 +189,7 @@ nt_thread_stack_size(void)
static struct nt_stack_chunk_header *
nt_alloc_thread_stack_chunk(void)
{
- int mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE;
-#if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
- mmap_flags |= MAP_STACK;
-#endif
-
- const char *m = (void *)mmap(NULL, MSTACK_CHUNK_SIZE, PROT_NONE, mmap_flags, -1, 0);
+ const char *m = (void *)mmap(NULL, MSTACK_CHUNK_SIZE, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (m == MAP_FAILED) {
return NULL;
}
@@ -318,9 +313,15 @@ nt_alloc_stack(rb_vm_t *vm, void **vm_stack, void **machine_stack)
char *stack_start = nt_stack_chunk_get_stack_start(ch, idx);
size_t vm_stack_size = vm->default_params.thread_vm_stack_size;
size_t mstack_size = nt_thread_stack_size() - vm_stack_size - MSTACK_PAGE_SIZE;
+ char *mstack_start = stack_start + vm_stack_size + MSTACK_PAGE_SIZE;
+
+ int mstack_flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
+#if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
+ mstack_flags |= MAP_STACK;
+#endif
if (mprotect(stack_start, vm_stack_size, PROT_READ | PROT_WRITE) != 0 ||
- mprotect(stack_start + vm_stack_size + MSTACK_PAGE_SIZE, mstack_size, PROT_READ | PROT_WRITE) != 0) {
+ mmap(mstack_start, mstack_size, PROT_READ | PROT_WRITE, mstack_flags, -1, 0) == MAP_FAILED) {
err = errno;
}
else {