1 /* SPDX-License-Identifier: LGPL-2.1-or-later */ 2 3 #include <stdint.h> 4 #include <stdlib.h> 5 6 #include "env-util.h" 7 #include "macro.h" 8 #include "memory-util.h" 9 #include "mempool.h" 10 #include "process-util.h" 11 #include "util.h" 12 13 struct pool { 14 struct pool *next; 15 size_t n_tiles; 16 size_t n_used; 17 }; 18 mempool_alloc_tile(struct mempool * mp)19void* mempool_alloc_tile(struct mempool *mp) { 20 size_t i; 21 22 /* When a tile is released we add it to the list and simply 23 * place the next pointer at its offset 0. */ 24 25 assert(mp->tile_size >= sizeof(void*)); 26 assert(mp->at_least > 0); 27 28 if (mp->freelist) { 29 void *r; 30 31 r = mp->freelist; 32 mp->freelist = * (void**) mp->freelist; 33 return r; 34 } 35 36 if (_unlikely_(!mp->first_pool) || 37 _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) { 38 size_t size, n; 39 struct pool *p; 40 41 n = mp->first_pool ? mp->first_pool->n_tiles : 0; 42 n = MAX(mp->at_least, n * 2); 43 size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size); 44 n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size; 45 46 p = malloc(size); 47 if (!p) 48 return NULL; 49 50 p->next = mp->first_pool; 51 p->n_tiles = n; 52 p->n_used = 0; 53 54 mp->first_pool = p; 55 } 56 57 i = mp->first_pool->n_used++; 58 59 return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size; 60 } 61 mempool_alloc0_tile(struct mempool * mp)62void* mempool_alloc0_tile(struct mempool *mp) { 63 void *p; 64 65 p = mempool_alloc_tile(mp); 66 if (p) 67 memzero(p, mp->tile_size); 68 return p; 69 } 70 mempool_free_tile(struct mempool * mp,void * p)71void mempool_free_tile(struct mempool *mp, void *p) { 72 * (void**) p = mp->freelist; 73 mp->freelist = p; 74 } 75 mempool_enabled(void)76bool mempool_enabled(void) { 77 static int b = -1; 78 79 if (!is_main_thread()) 80 return false; 81 82 if (!mempool_use_allowed) 83 b = false; 84 if (b < 0) 85 b = getenv_bool("SYSTEMD_MEMPOOL") != 0; 86 87 return b; 88 } 89 90 #if VALGRIND mempool_drop(struct mempool * mp)91void mempool_drop(struct mempool *mp) { 92 struct pool *p = mp->first_pool; 93 while (p) { 94 struct pool *n; 95 n = p->next; 96 free(p); 97 p = n; 98 } 99 } 100 #endif 101