1 /* $OpenBSD: pool.c,v 1.4 2023/04/19 12:58:15 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2017 Martin Pieuchot 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef NOPOOL 20 21 #include <sys/types.h> 22 #include <sys/queue.h> 23 24 #include <assert.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "xmalloc.h" 30 #include "pool.h" 31 32 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 33 34 struct pool_item { 35 SLIST_ENTRY(pool_item) pi_list; 36 }; 37 38 SIMPLEQ_HEAD(, pool) pool_head = SIMPLEQ_HEAD_INITIALIZER(pool_head); 39 40 void 41 pool_init(struct pool *pp, const char *name, size_t nmemb, size_t size) 42 { 43 size = MAXIMUM(size, sizeof(struct pool_item)); 44 45 SLIST_INIT(&pp->pr_free); 46 pp->pr_name = name; 47 pp->pr_nmemb = nmemb; 48 pp->pr_size = size; 49 pp->pr_nitems = 0; 50 pp->pr_nfree = 0; 51 52 SIMPLEQ_INSERT_TAIL(&pool_head, pp, pr_list); 53 } 54 55 void * 56 pool_get(struct pool *pp) 57 { 58 struct pool_item *pi; 59 60 if (SLIST_EMPTY(&pp->pr_free)) { 61 char *p; 62 size_t i; 63 64 p = xreallocarray(NULL, pp->pr_nmemb, pp->pr_size); 65 for (i = 0; i < pp->pr_nmemb; i++) { 66 pi = (struct pool_item *)p; 67 SLIST_INSERT_HEAD(&pp->pr_free, pi, pi_list); 68 p += pp->pr_size; 69 } 70 pp->pr_nitems += pp->pr_nmemb; 71 pp->pr_nfree += pp->pr_nmemb; 72 } 73 74 pi = SLIST_FIRST(&pp->pr_free); 75 SLIST_REMOVE_HEAD(&pp->pr_free, pi_list); 76 pp->pr_nfree--; 77 78 return pi; 79 } 80 81 void 82 pool_put(struct pool *pp, void *p) 83 { 84 struct pool_item *pi = (struct pool_item *)p; 85 86 if (pi == NULL) 87 return; 88 89 assert(pp->pr_nfree < pp->pr_nitems); 90 91 SLIST_INSERT_HEAD(&pp->pr_free, pi, pi_list); 92 pp->pr_nfree++; 93 } 94 95 void 96 pool_dump(void) 97 { 98 struct pool *pp; 99 100 SIMPLEQ_FOREACH(pp, &pool_head, pr_list) 101 printf("%s: %zd items, %zd free\n", pp->pr_name, pp->pr_nitems, 102 pp->pr_nfree); 103 } 104 #endif /* NOPOOL */ 105