mmap() API facade.

mmap() API anon test passes.

Fortune for naka's current commit: Future small blessing − 末小吉
master
Avril 3 years ago
parent 4dd4285ee0
commit f8f5d9102e
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1,44 @@
//! Memory mapping abstraction
#ifndef _MAP_H
#define _MAP_H
#include <stdbool.h>
#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_result_t;
typedef union memory_map {
// Common
struct {
void* origin;
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);
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);
#endif /* _MAP_H */

@ -0,0 +1,63 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <macros.h>
#include <map.h>
// Set all bytes to 0xff (ints i.e. fd will be -1)
static inline void _map_init(map_t *pOUT map)
{
memset(map, 0xff, sizeof(map_t));
}
static inline bool _map_is_file(const map_t* map)
{
return map->file.fd > 0;
}
map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT map)
{
void* ptr = mmap(NULL, size, PROT_READ | (write ? PROT_WRITE : 0), MAP_SHARED, fd, offset);
if(ptr == MAP_FAILED) return MAP_ERR_MMAP;
map->file = (struct mm_file){
.origin = ptr,
.len = size,
.fd = fd,
.fd_offset = offset,
};
return MAP_SUCCESS;
}
map_result_t map_file(const char* file, bool write, usize size, off_t offset, map_t *pOUT map)
{
int fd = open(file, write ? O_RDWR : O_RDONLY);
if(fd < 0) return MAP_ERR_OPEN;
return map_fd(fd, write, size, offset, map);
}
map_result_t map_anon(void* ptr, usize len, map_t *pOUT map)
{
ptr = mmap(ptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | (ptr ? MAP_FIXED : 0), -1, 0);
if(ptr==MAP_FAILED) return MAP_ERR_MMAP;
// Make sure .file.fd is -1, so we can tell this is anon in `map_free()`.
_map_init(map);
map->anon = (struct mm_anon) {
.origin = ptr,
.len = len,
};
return MAP_SUCCESS;
}
map_result_t map_free(map_t map)
{
if( munmap(map.anon.origin, map.anon.len) != 0) return MAP_ERR_UNMAP;
if( _map_is_file(&map) ) {
if( close(map.file.fd) != 0 ) return MAP_ERR_CLOSE;
}
return MAP_SUCCESS;
}

@ -0,0 +1,19 @@
#include <string.h>
#include <tests.h>
#include <map.h>
DEFTEST(map_anon)
{
map_t map;
TEST_ASSERT(map_anon(NULL, 1024, &map) == MAP_SUCCESS);
memset(map.origin, 0xab, map.len);
TEST_ASSERT( ((u8*)map.origin)[10] == 0xab );
TEST_ASSERT(map_free(map) == MAP_SUCCESS);
return TEST_OK;
}
RUNTEST_DEBUG(map_anon)
Loading…
Cancel
Save