libpulsar
A modular compiler for the pulsar programming language
Loading...
Searching...
No Matches
arena.c
Go to the documentation of this file.
1// Copyright (C) 2021, 2023 Ethan Uppal. All rights reserved.
2
3#include "arena.h"
4#include <stdlib.h> // exit
5#include <stdint.h> // uint64_t
6#include <string.h> // memcpy
7#include <stdio.h> // fprintf
8#include <errno.h> // errno
9#include <sys/mman.h> // mmap
10#include <unistd.h> // sysconf
11#include <libgen.h> // basename
12#include "util/abort.h" // ps_exit, CHECK
13
14// TODO: fix up later
15#ifdef PS_DEBUG_ARENA
16 #define _PSDebug(...) fprintf(stderr, "arena: " __VA_ARGS__)
17#else
18 #define _PSDebug(...) /* nothing */
19#endif
20#define NUSED __attribute__((unused))
21
23
24void ps_arena_open(enum ps_arena_domain domain) {
25 CHECK({
26 if (domain < 0 || domain >= __PS_ARENA_COUNT) {
27 _PSDebug("Invalid arena domain: %d\n", domain);
28 ps_exit(EXIT_FAILURE);
29 }
30 })
31 struct ps_arena_allocator* arena = &arenas[domain];
32 arena->page_size = sysconf(_SC_PAGESIZE);
33 arena->start = mmap(NULL, PS_INITIAL_ARENA_MMAP, PROT_NONE,
34 MAP_ANON | MAP_PRIVATE, -1, 0);
35 mprotect(arena->start, arena->page_size, PROT_READ | PROT_WRITE);
36 if (arena->start == MAP_FAILED) {
37 _PSDebug("mmap: %s\n", strerror(errno));
38 ps_exit(EXIT_FAILURE);
39 }
40 arena->offset = 0;
41 _PSDebug("Arena initialized at %p with %llu bytes\n", arena->start,
43}
44
46 CHECK({
47 if (domain < 0 || domain >= __PS_ARENA_COUNT) {
48 _PSDebug("Invalid arena domain: %d\n", domain);
49 ps_exit(EXIT_FAILURE);
50 }
51 })
52 struct ps_arena_allocator* arena = &arenas[domain];
53 if (!arena->start) {
54 return;
55 }
56 munmap(arena->start, PS_INITIAL_ARENA_MMAP);
57 arena->start = NULL;
58 _PSDebug("Arena was destroyed using %lu out of %llu bytes\n", arena->offset,
60}
61
62#define _PS_ARENA_ALLOCATE(arena, n) \
63 do { \
64 if (arena->offset + n >= PS_INITIAL_ARENA_MMAP) { \
65 _PSDebug("Exhausted arena virtual memory\n%s", ""); \
66 ps_exit(1); \
67 } \
68 arena->offset += n; \
69 if ((arena->offset & (arena->page_size - 1)) > 0) { \
70 const size_t new_size = (arena->offset + arena->page_size - 1) \
71 & -(arena->page_size); \
72 mprotect(arena->start, new_size, PROT_READ | PROT_WRITE); \
73 } \
74 } while (0)
75
76void* ps_arena_allocate(enum ps_arena_domain domain, size_t n) {
77 struct ps_arena_allocator* arena = &arenas[domain];
78 n = (n + 15ULL) & -16ULL;
79 void* ptr = (char*)arena->start + arena->offset;
80 _PS_ARENA_ALLOCATE(arena, n);
81 return ptr;
82}
83
84void* ps_arena_allocate_debug(enum ps_arena_domain domain, size_t n,
85 const char* file NUSED, const char* func NUSED, size_t line NUSED) {
86 void* ptr = ps_arena_allocate(domain, n);
87 _PSDebug("New arena object %p (%llu bytes) in %s at %s:%zu\n", ptr, n, func,
88 basename(file), line);
89 return ptr;
90}
91
92char* arena_strndup(enum ps_arena_domain arena, const char* str,
93 size_t length) {
94 char* new_str = arena_alloc(arena, length + 1);
95 new_str[length] = 0;
96 memcpy(new_str, str, length);
97 return new_str;
98}
Defines assertion and abortion functionality.
#define CHECK(...)
All code inside CHECK will be run when PS_DEBUG is defined.
Definition abort.h:22
char * arena_strndup(enum ps_arena_domain arena, const char *str, size_t length)
Definition arena.c:92
void ps_arena_open(enum ps_arena_domain domain)
Initializes the given arena for allocation.
Definition arena.c:24
void * ps_arena_allocate_debug(enum ps_arena_domain domain, size_t n, const char *file NUSED, const char *func NUSED, size_t line NUSED)
Definition arena.c:84
#define NUSED
Definition arena.c:20
#define _PSDebug(...)
Definition arena.c:18
void * ps_arena_allocate(enum ps_arena_domain domain, size_t n)
Definition arena.c:76
void ps_arena_close(enum ps_arena_domain domain)
Destroys any allocated objects in the given arena.
Definition arena.c:45
#define _PS_ARENA_ALLOCATE(arena, n)
Definition arena.c:62
struct ps_arena_allocator arenas[__PS_ARENA_COUNT]
Definition arena.c:22
Defines an arena allocator for the compiler.
#define arena_alloc(arena, n)
Definition arena.h:50
ps_arena_domain
Definition arena.h:25
@ __PS_ARENA_COUNT
Definition arena.h:25
#define PS_INITIAL_ARENA_MMAP
An allocation of 16MB per arena.
Definition arena.h:13
static void usize length
Definition lexer.h:71
usize page_size
Definition arena.h:19