From baa15747462a899c1fe83dd3265e068b186bd52f Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 5 Aug 2018 03:19:36 +0300 Subject: [PATCH] Added possibility to use user defined memory ops: Now u can create a special ndbuf with your custom memory operations, this is useful to keep ndbuf in a special mapped areas for a: - keep it secure (example lock pages to avoid your info going to swap) - using your own custom optimized allocator for your own block sizes Function: ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t); Args: 1. Pointer to yout ops: struct ndbuf_memops { void *(*alloc)(size_t); uint32_t (*zero)(void *, size_t); void (*free)(void *ptr); }; 2. Size of chunk to grow buffer. if <= default value will be set. --- ChangeLog | 6 ++ include/ndbuf/ndbuf.h | 20 ++++++- ndbuf.c | 134 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 134 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b5756e..f36fafd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +0.0.2 (15-nov-2018) + * Added possibility to use user defined memory ops with: + ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t); + * Fixed bug with pkgconfig %VERSION% value + + 0.0.1 (24-nov-2017) * initial version with all functions done * tired from reuse this code and ... now it's lib diff --git a/include/ndbuf/ndbuf.h b/include/ndbuf/ndbuf.h index a858d5f..ed1ff80 100644 --- a/include/ndbuf/ndbuf.h +++ b/include/ndbuf/ndbuf.h @@ -29,14 +29,25 @@ #define NDBUF_BURN (1 << 1) /* burn buffer data before free */ #define NDBUF_NREA (1 << 2) /* non reallocatable buffer */ +#define NDBUF_UCMO (1 << 3) /* user defined memops functions */ + +struct ndbuf_memops { + void *(*alloc)(size_t); + uint32_t (*zero)(void *, size_t); + void (*free)(void *ptr); +}; typedef struct __rawdatabuffer_type { char *raw; + union { + void (*freebuf)(char *); + const struct ndbuf_memops *mop; + }; uint32_t rlength; /* raw buffer allocated length */ uint32_t ulength; /* length of used allocated space */ uint32_t curr; /* cursor for read/write operations */ - int flags; - void (*freebuf)(char *); + size_t blk_size; + uint32_t flags; } ndbuf_t; /* variadic macro workaround */ @@ -67,12 +78,15 @@ typedef struct __rawdatabuffer_type { /* allocate raw buffer with defaults preallocation */ ndbuf_t *ndbuf_new(void); -/* will do the same as ndbuf_new but will allocate given length */ +/* will do the same as ndbuf_new but will pre-allocate with the given length */ ndbuf_t *ndbuf_new_palloc(uint32_t); /* create ndbuf from raw buffer */ ndbuf_t *ndbuf_new_frombuf(char *buf, size_t buf_len, void (*freebuf)(char *)); +/* create a new buffer with user defined memops */ +ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *, const size_t); + /* free all allocated space and buffer itself */ void ndbuf_free(ndbuf_t *); diff --git a/ndbuf.c b/ndbuf.c index 34263cb..47c84bd 100644 --- a/ndbuf.c +++ b/ndbuf.c @@ -104,16 +104,51 @@ ndbuf_t *ndbuf_new_palloc(uint32_t alen) return b; } +ndbuf_t *ndbuf_new_wmops(const struct ndbuf_memops *o, const size_t blk_len) +{ + ndbuf_t *b = NULL; + + if(!o) return NULL; + else { /* avoid nil calls */ + if(!o->alloc || !o->free) return NULL; + } + + if(!(b = malloc(sizeof(ndbuf_t)))) return NULL; + else memset(b, 0, sizeof(ndbuf_t)); + + if(blk_len <= 0) b->blk_size = DEFAULT_PREALLOC_SIZE; + + if(!(b->raw = o->alloc(b->blk_size))) { + free(b); + return NULL; + } else { + b->rlength = b->blk_size; + b->ulength = b->curr = 0; + b->mop = o; + b->flags |= NDBUF_UCMO; + } + + return b; +} + /* free all allocated space and buffer itself */ void ndbuf_free(ndbuf_t *b) { + const struct ndbuf_memops *o = NULL; if(!b) return; - if((b->flags & NDBUF_BURN) && b->raw) - memset(b->raw, 0, b->rlength); + if(b->flags & NDBUF_UCMO) o = b->mop; - if((b->flags & NDBUF_NREA) && b->freebuf) b->freebuf(b->raw); - else if(b->raw) free(b->raw); + if(o) { + if((b->flags & NDBUF_BURN) && o->zero) o->zero((void *)b->raw, b->rlength); + o->free(b->raw); + } else { + if((b->flags & NDBUF_BURN) && b->raw) + memset(b->raw, 0, b->rlength); + + if((b->flags & NDBUF_NREA) && b->freebuf) b->freebuf(b->raw); + else if(b->raw) free(b->raw); + } if(b->flags & NDBUF_BURN) memset(b, 0, sizeof(ndbuf_t)); free(b); @@ -210,23 +245,37 @@ static int __rdb_grow(ndbuf_t *b, uint32_t len) { uint32_t rlen; char *ne = NULL; + const struct ndbuf_memops *o = NULL; + size_t bs = b->blk_size; if(!len) return -1; if(b->rlength + len > NDBUF_MAXLENGTH) return -1; - rlen = len + - (len%DEFAULT_PREALLOC_SIZE != 0 ? (DEFAULT_PREALLOC_SIZE - len%DEFAULT_PREALLOC_SIZE) : 0); + if(b->flags & NDBUF_UCMO) o = b->mop; + + rlen = len + (len%bs != 0 ? (bs - len%bs) : 0); if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len; rlen += b->rlength; - if(!(ne = malloc(rlen))) return -1; + if(o) ne = (char *)o->alloc(rlen); + else ne = malloc(rlen); - if(b->flags & NDBUF_BURN) memset(ne, 0, rlen); + if(!ne) return -1; + + if(b->flags & NDBUF_BURN) { + if(o) o->zero((void *)ne, rlen); + else memset(ne, 0, rlen); + } memcpy(ne, b->raw, b->ulength); - if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength); - free(b->raw); + if(o) { + if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength); + o->free((void *)b->raw); + } else { + if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength); + free(b->raw); + } b->raw = ne; b->rlength = rlen; @@ -306,7 +355,9 @@ uint32_t ndbuf_write_raw(ndbuf_t *b, void *wi, uint32_t len) uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len) { char *ne; + const struct ndbuf_memops *o = NULL; uint32_t rlen; + size_t bs = b->blk_size; if(!b || !b->raw) return 0; if(!wi || !len) return 0; @@ -314,19 +365,33 @@ uint32_t ndbuf_write_raw_head(ndbuf_t *b, void *wi, uint32_t len) /* allocate a new one and copy it right */ if(b->rlength + len > NDBUF_MAXLENGTH) return -1; - rlen = len + - (len%DEFAULT_PREALLOC_SIZE != 0 ? (DEFAULT_PREALLOC_SIZE - len%DEFAULT_PREALLOC_SIZE) : 0); + rlen = len + (len%bs != 0 ? (bs - len%bs) : 0); if(b->rlength + rlen > NDBUF_MAXLENGTH) rlen = len; rlen += b->rlength; - if(!(ne = malloc(rlen))) return -1; - if(b->flags & NDBUF_BURN) memset(ne, 0, rlen); + if(b->flags & NDBUF_UCMO) o = b->mop; + + if(o) ne = (char *)o->alloc(rlen); + else ne = malloc(rlen); + + if(!ne) return -1; + + if(b->flags & NDBUF_BURN) { + if(o) o->zero((void *)ne, rlen); + else memset(ne, 0, rlen); + } memcpy((void *)ne + len, b->raw, b->ulength); - if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength); - free(b->raw); + if(o) { + if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength); + o->free((void *)b->raw); + } else { + if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength); + free(b->raw); + } + b->raw = ne; b->rlength = rlen; } else { @@ -705,6 +770,8 @@ void ndbuf_setflags(ndbuf_t *b, int af) { if(!b) return; + if(((af & NDBUF_BURN) && (b->flags & NDBUF_UCMO)) && !b->mop->zero) return; + b->flags |= af; return; @@ -715,6 +782,8 @@ void ndbuf_exflags(ndbuf_t *b, int nf) { if(!b) return; + if(b->flags & NDBUF_UCMO) nf |= NDBUF_UCMO; + b->flags = nf; return; @@ -749,24 +818,43 @@ int ndbuf_cmp(ndbuf_t *b1, ndbuf_t *b2) /* let the buffer to use actually used bytes, not all allocated space * will return 0 on success (or in case if it doesn't required), * ENOMEM or other error if fails + * TODO: ? make this buffer non reallocable ? */ int ndbuf_memopt(ndbuf_t *b) { uint32_t len; + size_t bs = b->blk_size; char *ne; + const struct ndbuf_memops *o = NULL; if(!b || !b->raw) return EINVAL; - if((b->rlength - b->ulength) > DEFAULT_PREALLOC_SIZE) { + if((b->rlength - b->ulength) > bs) { len = b->ulength + - (b->ulength%DEFAULT_PREALLOC_SIZE != 0 ? - (DEFAULT_PREALLOC_SIZE - b->ulength%DEFAULT_PREALLOC_SIZE) : 0); - if(!(ne = malloc(len))) return ENOMEM; + (b->ulength%bs != 0 ? (bs - b->ulength%bs) : 0); + + if(b->flags & NDBUF_UCMO) o = b->mop; + + if(o) ne = (char *)o->alloc(len); + else ne = malloc(len); + + if(!ne) return ENOMEM; + + if(b->flags & NDBUF_BURN) { + if(o) o->zero((void *)ne, len); + else memset(ne, 0, len); + } - if(b->flags & NDBUF_BURN) memset(ne, 0, len); memcpy(ne, b->raw, b->ulength); - if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->ulength); - free(b->raw); + + if(o) { + if(b->flags & NDBUF_BURN) o->zero((void *)b->raw, b->rlength); + o->free((void *)b->raw); + } else { + if(b->flags & NDBUF_BURN) memset(b->raw, 0, b->rlength); + free(b->raw); + } + b->raw = ne; b->rlength = len; }