diff options
| author | John Hawthorn <john@hawthorn.email> | 2026-03-08 12:32:39 -0700 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2026-03-11 17:41:59 -0700 |
| commit | 764a245ef9e305a515a8be54b87c8b7b3ac45af0 (patch) | |
| tree | 4e7b8724a8e7547770a40efc5933416fcc55f129 | |
| parent | 21f2bbf322e955b1e393365d6190eaa38bdfc356 (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.c | 15 |
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 { |
