Serene Runtime 1.0.0
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#include <sys/mman.h>
26
27#ifdef __APPLE__
28#define STACK_FLAGS MAP_PRIVATE | MAP_ANONYMOUS
29#else
30#define STACK_FLAGS MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_STACK
31#endif
32
33// NOLINTBEGIN(hicpp-sign*, performance-no-int*)
35 const size_t os_page_size = srn_mm_get_os_page_size();
36 const size_t desired_size = size ? size : (size_t)SRN_FIBER_DEFAULT_STACK_SIZE;
37
38 // Round upto a multiple of PAGE size
39 const size_t usable = (desired_size + os_page_size - 1) & ~(os_page_size - 1);
40 // Add a page to act as a guard page
41 const size_t total = usable + os_page_size;
42
43 // Since stack grows downward, the starting point where mmap returns will
44 // be the end of the stack for us. We could of used MAP_GROWSDOWN to
45 // change the behaviour, but that causes the stack to grow, but we have
46 // a fix stack.
47 void *end = mmap(nullptr, total, PROT_READ | PROT_WRITE, STACK_FLAGS,
48 // according to the man page, for anonymous mode fd should be -1
49 -1,
50 // according to the man page, for anonymous mode offset should be 0
51 0);
52
53 PANIC_IF(end == MAP_FAILED, "Failed to allocate the stack for the fiber subsystem");
54
55 if (mprotect(end, os_page_size, PROT_NONE) == -1) {
56 munmap(end, total);
57 PANIC("Failed to allocate the guard page for the fiber subsystem");
58 }
59
60 const uintptr_t start = (uintptr_t)end + (uintptr_t)total;
61 const uintptr_t limit = (uintptr_t)end + (uintptr_t)os_page_size;
62
63 srn_fiber_stack_t stack = {.start = (void *)start, .limit = (void *)limit, .guard = end};
64 return stack;
65}
66
68 munmap(stack.guard, (uintptr_t)stack.start - (uintptr_t)stack.guard);
69}
70// NOLINTEND(hicpp-sign*, performance-no-int*)
static atomic_int total
Definition 05_parallel.c:42
size_t srn_mm_get_os_page_size(void)
Retutrns the OS page size.
Definition default.c:270
AI Generated (🤦) Fiber subsystem overview.
#define SRN_FIBER_DEFAULT_STACK_SIZE
Default size of every fiber stack.
Definition fiber.h:138
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...
Definition stack_posix.c:34
#define STACK_FLAGS
Definition stack_posix.c:30
void srn_fiber_stack_free(srn_fiber_stack_t stack)
Definition stack_posix.c:67
One stack per fiber, mapped with a guard page at the low end so an overflow faults deterministically ...
Definition fiber.h:168
void * guard
The protected page to detect stack overflows.
Definition fiber.h:174
void * start
High end, stack pointer initialises to this address.
Definition fiber.h:170
#define PANIC_IF(cond, msg)
Definition utils.h:57
#define PANIC(msg)
Definition utils.h:51