#ifndef COSMOPOLITAN_MAPS_H_ #define COSMOPOLITAN_MAPS_H_ #include "libc/intrin/atomic.h" #include "libc/intrin/tree.h" #include "libc/runtime/runtime.h" #include "libc/thread/tls2.internal.h" COSMOPOLITAN_C_START_ #define MAPS_RETRY ((void *)-1) #define MAP_TREE_CONTAINER(e) TREE_CONTAINER(struct Map, tree, e) struct Map { char *addr; /* granule aligned */ size_t size; /* must be nonzero */ int64_t off; /* ignore for anon */ int prot; /* memory protects */ int flags; /* memory map flag */ bool iscow; /* windows nt only */ bool readonlyfile; /* windows nt only */ unsigned visited; /* checks and fork */ intptr_t hand; /* windows nt only */ union { struct Tree tree; struct Map *freed; }; }; struct Maps { struct Tree *maps; _Atomic(uint64_t) lock; _Atomic(struct Map *) freed; size_t count; size_t pages; _Atomic(char *) pick; struct Map stack; struct Map guard; }; struct AddrSize { char *addr; size_t size; }; extern struct Maps __maps; void __maps_init(void); bool __maps_lock(void); void __maps_check(void); void __maps_unlock(void); void *__maps_randaddr(void); void *__maps_pickaddr(size_t); void __maps_add(struct Map *); void __maps_free(struct Map *); void __maps_insert(struct Map *); struct Map *__maps_alloc(void); struct Map *__maps_floor(const char *); void __maps_stack(char *, int, int, size_t, int, intptr_t); int __maps_compare(const struct Tree *, const struct Tree *); struct AddrSize __get_main_stack(void); forceinline optimizespeed int __maps_search(const void *key, const struct Tree *node) { const char *addr = (const char *)key; const struct Map *map = (const struct Map *)MAP_TREE_CONTAINER(node); return (addr > map->addr) - (addr < map->addr); } static inline struct Map *__maps_next(struct Map *map) { struct Tree *node; if ((node = tree_next(&map->tree))) return MAP_TREE_CONTAINER(node); return 0; } static inline struct Map *__maps_first(void) { struct Tree *node; if ((node = tree_first(__maps.maps))) return MAP_TREE_CONTAINER(node); return 0; } COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_MAPS_H_ */