X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Flibloc.git;a=blobdiff_plain;f=src%2Fstringpool.c;h=27388cc12551bfd4231a095092b1beb09730fec2;hp=abd383171b9318b3b3190c5a0508c6a689136d7e;hb=8f5b676af42606975d5473c17bd8474527566b16;hpb=2601e83eca9f5d8447186256c642aef25441f07e diff --git a/src/stringpool.c b/src/stringpool.c index abd3831..27388cc 100644 --- a/src/stringpool.c +++ b/src/stringpool.c @@ -19,8 +19,11 @@ #include #include #include +#include +#include #include +#include #include "libloc-private.h" #include "stringpool.h" @@ -34,21 +37,44 @@ struct loc_stringpool { ssize_t max_length; }; +static int loc_stringpool_deallocate(struct loc_stringpool* pool) { + if (pool->data) { + int r = munmap(pool->data, pool->max_length); + if (r) { + ERROR(pool->ctx, "Could not unmap data at %p: %s\n", + pool->data, strerror(errno)); + + return r; + } + } + + return 0; +} + static int loc_stringpool_allocate(struct loc_stringpool* pool, size_t length) { // Drop old data - if (pool->data) - free(pool->data); + int r = loc_stringpool_deallocate(pool); + if (r) + return r; pool->max_length = length; + + // Align to page size + while (pool->max_length % sysconf(_SC_PAGE_SIZE) > 0) + pool->max_length++; + DEBUG(pool->ctx, "Allocating pool of %zu bytes\n", pool->max_length); - if (pool->max_length > 0) { - pool->data = malloc(pool->max_length); - if (!pool->data) - return -ENOMEM; + // Allocate some memory + pool->data = pool->pos = mmap(NULL, pool->max_length, + PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + + if (pool->data == MAP_FAILED) { + DEBUG(pool->ctx, "%s\n", strerror(errno)); + return -errno; } - pool->pos = pool->data; + DEBUG(pool->ctx, "Allocated pool at %p\n", pool->data); return 0; } @@ -62,10 +88,12 @@ LOC_EXPORT int loc_stringpool_new(struct loc_ctx* ctx, struct loc_stringpool** p p->refcount = 1; // Allocate the data section - int r = loc_stringpool_allocate(p, max_length); - if (r) { - loc_stringpool_unref(p); - return r; + if (max_length > 0) { + int r = loc_stringpool_allocate(p, max_length); + if (r) { + loc_stringpool_unref(p); + return r; + } } DEBUG(p->ctx, "String pool allocated at %p\n", p); @@ -84,11 +112,8 @@ LOC_EXPORT struct loc_stringpool* loc_stringpool_ref(struct loc_stringpool* pool static void loc_stringpool_free(struct loc_stringpool* pool) { DEBUG(pool->ctx, "Releasing string pool %p\n", pool); + loc_stringpool_deallocate(pool); loc_unref(pool->ctx); - - if (pool->data) - free(pool->data); - free(pool); } @@ -209,24 +234,17 @@ LOC_EXPORT void loc_stringpool_dump(struct loc_stringpool* pool) { } } -LOC_EXPORT int loc_stringpool_read(struct loc_stringpool* pool, FILE* f, off_t offset, size_t length) { - // Allocate enough space - int r = loc_stringpool_allocate(pool, length); - if (r) - return r; +#include - // Seek to the right offset - r = fseek(f, offset, SEEK_SET); - if (r) - return r; +LOC_EXPORT int loc_stringpool_read(struct loc_stringpool* pool, FILE* f, off_t offset, size_t length) { + DEBUG(pool->ctx, "Reading string pool from %zu (%zu bytes)\n", offset, length); - size_t bytes_read = fread(pool->data, sizeof(*pool->data), length, f); - if (bytes_read < length) { - ERROR(pool->ctx, "Could not read pool. Only read %zu bytes\n", bytes_read); - return 1; - } + pool->data = pool->pos = mmap(NULL, length, PROT_READ, + MAP_PRIVATE, fileno(f), offset); + pool->max_length = length; - DEBUG(pool->ctx, "Read pool of %zu bytes\n", length); + if (pool->data == MAP_FAILED) + return -errno; return 0; }