Program Listing for File umap.cpp¶
↰ Return to documentation for file (umap/umap.cpp)
//////////////////////////////////////////////////////////////////////////////
// Copyright 2017-2020 Lawrence Livermore National Security, LLC and other
// UMAP Project Developers. See the top-level LICENSE file for details.
//
// SPDX-License-Identifier: LGPL-2.1-only
//////////////////////////////////////////////////////////////////////////////
#include <cinttypes>
#include <errno.h> // strerror()
#include <string.h> // strerror()
#include <sys/mman.h>
#include "umap/config.h"
#include "umap/RegionManager.hpp"
#include "umap/umap.h"
#include "umap/store/Store.hpp"
#include "umap/util/Macros.hpp"
void*
umap(
void* region_addr
, uint64_t region_size
, int prot
, int flags
, int fd
, off_t offset
)
{
UMAP_LOG(Debug,
"region_addr: " << region_addr
<< ", region_size: " << region_size
<< ", prot: " << prot
<< ", flags: " << flags
<< ", offset: " << offset
);
return Umap::umap_ex(region_addr, region_size, prot, flags, fd, 0, nullptr);
}
#ifdef MARGO_ROOT
void* umap_network(const char* id
, void* region_addr
, size_t region_size)
{
Umap::Store *ds;
if( region_addr!=NULL ){
/* Server */
ds = new Umap::StoreNetworkServer(id, region_addr, region_size);
auto& rm = Umap::RegionManager::getInstance();
rm.addServerRegion(ds, (char*)region_addr, region_size);
return region_addr;
}else{
/*Client */
ds = new Umap::StoreNetworkClient(id, region_size);
return Umap::umap_ex(region_addr, region_size, PROT_READ, UMAP_PRIVATE, -1, 0, ds);
}
}
#endif
int
uunmap(void* addr, uint64_t length)
{
UMAP_LOG(Debug, "addr: " << addr << ", length: " << length);
auto& rm = Umap::RegionManager::getInstance();
rm.removeRegion((char*)addr);
UMAP_LOG(Debug, "Done");
return 0;
}
int umap_flush(){
return Umap::RegionManager::getInstance().flush_buffer();
}
int umap_evict(){
return Umap::RegionManager::getInstance().evict_buffer();
}
void umap_prefetch( int npages, umap_prefetch_item* page_array )
{
Umap::RegionManager::getInstance().prefetch(npages, page_array);
}
long
umapcfg_get_system_page_size( void )
{
return Umap::RegionManager::getInstance().get_system_page_size();
}
uint64_t
umapcfg_get_max_pages_in_buffer( void )
{
return Umap::RegionManager::getInstance().get_max_pages_in_buffer();
}
uint64_t
umapcfg_get_read_ahead( void )
{
return Umap::RegionManager::getInstance().get_read_ahead();
}
uint64_t
umapcfg_get_umap_page_size( void )
{
return Umap::RegionManager::getInstance().get_umap_page_size();
}
uint64_t
umapcfg_get_num_fillers( void )
{
return Umap::RegionManager::getInstance().get_num_fillers();
}
uint64_t
umapcfg_get_num_evictors( void )
{
return Umap::RegionManager::getInstance().get_num_evictors();
}
int
umapcfg_get_evict_low_water_threshold( void )
{
return Umap::RegionManager::getInstance().get_evict_low_water_threshold();
}
int
umapcfg_get_evict_high_water_threshold( void )
{
return Umap::RegionManager::getInstance().get_evict_high_water_threshold();
}
uint64_t
umapcfg_get_max_fault_events( void )
{
return Umap::RegionManager::getInstance().get_max_fault_events();
}
namespace Umap {
// A global variable to ensure thread-safety
std::mutex g_mutex;
void*
umap_ex(
void* region_addr
, uint64_t region_size
, int prot
, int flags
, int fd
, off_t offset
, Store* store
)
{
std::lock_guard<std::mutex> lock(g_mutex);
auto& rm = RegionManager::getInstance();
auto umap_psize = rm.get_umap_page_size();
UMAP_LOG(Info,
"region_addr: " << region_addr
<< ", region_size: " << region_size
<< ", prot: " << prot
<< ", flags: " << flags
<< ", offset: " << offset
<< ", store: " << store
<< ", umap_psize: " << umap_psize
);
#ifdef UMAP_RO_MODE
if( prot != PROT_READ )
UMAP_ERROR("only PROT_READ is supported in UMAP_RO_MODE compilation");
#else
if( prot & ~(PROT_READ|PROT_WRITE) )
UMAP_ERROR("only PROT_READ or PROT_WRITE is supported in UMap");
#endif
//
// TODO: Allow for non-page-multiple size and zero-fill like mmap does
//
if ( ( region_size % umap_psize ) ) {
UMAP_ERROR("Region size " << region_size
<< " is not a multple of umapPageSize ("
<< rm.get_umap_page_size() << ")");
}
if ( ( (uint64_t)region_addr & (umap_psize - 1) ) ) {
UMAP_ERROR("region_addr must be page aligned: " << region_addr
<< ", page size is: " << rm.get_umap_page_size());
}
if (!(flags & UMAP_PRIVATE) || flags & ~(UMAP_PRIVATE|UMAP_FIXED)) {
UMAP_ERROR("Invalid flags: " << std::hex << flags);
}
//
// When dealing with umap-page-sizes that could be multiples of the actual
// system-page-size, it is possible for mmap() to provide a region that is on
// a system-page-boundary, but not necessarily on a umap-page-size boundary.
//
// We always allocate an additional umap-page-size set of bytes so that we can
// make certain that the umap-region begins on a umap-page-size boundary.
//
uint64_t mmap_size = region_size + umap_psize;
void* mmap_region = mmap(region_addr, mmap_size,
prot, flags | (MAP_ANONYMOUS | MAP_NORESERVE), -1, 0);
if (mmap_region == MAP_FAILED) {
UMAP_ERROR("mmap failed: " << strerror(errno));
return UMAP_FAILED;
}
uint64_t umap_size = region_size;
void* umap_region;
umap_region = (void*)((uint64_t)mmap_region + umap_psize - 1);
umap_region = (void*)((uint64_t)umap_region & ~(umap_psize - 1));
if ( store == nullptr )
store = Store::make_store(umap_region, umap_size, umap_psize, fd);
rm.addRegion(store, (char*)umap_region, umap_size, (char*)mmap_region, mmap_size);
return umap_region;
}
} // namespace Umap