mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-25 10:48:54 -06:00
an experimental memory mapped pool. still not in use
This commit is contained in:
@@ -23,6 +23,10 @@
|
|||||||
#include <gu/assert.h>
|
#include <gu/assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef USE_VALGRIND
|
#ifdef USE_VALGRIND
|
||||||
#include <valgrind/valgrind.h>
|
#include <valgrind/valgrind.h>
|
||||||
@@ -139,18 +143,20 @@ struct GuFinalizerNode {
|
|||||||
GuFinalizer* fin;
|
GuFinalizer* fin;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GuPoolFlags {
|
enum GuPoolType {
|
||||||
GU_POOL_LOCAL = 1 << 0
|
GU_POOL_HEAP,
|
||||||
|
GU_POOL_LOCAL,
|
||||||
|
GU_POOL_MMAP
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GuPool {
|
struct GuPool {
|
||||||
uint8_t* curr_buf; // actually GuMemChunk*
|
uint8_t* curr_buf; // actually GuMemChunk*
|
||||||
GuMemChunk* chunks;
|
GuMemChunk* chunks;
|
||||||
GuFinalizerNode* finalizers;
|
GuFinalizerNode* finalizers;
|
||||||
uint16_t flags;
|
uint16_t type;
|
||||||
uint16_t left_edge;
|
size_t left_edge;
|
||||||
uint16_t right_edge;
|
size_t right_edge;
|
||||||
uint16_t curr_size;
|
size_t curr_size;
|
||||||
uint8_t init_buf[];
|
uint8_t init_buf[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,7 +166,7 @@ gu_init_pool(uint8_t* buf, size_t sz)
|
|||||||
gu_require(gu_aligned((uintptr_t) (void*) buf, gu_alignof(GuPool)));
|
gu_require(gu_aligned((uintptr_t) (void*) buf, gu_alignof(GuPool)));
|
||||||
gu_require(sz >= sizeof(GuPool));
|
gu_require(sz >= sizeof(GuPool));
|
||||||
GuPool* pool = (GuPool*) buf;
|
GuPool* pool = (GuPool*) buf;
|
||||||
pool->flags = 0;
|
pool->type = GU_POOL_HEAP;
|
||||||
pool->curr_size = sz;
|
pool->curr_size = sz;
|
||||||
pool->curr_buf = (uint8_t*) pool;
|
pool->curr_buf = (uint8_t*) pool;
|
||||||
pool->chunks = NULL;
|
pool->chunks = NULL;
|
||||||
@@ -175,7 +181,7 @@ GuPool*
|
|||||||
gu_local_pool_(uint8_t* buf, size_t sz)
|
gu_local_pool_(uint8_t* buf, size_t sz)
|
||||||
{
|
{
|
||||||
GuPool* pool = gu_init_pool(buf, sz);
|
GuPool* pool = gu_init_pool(buf, sz);
|
||||||
pool->flags |= GU_POOL_LOCAL;
|
pool->type = GU_POOL_LOCAL;
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,9 +194,55 @@ gu_new_pool(void)
|
|||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GuPool*
|
||||||
|
gu_mmap_pool(char* fpath, void* addr, size_t size, void**pptr)
|
||||||
|
{
|
||||||
|
int prot = PROT_READ;
|
||||||
|
int fd = open(fpath, O_RDONLY, S_IREAD);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
fd = open(fpath, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ftruncate(fd, size) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prot |= PROT_WRITE;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ptr = mmap(addr, size, prot, MAP_SHARED, fd, 0);
|
||||||
|
if (ptr == MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gu_require(ptr == addr);
|
||||||
|
|
||||||
|
*pptr = (prot & PROT_WRITE) ? NULL : ptr;
|
||||||
|
|
||||||
|
size_t sz = GU_FLEX_SIZE(GuPool, init_buf, sizeof(int));
|
||||||
|
uint8_t* buf = gu_mem_buf_alloc(sz, &sz);
|
||||||
|
GuPool* pool = gu_init_pool(buf, size);
|
||||||
|
|
||||||
|
*((int*) pool->init_buf) = fd;
|
||||||
|
|
||||||
|
pool->type = GU_POOL_MMAP;
|
||||||
|
pool->curr_buf = ptr;
|
||||||
|
pool->left_edge = 0;
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gu_pool_expand(GuPool* pool, size_t req)
|
gu_pool_expand(GuPool* pool, size_t req)
|
||||||
{
|
{
|
||||||
|
gu_require(pool->type != GU_POOL_MMAP);
|
||||||
size_t real_req = GU_MAX(req, GU_MIN(((size_t)pool->curr_size) + 1,
|
size_t real_req = GU_MAX(req, GU_MIN(((size_t)pool->curr_size) + 1,
|
||||||
gu_mem_chunk_max_size));
|
gu_mem_chunk_max_size));
|
||||||
gu_assert(real_req >= sizeof(GuMemChunk));
|
gu_assert(real_req >= sizeof(GuMemChunk));
|
||||||
@@ -201,7 +253,6 @@ gu_pool_expand(GuPool* pool, size_t req)
|
|||||||
pool->curr_buf = (uint8_t*) chunk;
|
pool->curr_buf = (uint8_t*) chunk;
|
||||||
pool->left_edge = offsetof(GuMemChunk, data);
|
pool->left_edge = offsetof(GuMemChunk, data);
|
||||||
pool->right_edge = pool->curr_size = size;
|
pool->right_edge = pool->curr_size = size;
|
||||||
// size should always fit in uint16_t
|
|
||||||
gu_assert((size_t) pool->right_edge == size);
|
gu_assert((size_t) pool->right_edge == size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +271,6 @@ static void*
|
|||||||
gu_pool_malloc_aligned(GuPool* pool, size_t pre_align, size_t pre_size,
|
gu_pool_malloc_aligned(GuPool* pool, size_t pre_align, size_t pre_size,
|
||||||
size_t align, size_t size)
|
size_t align, size_t size)
|
||||||
{
|
{
|
||||||
gu_require(size <= gu_mem_max_shared_alloc);
|
|
||||||
size_t pos = gu_mem_advance(pool->left_edge, pre_align, pre_size,
|
size_t pos = gu_mem_advance(pool->left_edge, pre_align, pre_size,
|
||||||
align, size);
|
align, size);
|
||||||
if (pos > (size_t) pool->right_edge) {
|
if (pos > (size_t) pool->right_edge) {
|
||||||
@@ -267,7 +317,8 @@ gu_malloc_prefixed(GuPool* pool, size_t pre_align, size_t pre_size,
|
|||||||
}
|
}
|
||||||
size_t full_size = gu_mem_advance(offsetof(GuMemChunk, data),
|
size_t full_size = gu_mem_advance(offsetof(GuMemChunk, data),
|
||||||
pre_align, pre_size, align, size);
|
pre_align, pre_size, align, size);
|
||||||
if (full_size > gu_mem_max_shared_alloc) {
|
if (full_size > gu_mem_max_shared_alloc &&
|
||||||
|
pool->type != GU_POOL_MMAP) {
|
||||||
GuMemChunk* chunk = gu_mem_alloc(full_size);
|
GuMemChunk* chunk = gu_mem_alloc(full_size);
|
||||||
chunk->next = pool->chunks;
|
chunk->next = pool->chunks;
|
||||||
pool->chunks = chunk;
|
pool->chunks = chunk;
|
||||||
@@ -300,6 +351,7 @@ gu_malloc_aligned(GuPool* pool, size_t size, size_t align)
|
|||||||
void
|
void
|
||||||
gu_pool_finally(GuPool* pool, GuFinalizer* finalizer)
|
gu_pool_finally(GuPool* pool, GuFinalizer* finalizer)
|
||||||
{
|
{
|
||||||
|
gu_require(pool->type != GU_POOL_MMAP);
|
||||||
GuFinalizerNode* node = gu_new(GuFinalizerNode, pool);
|
GuFinalizerNode* node = gu_new(GuFinalizerNode, pool);
|
||||||
node->next = pool->finalizers;
|
node->next = pool->finalizers;
|
||||||
node->fin = finalizer;
|
node->fin = finalizer;
|
||||||
@@ -321,8 +373,13 @@ gu_pool_free(GuPool* pool)
|
|||||||
chunk = next;
|
chunk = next;
|
||||||
}
|
}
|
||||||
VG(VALGRIND_DESTROY_MEMPOOL(pool));
|
VG(VALGRIND_DESTROY_MEMPOOL(pool));
|
||||||
if (!pool->flags & GU_POOL_LOCAL) {
|
if (pool->type == GU_POOL_HEAP) {
|
||||||
gu_mem_buf_free(pool);
|
gu_mem_buf_free(pool);
|
||||||
|
} else if (pool->type == GU_POOL_MMAP) {
|
||||||
|
int fd = *((int*) pool->init_buf);
|
||||||
|
|
||||||
|
munmap(pool->curr_buf, pool->curr_size);
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ gu_local_pool_(uint8_t* init_buf, size_t sz);
|
|||||||
* should not be used in the bodies of recursive functions.
|
* should not be used in the bodies of recursive functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// Create a pool stored in a memory mapped file.
|
||||||
|
GuPool*
|
||||||
|
gu_mmap_pool(char* fpath, void* addr, size_t size, void**pptr);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
/// @name Destroying a pool
|
/// @name Destroying a pool
|
||||||
|
|||||||
Reference in New Issue
Block a user