#include "malunal/config.h" #if MALUNAL_PLATFORM_LINUX #include #include #include #include #include "internal.h" static malunal_size_t g_platform_page_size = 0; malunal_size_t platform_page_size() { return g_platform_page_size == 0 ? g_platform_page_size = sysconf(_SC_PAGE_SIZE) : g_platform_page_size; } static allocation_error_t linux_initialize( impl_mptr_t allocator, allocator_mptr_t upstream, malunal_size_t capacity ) { MALUNAL_UNUSED(allocator); MALUNAL_UNUSED(upstream); MALUNAL_UNUSED(capacity); return ALLOCATION_ERROR_SUCCESS; } static allocation_error_t linux_finalize(impl_mptr_t allocator) { MALUNAL_UNUSED(allocator); return ALLOCATION_ERROR_SUCCESS; } static allocation_result_t linux_acquire( impl_mptr_t allocator, malunal_size_t size ) { MALUNAL_UNUSED(allocator); const malunal_int32_t memops = PROT_READ | PROT_WRITE; const malunal_int32_t memprms = MAP_PRIVATE | MAP_ANONYMOUS; malunal_mptr_t ptr = mmap(0, size, memops, memprms, -1, 0); if (ptr == MAP_FAILED || ptr == NULL_ADDRESS) return (allocation_result_t) { .threw = 1, .error = ALLOCATION_ERROR_OUT_OF_MEMORY }; allocator->allocated += size; allocator->reserved += size; allocator->acquires += 1; return (allocation_result_t) { .threw = 0, .address = ptr }; } static allocation_error_t linux_release( impl_mptr_t allocator, malunal_mptr_t address, malunal_size_t size ) { MALUNAL_UNUSED(allocator); munmap(address, size); allocator->allocated -= size; allocator->reserved -= size; allocator->releases += 1; return ALLOCATION_ERROR_SUCCESS; } static allocation_result_t linux_reacquire( impl_mptr_t allocator, malunal_mptr_t address, malunal_size_t oldsize, malunal_size_t newsize ) { allocation_result_t result = linux_acquire(allocator, newsize); if (result.threw) return result; result.address = memcpy(result.address, address, oldsize); linux_release(allocator, address, oldsize); return result; } static const virtual_table_t linux_vtable = { .initialize = (allocator_initialize_pfn_t)&linux_initialize, .finalize = (allocator_finalize_pfn_t)&linux_finalize, .acquire = (allocator_acquire_pfn_t)&linux_acquire, .reacquire = (allocator_reacquire_pfn_t)&linux_reacquire, .release = (allocator_release_pfn_t)&linux_release }; allocator_t linux_allocator() { implementation_t implementation = { .vtable = &linux_vtable, .upstream = NULL_ADDRESS, .context = NULL_ADDRESS, .allocated = 0, .reserved = 0, .acquires = 0, .releases = 0 }; allocator_t result; memcpy( &result, &implementation, sizeof(implementation_t) ); return result; } #endif /* MALUNAL_PLATFORM_LINUX */