Skip to content

Commit

Permalink
Simplify memory manager
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Jul 5, 2024
1 parent 5a9a08d commit 01587de
Show file tree
Hide file tree
Showing 40 changed files with 450 additions and 310 deletions.
24 changes: 24 additions & 0 deletions ctl/is_void.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_VOID_H_
#define CTL_IS_VOID_H_
#include "integral_constant.h"
#include "remove_cv.h"

namespace ctl {

template<typename>
struct is_void_ : public ctl::false_type
{};

template<>
struct is_void_<void> : public ctl::true_type
{};

template<typename _Tp>
struct is_void : public is_void_<typename ctl::remove_cv<_Tp>::type>::type
{};

} // namespace ctl

#endif // CTL_IS_VOID_H_
2 changes: 1 addition & 1 deletion ctl/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ class vector
capacity_ = new_capacity;
}

Allocator alloc_;
[[no_unique_address]] Allocator alloc_;
pointer data_;
size_type size_;
size_type capacity_;
Expand Down
4 changes: 2 additions & 2 deletions examples/greenbean.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <sys/socket.h>
#include <time.h>
#include "libc/mem/leaks.h"
#include "libc/runtime/runtime.h"

/**
* @fileoverview greenbean lightweight threaded web server
Expand Down Expand Up @@ -336,10 +337,9 @@ int main(int argc, char *argv[]) {
sigaddset(&block, SIGHUP);
sigaddset(&block, SIGQUIT);
pthread_attr_t attr;
int pagesz = getauxval(AT_PAGESZ);
unassert(!pthread_attr_init(&attr));
unassert(!pthread_attr_setstacksize(&attr, 65536));
unassert(!pthread_attr_setguardsize(&attr, pagesz));
unassert(!pthread_attr_setguardsize(&attr, getpagesize()));
unassert(!pthread_attr_setsigmask_np(&attr, &block));
unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0));
pthread_t *th = gc(calloc(threads, sizeof(pthread_t)));
Expand Down
2 changes: 1 addition & 1 deletion libc/calls/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @return 0 on success, or -1 w/ errno
* @raise EINVAL if `advice` isn't valid or supported by system
* @raise EINVAL on Linux if addr/length isn't page size aligned with
* respect to `getauxval(AT_PAGESZ)`
* respect to `getpagesize()`
* @raise ENOMEM on Linux if addr/length overlaps unmapped regions
* @see libc/sysv/consts.sh
* @see fadvise()
Expand Down
2 changes: 1 addition & 1 deletion libc/calls/posix_madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @return 0 on success, or errno on error
* @raise EINVAL if `advice` isn't valid or supported by system
* @raise EINVAL on Linux if addr/length isn't page size aligned with
* respect to `getauxval(AT_PAGESZ)`
* respect to `getpagesize()`
* @raise ENOMEM on Linux if addr/length overlaps unmapped regions
* @returnserrno
*/
Expand Down
14 changes: 7 additions & 7 deletions libc/calls/setrlimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "libc/calls/struct/rlimit.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
Expand Down Expand Up @@ -77,6 +78,7 @@
*/
int setrlimit(int resource, const struct rlimit *rlim) {
int rc;
int olde = errno;
if (resource == 127) {
rc = einval();
} else if (!rlim) {
Expand All @@ -85,18 +87,16 @@ int setrlimit(int resource, const struct rlimit *rlim) {
rc = _sysret(__syslib->__setrlimit(resource, rlim));
} else if (!IsWindows()) {
rc = sys_setrlimit(resource, rlim);
if (IsXnu() && !rc && resource == RLIMIT_AS) {
// TODO(jart): What's up with XNU and NetBSD?
__virtualmax = rlim->rlim_cur;
}
} else if (resource == RLIMIT_STACK) {
rc = enotsup();
} else if (resource == RLIMIT_AS) {
__virtualmax = rlim->rlim_cur;
rc = 0;
} else {
rc = einval();
}
if (resource == RLIMIT_AS) {
__virtualmax = rlim->rlim_cur;
errno = olde;
rc = 0;
}
STRACE("setrlimit(%s, %s) → %d% m", DescribeRlimitName(resource),
DescribeRlimit(0, rlim), rc);
return rc;
Expand Down
2 changes: 1 addition & 1 deletion libc/dlopen/dlopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ static wontreturn dontinstrument void foreign_helper(void **p) {
static dontinline void elf_exec(const char *file, char **envp) {

// get microprocessor page size
long pagesz = getauxval(AT_PAGESZ);
long pagesz = getpagesize();

// load helper executable into address space
struct Loaded prog;
Expand Down
13 changes: 11 additions & 2 deletions libc/intrin/getauxval.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/getauxval.internal.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"

Expand All @@ -35,11 +38,17 @@ unsigned long getauxval(unsigned long key) {
x = __getauxval(key);
if (key == AT_PAGESZ) {
if (!x.isfound) {
if (!IsWindows()) {
#ifdef __aarch64__
x.value = 16384;
x.value = 16384;
#else
x.value = 4096;
x.value = 4096;
#endif
} else {
struct NtSystemInfo si;
GetSystemInfo(&si);
x.value = si.dwPageSize;
}
}
x.isfound = true;
}
Expand Down
2 changes: 1 addition & 1 deletion libc/intrin/getmainstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static size_t __get_stack_size(int pagesz, uintptr_t start, uintptr_t top) {
* This function works on every OS except Windows.
*/
struct AddrSize __get_main_stack(void) {
int pagesz = getauxval(AT_PAGESZ);
int pagesz = getpagesize();
uintptr_t start = (uintptr_t)__argv;
uintptr_t top = __get_main_top(pagesz);
uintptr_t bot = top - __get_stack_size(pagesz, start, top);
Expand Down
3 changes: 2 additions & 1 deletion libc/runtime/getpagesize.c → libc/intrin/getpagesize.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"

/**
* Returns granularity of memory manager.
* @see sysconf(_SC_PAGE_SIZE) which is portable
*/
int getpagesize(void) {
return __granularity();
return getauxval(AT_PAGESZ);
}
15 changes: 11 additions & 4 deletions libc/intrin/granularity.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/dce.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"

int __granularity(void) {
if (IsWindows())
return 65536;
static int res;
if (!res)
res = getauxval(AT_PAGESZ);
if (!res) {
if (!IsWindows()) {
res = getpagesize();
} else {
struct NtSystemInfo si;
GetSystemInfo(&si);
res = si.dwAllocationGranularity;
}
}
return res;
}
23 changes: 13 additions & 10 deletions libc/intrin/kprintf.greg.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,20 @@ __funline bool kischarmisaligned(const char *p, signed char t) {
}

privileged static bool32 kisdangerous_unlocked(const char *addr) {
struct Dll *e, *e2;
for (e = dll_first(__maps.used); e; e = e2) {
e2 = dll_next(__maps.used, e);
struct Map *map = MAP_CONTAINER(e);
if (map->addr <= addr && addr < map->addr + map->size) {
dll_remove(&__maps.used, e);
dll_make_first(&__maps.used, e);
return !(map->prot & PROT_READ);
}
struct Dll *e;
if ((e = dll_first(__maps.used))) {
do {
struct Map *map = MAP_CONTAINER(e);
if (map->addr <= addr && addr < map->addr + map->size) {
dll_remove(&__maps.used, e);
dll_make_first(&__maps.used, e);
return !(map->prot & PROT_READ);
}
} while ((e = dll_next(__maps.used, e)));
return true;
} else {
return false;
}
return true;
}

privileged bool32 kisdangerous(const void *addr) {
Expand Down
33 changes: 20 additions & 13 deletions libc/intrin/maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ struct Maps __maps;
void __maps_add(struct Map *map) {
dll_init(&map->elem);
dll_make_first(&__maps.used, &map->elem);
map->next = __maps.maps;
__maps.maps = map;
++__maps.count;
}

Expand All @@ -44,23 +42,31 @@ static void __maps_adder(struct Map *map, int pagesz) {
__maps_add(map);
}

void __maps_stack(void *stackaddr, int pagesz, size_t stacksize, int stackprot,
intptr_t stackhand) {
__maps.stack.addr = stackaddr;
__maps.stack.size = stacksize;
void __maps_stack(char *stackaddr, int pagesz, int guardsize, size_t stacksize,
int stackprot, intptr_t stackhand) {
__maps.stack.addr = stackaddr + guardsize;
__maps.stack.size = stacksize - guardsize;
__maps.stack.prot = stackprot;
__maps.stack.h = stackhand;
__maps.stack.hand = -1;
__maps_adder(&__maps.stack, pagesz);
if (guardsize) {
__maps.guard.addr = stackaddr;
__maps.guard.size = guardsize;
__maps.guard.prot = PROT_NONE;
__maps.guard.hand = stackhand;
__maps_adder(&__maps.guard, pagesz);
}
}

void __maps_init(void) {
int pagesz = getauxval(AT_PAGESZ);
int pagesz = getpagesize();

// record _start() stack mapping
if (!IsWindows()) {
struct AddrSize stack;
stack = __get_main_stack();
__maps_stack(stack.addr, pagesz, stack.size, (uintptr_t)ape_stack_prot, 0);
__maps_stack(stack.addr, pagesz, 0, stack.size, (uintptr_t)ape_stack_prot,
0);
}

// record .text and .data mappings
Expand All @@ -78,22 +84,23 @@ void __maps_init(void) {
__maps_adder(&text, pagesz);
}

privileged void __maps_lock(void) {
privileged bool __maps_lock(void) {
struct CosmoTib *tib;
if (!__threaded)
return;
return false;
if (!__tls_enabled)
return;
return false;
tib = __get_tls_privileged();
if (tib->tib_relock_maps++)
return;
return true;
while (atomic_exchange_explicit(&__maps.lock, 1, memory_order_acquire)) {
#if defined(__GNUC__) && defined(__aarch64__)
__asm__ volatile("yield");
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
__asm__ volatile("pause");
#endif
}
return false;
}

privileged void __maps_unlock(void) {
Expand Down
14 changes: 7 additions & 7 deletions libc/intrin/maps.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ COSMOPOLITAN_C_START_
#define MAP_CONTAINER(e) DLL_CONTAINER(struct Map, elem, e)

struct Map {
struct Map *next; /* for __maps.maps */
char *addr; /* granule aligned */
size_t size; /* must be nonzero */
struct Dll elem; /* for __maps.free */
Expand All @@ -18,18 +17,20 @@ struct Map {
bool iscow; /* windows nt only */
bool readonlyfile; /* windows nt only */
unsigned visited; /* used for checks */
intptr_t h; /* windows nt only */
intptr_t hand; /* windows nt only */
};

struct Maps {
unsigned mono;
atomic_int lock;
struct Map *maps;
struct Dll *free;
struct Map stack;
struct Dll *used;
size_t count;
size_t pages;
struct Map stack;
struct Map guard;
bool once;
atomic_ulong rollo;
};

struct AddrSize {
Expand All @@ -40,16 +41,15 @@ struct AddrSize {
extern struct Maps __maps;

void __maps_init(void);
void __maps_lock(void);
bool __maps_lock(void);
void __maps_check(void);
void __maps_unlock(void);
void __maps_add(struct Map *);
struct Map *__maps_alloc(void);
void __maps_free(struct Map *);
void __maps_insert(struct Map *);
int __munmap(char *, size_t, bool);
void *__mmap(char *, size_t, int, int, int, int64_t);
void __maps_stack(void *, int, size_t, int, intptr_t);
void __maps_stack(char *, int, int, size_t, int, intptr_t);
struct AddrSize __get_main_stack(void);

COSMOPOLITAN_C_END_
Expand Down
Loading

0 comments on commit 01587de

Please sign in to comment.