//! Memory mapping abstraction #ifndef _MAP_H #define _MAP_H #include #include "ints.h" typedef enum mm_err { MAP_ERR_UNKNOWN = 0, MAP_SUCCESS = 1, MAP_ERR_MMAP, MAP_ERR_UNMAP, MAP_ERR_OPEN, MAP_ERR_CLOSE, MAP_ERR_STAT, MAP_ERR_ADVISE, } map_result_t; typedef union memory_map { // Common struct { union { void* origin; u8* area; }; usize len; }; // Specific to anon / file struct mm_file { void* origin; usize len; off_t fd_offset; int fd; } file; struct mm_anon { void* origin; usize len; } anon; } map_t; map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT map); /// Specify size as 0 to use the file's full size for the map. map_result_t map_file(const char* file, bool write, usize size, off_t offset, map_t *pOUT map); map_result_t map_anon(void* ptr, usize len, map_t *pOUT map); map_result_t map_free(map_t map); map_result_t map_preload(map_t *pINOUT map, bool random); const char* map_error_str(map_result_t res); _mixin int _map_handle_err(const char* stmt, const char* file, int line, const char* func, map_result_t res) { if(res == MAP_SUCCESS) return 1; else { const char* err = map_error_str(res); ERROR("mapping failed at %s:%d->%s(): on stmt `%s`", file, line, func, stmt); switch(res) { // Non-errno errors case MAP_ERR_UNKNOWN: case MAP_SUCCESS: fprintf(stderr, err); if(0) // errno errors default: perror(err); return 0; } } UNREACHABLE(); } #define map_handle_err(stmt) _map_handle_err(#stmt, __FILE__, __LINE__, __func__, stmt) #endif /* _MAP_H */