src/basic_mempool.c

Mon, 08 Aug 2022 17:12:00 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 08 Aug 2022 17:12:00 +0200
changeset 572
f0f99dd06d9f
parent 571
f83583a0bbac
child 650
77021e06b1a8
permissions
-rw-r--r--

#201 - remove dangerous allocator config

There is no plausible use case, except using the testing
allocator in the test case, and having the possibility to
specify any allocator (including another mempool) causes
more harm than good.

universe@571 1 /*
universe@571 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@571 3 *
universe@571 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@571 5 *
universe@571 6 * Redistribution and use in source and binary forms, with or without
universe@571 7 * modification, are permitted provided that the following conditions are met:
universe@571 8 *
universe@571 9 * 1. Redistributions of source code must retain the above copyright
universe@571 10 * notice, this list of conditions and the following disclaimer.
universe@571 11 *
universe@571 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@571 13 * notice, this list of conditions and the following disclaimer in the
universe@571 14 * documentation and/or other materials provided with the distribution.
universe@571 15 *
universe@571 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@571 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@571 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@571 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@571 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@571 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@571 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@571 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@571 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@571 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@571 26 * POSSIBILITY OF SUCH DAMAGE.
universe@571 27 */
universe@571 28
universe@571 29 #include "cx/basic_mempool.h"
universe@571 30 #include "cx/utils.h"
universe@571 31 #include <stdint.h>
universe@571 32 #include <string.h>
universe@571 33
universe@571 34 #define of_chk_(n) if (SIZE_MAX - sizeof(cx_destructor_func) < (n)) return NULL
universe@571 35
universe@571 36 /** Internal structure for denoting pooled memory. */
universe@571 37 typedef struct {
universe@571 38 /** The destructor. */
universe@571 39 cx_destructor_func destructor;
universe@571 40 /**
universe@571 41 * Access to the first byte of the polled memory.
universe@571 42 */
universe@571 43 char c;
universe@571 44 } cx_basic_mempool_memory;
universe@571 45
universe@571 46 static int cx_basic_mempool_chcap(
universe@571 47 struct cx_basic_mempool_s *pool,
universe@571 48 size_t newcap
universe@571 49 ) {
universe@571 50 if (newcap < pool->ndata) {
universe@571 51 return 1;
universe@571 52 }
universe@571 53
universe@571 54 size_t newcapsz;
universe@571 55 if (cx_szmul(newcap, sizeof(void *), &newcapsz)) {
universe@571 56 return 1;
universe@571 57 }
universe@571 58
universe@571 59 void **data = realloc(pool->data, newcapsz);
universe@571 60 if (data) {
universe@571 61 pool->data = data;
universe@571 62 pool->size = newcap;
universe@571 63 return 0;
universe@571 64 } else {
universe@571 65 return 1;
universe@571 66 }
universe@571 67 }
universe@571 68
universe@571 69 void *cx_malloc_basic_mempool(
universe@571 70 void *data,
universe@571 71 size_t n
universe@571 72 ) {
universe@571 73 of_chk_(n);
universe@571 74 struct cx_basic_mempool_s *pool = data;
universe@571 75
universe@571 76 if (pool->ndata >= pool->size) {
universe@571 77 size_t newcap = pool->size * 2;
universe@571 78 if (newcap < pool->size || cx_basic_mempool_chcap(pool, newcap)) {
universe@571 79 return NULL;
universe@571 80 }
universe@571 81 }
universe@571 82
universe@572 83 cx_basic_mempool_memory *mem = malloc(sizeof(cx_destructor_func) + n);
universe@571 84 if (mem == NULL) {
universe@571 85 return NULL;
universe@571 86 }
universe@571 87
universe@571 88 mem->destructor = NULL;
universe@571 89 pool->data[pool->ndata] = mem;
universe@571 90 pool->ndata++;
universe@571 91
universe@571 92 return &(mem->c);
universe@571 93 }
universe@571 94
universe@571 95 void *cx_calloc_basic_mempool(
universe@571 96 void *data,
universe@571 97 size_t nelem,
universe@571 98 size_t elsize
universe@571 99 ) {
universe@571 100 size_t msz;
universe@571 101 if (cx_szmul(nelem, elsize, &msz)) {
universe@571 102 return NULL;
universe@571 103 }
universe@571 104 void *ptr = cx_malloc_basic_mempool(data, msz);
universe@571 105 if (ptr == NULL) {
universe@571 106 return NULL;
universe@571 107 }
universe@571 108 memset(ptr, 0, nelem * elsize);
universe@571 109 return ptr;
universe@571 110 }
universe@571 111
universe@571 112 void *cx_realloc_basic_mempool(
universe@571 113 void *data,
universe@571 114 void *ptr,
universe@571 115 size_t n
universe@571 116 ) {
universe@571 117 of_chk_(n);
universe@571 118 struct cx_basic_mempool_s *pool = data;
universe@571 119
universe@571 120 char *mem = ((char *) ptr) - sizeof(cx_destructor_func);
universe@572 121 char *newm = (char *) realloc(mem, n + sizeof(cx_destructor_func));
universe@571 122 if (newm == NULL) {
universe@571 123 return NULL;
universe@571 124 }
universe@571 125 if (mem != newm) {
universe@571 126 cx_for_n(i, pool->ndata) {
universe@571 127 if (pool->data[i] == mem) {
universe@571 128 pool->data[i] = newm;
universe@571 129 return newm + sizeof(cx_destructor_func);
universe@571 130 }
universe@571 131 }
universe@571 132 abort();
universe@571 133 } else {
universe@571 134 return newm + sizeof(cx_destructor_func);
universe@571 135 }
universe@571 136 }
universe@571 137
universe@571 138 void cx_free_basic_mempool(
universe@571 139 void *data,
universe@571 140 void *ptr
universe@571 141 ) {
universe@571 142 struct cx_basic_mempool_s *pool = data;
universe@571 143
universe@571 144 cx_basic_mempool_memory *mem = (cx_basic_mempool_memory *)
universe@571 145 ((char *) ptr - sizeof(cx_destructor_func));
universe@571 146 cx_for_n(i, pool->ndata) {
universe@571 147 if (mem == pool->data[i]) {
universe@571 148 if (mem->destructor != NULL) {
universe@571 149 mem->destructor(&(mem->c));
universe@571 150 }
universe@572 151 free(mem);
universe@571 152 size_t last_index = pool->ndata - 1;
universe@571 153 if (i != last_index) {
universe@571 154 pool->data[i] = pool->data[last_index];
universe@571 155 pool->data[last_index] = NULL;
universe@571 156 }
universe@571 157 pool->ndata--;
universe@571 158 return;
universe@571 159 }
universe@571 160 }
universe@571 161 abort();
universe@571 162 }
universe@571 163
universe@571 164 void cx_basic_mempool_destroy(CxMempool *p) {
universe@571 165 struct cx_basic_mempool_s *pool = (struct cx_basic_mempool_s *) p;
universe@571 166 cx_basic_mempool_memory *mem;
universe@571 167 cx_for_n(i, pool->ndata) {
universe@571 168 mem = (cx_basic_mempool_memory *) pool->data[i];
universe@571 169 if (mem) {
universe@571 170 if (mem->destructor) {
universe@571 171 mem->destructor(&(mem->c));
universe@571 172 }
universe@572 173 free(mem);
universe@571 174 }
universe@571 175 }
universe@571 176 free(pool->data);
universe@571 177 free((void *) p->allocator);
universe@571 178 free(pool);
universe@571 179 }
universe@571 180
universe@571 181 void cx_basic_mempool_set_destr(
universe@571 182 __attribute__((__unused__)) CxMempool *pool,
universe@571 183 void *ptr,
universe@571 184 cx_destructor_func func
universe@571 185 ) {
universe@571 186 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func;
universe@571 187 }
universe@571 188
universe@571 189 static cx_allocator_class cx_basic_mempool_allocator_class = {
universe@571 190 cx_malloc_basic_mempool,
universe@571 191 cx_realloc_basic_mempool,
universe@571 192 cx_calloc_basic_mempool,
universe@571 193 cx_free_basic_mempool
universe@571 194 };
universe@571 195
universe@571 196 static cx_mempool_class cx_basic_mempool_class = {
universe@571 197 cx_basic_mempool_destroy,
universe@571 198 cx_basic_mempool_set_destr,
universe@571 199 };
universe@571 200
universe@572 201 CxMempool *cxBasicMempoolCreate(size_t capacity) {
universe@571 202 size_t poolsize;
universe@571 203 if (cx_szmul(capacity, sizeof(void *), &poolsize)) {
universe@571 204 return NULL;
universe@571 205 }
universe@571 206
universe@571 207 struct cx_basic_mempool_s *pool =
universe@571 208 malloc(sizeof(struct cx_basic_mempool_s));
universe@571 209 if (pool == NULL) {
universe@571 210 return NULL;
universe@571 211 }
universe@571 212
universe@571 213
universe@571 214 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
universe@571 215 if (!provided_allocator) {
universe@571 216 free(pool);
universe@571 217 return NULL;
universe@571 218 }
universe@571 219 provided_allocator->cl = &cx_basic_mempool_allocator_class;
universe@571 220 provided_allocator->data = pool;
universe@571 221
universe@571 222 pool->base.cl = &cx_basic_mempool_class;
universe@571 223 pool->base.allocator = provided_allocator;
universe@571 224
universe@571 225 pool->data = malloc(poolsize);
universe@571 226 if (pool->data == NULL) {
universe@571 227 free(provided_allocator);
universe@571 228 free(pool);
universe@571 229 return NULL;
universe@571 230 }
universe@571 231
universe@571 232 pool->ndata = 0;
universe@571 233 pool->size = capacity;
universe@571 234
universe@571 235 return (CxMempool *) pool;
universe@571 236 }

mercurial