/[LeafOK_CVS]/lbbs/src/memory_pool.c
ViewVC logotype

Contents of /lbbs/src/memory_pool.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Tue Jan 6 13:59:21 2026 UTC (2 months, 1 week ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +6 -3 lines
Content type: text/x-csrc
Bug fix

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * memory_pool
4 * - memory pool
5 *
6 * Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "log.h"
14 #include "memory_pool.h"
15 #include <stdlib.h>
16 #include <string.h>
17
18 MEMORY_POOL *memory_pool_init(size_t node_size, size_t node_count_per_chunk, int chunk_count_limit)
19 {
20 MEMORY_POOL *p_pool;
21
22 if (node_size < sizeof(void *))
23 {
24 log_error("Error: node_size < sizeof(void *)");
25 return NULL;
26 }
27
28 p_pool = malloc(sizeof(MEMORY_POOL));
29 if (p_pool == NULL)
30 {
31 log_error("malloc(MEMORY_POOL) error: OOM");
32 return NULL;
33 }
34
35 p_pool->node_size = node_size;
36 p_pool->node_count_per_chunk = node_count_per_chunk;
37 p_pool->chunk_count_limit = chunk_count_limit;
38 p_pool->chunk_count = 0;
39 p_pool->p_free = NULL;
40
41 p_pool->p_chunks = malloc(sizeof(void *) * (size_t)chunk_count_limit);
42 if (p_pool->p_chunks == NULL)
43 {
44 log_error("malloc(sizeof(void *) * %d) error: OOM", chunk_count_limit);
45 free(p_pool);
46 return NULL;
47 }
48
49 p_pool->node_count_allocated = 0;
50 p_pool->node_count_free = 0;
51 p_pool->node_count_total = 0;
52
53 return p_pool;
54 }
55
56 void memory_pool_cleanup(MEMORY_POOL *p_pool)
57 {
58 if (p_pool == NULL)
59 {
60 return;
61 }
62
63 if (p_pool->node_count_allocated > 0)
64 {
65 log_error("Still have %d in-use nodes", p_pool->node_count_allocated);
66 }
67
68 while (p_pool->chunk_count > 0)
69 {
70 (p_pool->chunk_count)--;
71 free(p_pool->p_chunks[p_pool->chunk_count]);
72 }
73
74 free(p_pool->p_chunks);
75 free(p_pool);
76 }
77
78 inline static void *memory_pool_add_chunk(MEMORY_POOL *p_pool)
79 {
80 void *p_chunk;
81 void *p_node;
82 size_t i;
83 size_t chunk_size;
84
85 if (p_pool->chunk_count >= p_pool->chunk_count_limit)
86 {
87 log_error("Chunk count limit %d reached", p_pool->chunk_count);
88 return NULL;
89 }
90
91 chunk_size = p_pool->node_size * p_pool->node_count_per_chunk;
92 p_chunk = malloc(chunk_size);
93 if (p_chunk == NULL)
94 {
95 log_error("malloc(%zu) error: OOM", chunk_size);
96 return NULL;
97 }
98
99 p_node = p_pool->p_free;
100 memcpy((char *)p_chunk + (p_pool->node_count_per_chunk - 1) * p_pool->node_size, &p_node, sizeof(p_node));
101 for (i = 0; i < p_pool->node_count_per_chunk - 1; i++)
102 {
103 p_node = (char *)p_chunk + (i + 1) * p_pool->node_size;
104 memcpy((char *)p_chunk + i * p_pool->node_size, &p_node, sizeof(p_node));
105 }
106
107 p_pool->p_chunks[p_pool->chunk_count] = p_chunk;
108 (p_pool->chunk_count)++;
109 p_pool->node_count_total += (int)p_pool->node_count_per_chunk;
110 p_pool->node_count_free += (int)p_pool->node_count_per_chunk;
111
112 p_pool->p_free = p_chunk;
113
114 return p_chunk;
115 }
116
117 void *memory_pool_alloc(MEMORY_POOL *p_pool)
118 {
119 void *p_node;
120
121 if (p_pool == NULL)
122 {
123 log_error("NULL pointer error");
124 return NULL;
125 }
126
127 if (p_pool->p_free == NULL && memory_pool_add_chunk(p_pool) == NULL)
128 {
129 log_error("Add chunk error");
130 return NULL;
131 }
132
133 p_node = p_pool->p_free;
134 memcpy(&(p_pool->p_free), p_node, sizeof(p_pool->p_free));
135
136 (p_pool->node_count_free)--;
137 (p_pool->node_count_allocated)++;
138
139 return p_node;
140 }
141
142 void memory_pool_free(MEMORY_POOL *p_pool, void *p_node)
143 {
144 if (p_pool == NULL)
145 {
146 log_error("NULL pointer error");
147 return;
148 }
149
150 // For test and debug
151 #ifdef _DEBUG
152 memory_pool_check_node(p_pool, p_node);
153 #endif
154
155 memcpy(p_node, &(p_pool->p_free), sizeof(p_pool->p_free));
156 p_pool->p_free = p_node;
157
158 (p_pool->node_count_free)++;
159 (p_pool->node_count_allocated)--;
160 }
161
162 int memory_pool_check_node(MEMORY_POOL *p_pool, void *p_node)
163 {
164 size_t chunk_size;
165 int i;
166
167 if (p_pool == NULL || p_node == NULL)
168 {
169 log_error("NULL pointer error");
170 return -1;
171 }
172
173 chunk_size = p_pool->node_size * p_pool->node_count_per_chunk;
174
175 for (i = 0; i < p_pool->chunk_count; i++)
176 {
177 if (p_node >= p_pool->p_chunks[i] && (char *)p_node < (char *)(p_pool->p_chunks[i]) + chunk_size)
178 {
179 if ((size_t)((char *)p_node - (char *)(p_pool->p_chunks[i])) % p_pool->node_size == 0)
180 {
181 return 0; // OK
182 }
183 else
184 {
185 log_error("Address of node (%p) is not aligned with border of chunk %d [%p, %p)",
186 p_node, i, p_pool->p_chunks[i], (char *)(p_pool->p_chunks[i]) + chunk_size);
187 return -3;
188 }
189 }
190 }
191
192 log_error("Address of node is not in range of chunks");
193 return -2;
194 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1