Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
stack_posix.c
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <[email protected]>
4 *
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#include <stdint.h>
20
21#include "serene/rt/fiber.h"
23#include "serene/utils.h"
24
25// POSIX stack backend, mmap-based allocation with a guard page. On a target without mmap (Windows)
26// this file compiles to nothing and a sibling backend should supply srn_fiber_stack_alloc/free
27// instead. The selection is by target macro, so the whole runtime source set can be handed to a
28// cross compiler and only the matching backend emits symbols.
29#if defined(__unix__) || defined(__APPLE__)
30
31# include <sys/mman.h>
32
33# ifdef __APPLE__
34# define STACK_FLAGS MAP_PRIVATE | MAP_ANONYMOUS
35# else
36# define STACK_FLAGS MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_STACK
37# endif
38
39// NOLINTBEGIN(hicpp-sign*, performance-no-int*)
41 const size_t os_page_size = srn_mm_get_os_page_size();
42 const size_t desired_size = size ? size : (size_t)SRN_FIBER_DEFAULT_STACK_SIZE;
43
44 // Reject sizes the page rounding below would wrap. A wrapped size would
45 // silently grant a one page stack instead of failing.
46 PANIC_IF(desired_size > SIZE_MAX - (2 * os_page_size), "Requested fiber stack size is too large");
47
48 // Round upto a multiple of PAGE size
49 const size_t usable = (desired_size + os_page_size - 1) & ~(os_page_size - 1);
50 // Add a page to act as a guard page
51 const size_t total = usable + os_page_size;
52
53 // Since stack grows downward, the starting point where mmap returns will be the end of the stack
54 // for us. We could of used MAP_GROWSDOWN to change the behaviour, but that causes the stack to
55 // grow, but we have a fix stack.
56 void *end = mmap(
57 nullptr, total, PROT_READ | PROT_WRITE, STACK_FLAGS,
58 // according to the man page, for anonymous mode fd should be -1
59 -1,
60 // according to the man page, for anonymous mode offset should be 0
61 0
62 );
63
64 PANIC_IF(end == MAP_FAILED, "Failed to allocate the stack for the fiber subsystem");
65
66 if (mprotect(end, os_page_size, PROT_NONE) == -1) {
67 munmap(end, total);
68 PANIC("Failed to allocate the guard page for the fiber subsystem");
69 }
70
71 const uintptr_t start = (uintptr_t)end + (uintptr_t)total;
72 const uintptr_t limit = (uintptr_t)end + (uintptr_t)os_page_size;
73
74 srn_fiber_stack_t stack = {.start = (void *)start, .limit = (void *)limit, .guard = end};
75 return stack;
76}
77
79 munmap(stack.guard, (uintptr_t)stack.start - (uintptr_t)stack.guard);
80}
81// NOLINTEND(hicpp-sign*, performance-no-int*)
82
83#endif // POSIX stack backend
static atomic_int total
Definition 05_parallel.c:40
size_t srn_mm_get_os_page_size(void)
Retutrns the OS page size.
Definition default.c:303
AI Generated (🤦) Fiber subsystem overview.
srn_fiber_stack_t srn_fiber_stack_alloc(size_t size)
Allocate a stack of at least size usable bytes plus a guard page, or SRN_FIBER_DEFAULT_STACK_SIZE whe...
void srn_fiber_stack_free(srn_fiber_stack_t stack)
#define SRN_FIBER_DEFAULT_STACK_SIZE
Default size of every fiber stack.
Definition fiber.h:180
One stack per fiber, mapped with a guard page at the low end so an overflow faults deterministically ...
Definition fiber.h:218
void * guard
The protected page to detect stack overflows.
Definition fiber.h:224
void * start
High end, stack pointer initialises to this address.
Definition fiber.h:220
#define PANIC_IF(cond, msg)
Definition utils.h:59
#define PANIC(msg)
Definition utils.h:53