1 /* GLIB sliced memory - fast concurrent memory chunk allocator
2 * Copyright (C) 2005 Tim Janik
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 /* MT safe */
20
21 #include "config.h"
22 #include "glibconfig.h"
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "gslice.h"
28
29 #include "gmem.h" /* gslice.h */
30 #include "glib_trace.h"
31 #include "gprintf.h"
32
33
34 /* --- auxiliary functions --- */
35 void
36 g_slice_set_config (GSliceConfig ckey,
37 gint64 value)
38 {
39 /* deprecated, no implementation */
40 }
41
42 gint64
43 g_slice_get_config (GSliceConfig ckey)
44 {
45 /* deprecated, no implementation */
46 return 0;
47 }
48
49 gint64*
50 g_slice_get_config_state (GSliceConfig ckey,
51 gint64 address,
52 guint *n_values)
53 {
54 /* deprecated, no implementation */
55 return NULL;
56 }
57
58 /* --- API functions --- */
59
60 /**
61 * g_slice_new:
62 * @type: the type to allocate, typically a structure name
63 *
64 * A convenience macro to allocate a block of memory from the
65 * slice allocator.
66 *
67 * It calls g_slice_alloc() with `sizeof (@type)` and casts the
68 * returned pointer to a pointer of the given type, avoiding a type
69 * cast in the source code.
70 *
71 * This can never return %NULL as the minimum allocation size from
72 * `sizeof (@type)` is 1 byte.
73 *
74 * Since GLib 2.76 this always uses the system malloc() implementation
75 * internally.
76 *
77 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
78 * to @type
79 *
80 * Since: 2.10
81 */
82
83 /**
84 * g_slice_new0:
85 * @type: the type to allocate, typically a structure name
86 *
87 * A convenience macro to allocate a block of memory from the
88 * slice allocator and set the memory to 0.
89 *
90 * It calls g_slice_alloc0() with `sizeof (@type)`
91 * and casts the returned pointer to a pointer of the given type,
92 * avoiding a type cast in the source code.
93 *
94 * This can never return %NULL as the minimum allocation size from
95 * `sizeof (@type)` is 1 byte.
96 *
97 * Since GLib 2.76 this always uses the system malloc() implementation
98 * internally.
99 *
100 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
101 * to @type
102 *
103 * Since: 2.10
104 */
105
106 /**
107 * g_slice_dup:
108 * @type: the type to duplicate, typically a structure name
109 * @mem: (not nullable): the memory to copy into the allocated block
110 *
111 * A convenience macro to duplicate a block of memory using
112 * the slice allocator.
113 *
114 * It calls g_slice_copy() with `sizeof (@type)`
115 * and casts the returned pointer to a pointer of the given type,
116 * avoiding a type cast in the source code.
117 *
118 * This can never return %NULL.
119 *
120 * Since GLib 2.76 this always uses the system malloc() implementation
121 * internally.
122 *
123 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
124 * to @type
125 *
126 * Since: 2.14
127 */
128
129 /**
130 * g_slice_free:
131 * @type: the type of the block to free, typically a structure name
132 * @mem: (nullable): a pointer to the block to free
133 *
134 * A convenience macro to free a block of memory that has
135 * been allocated from the slice allocator.
136 *
137 * It calls g_slice_free1() using `sizeof (type)`
138 * as the block size.
139 * Note that the exact release behaviour can be changed with the
140 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
141 *
142 * If @mem is %NULL, this macro does nothing.
143 *
144 * Since GLib 2.76 this always uses the system free() implementation internally.
145 *
146 * Since: 2.10
147 */
148
149 /**
150 * g_slice_free_chain:
151 * @type: the type of the @mem_chain blocks
152 * @mem_chain: (nullable): a pointer to the first block of the chain
153 * @next: the field name of the next pointer in @type
154 *
155 * Frees a linked list of memory blocks of structure type @type.
156 *
157 * The memory blocks must be equal-sized, allocated via
158 * g_slice_alloc() or g_slice_alloc0() and linked together by
159 * a @next pointer (similar to #GSList). The name of the
160 * @next field in @type is passed as third argument.
161 * Note that the exact release behaviour can be changed with the
162 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
163 *
164 * If @mem_chain is %NULL, this function does nothing.
165 *
166 * Since GLib 2.76 this always uses the system free() implementation internally.
167 *
168 * Since: 2.10
169 */
170
171 /**
172 * g_slice_alloc:
173 * @block_size: the number of bytes to allocate
174 *
175 * Allocates a block of memory from the libc allocator.
176 *
177 * The block address handed out can be expected to be aligned
178 * to at least `1 * sizeof (void*)`.
179 *
180 * Since GLib 2.76 this always uses the system malloc() implementation
181 * internally.
182 *
183 * Returns: (nullable): a pointer to the allocated memory block, which will
184 * be %NULL if and only if @mem_size is 0
185 *
186 * Since: 2.10
187 */
188 gpointer
189 g_slice_alloc (gsize mem_size)
190 {
191 gpointer mem;
192
193 mem = g_malloc (mem_size);
194 TRACE (GLIB_SLICE_ALLOC((void*)mem, mem_size));
195
196 return mem;
197 }
198
199 /**
200 * g_slice_alloc0:
201 * @block_size: the number of bytes to allocate
202 *
203 * Allocates a block of memory via g_slice_alloc() and initializes
204 * the returned memory to 0.
205 *
206 * Since GLib 2.76 this always uses the system malloc() implementation
207 * internally.
208 *
209 * Returns: (nullable): a pointer to the allocated block, which will be %NULL
210 * if and only if @mem_size is 0
211 *
212 * Since: 2.10
213 */
214 gpointer
215 g_slice_alloc0 (gsize mem_size)
216 {
217 gpointer mem = g_slice_alloc (mem_size);
218 if (mem)
219 memset (mem, 0, mem_size);
220 return mem;
221 }
222
223 /**
224 * g_slice_copy:
225 * @block_size: the number of bytes to allocate
226 * @mem_block: the memory to copy
227 *
228 * Allocates a block of memory from the slice allocator
229 * and copies @block_size bytes into it from @mem_block.
230 *
231 * @mem_block must be non-%NULL if @block_size is non-zero.
232 *
233 * Since GLib 2.76 this always uses the system malloc() implementation
234 * internally.
235 *
236 * Returns: (nullable): a pointer to the allocated memory block,
237 * which will be %NULL if and only if @mem_size is 0
238 *
239 * Since: 2.14
240 */
241 gpointer
242 g_slice_copy (gsize mem_size,
243 gconstpointer mem_block)
244 {
245 gpointer mem = g_slice_alloc (mem_size);
246 if (mem)
247 memcpy (mem, mem_block, mem_size);
248 return mem;
249 }
250
251 /**
252 * g_slice_free1:
253 * @block_size: the size of the block
254 * @mem_block: (nullable): a pointer to the block to free
255 *
256 * Frees a block of memory.
257 *
258 * The memory must have been allocated via g_slice_alloc() or
259 * g_slice_alloc0() and the @block_size has to match the size
260 * specified upon allocation. Note that the exact release behaviour
261 * can be changed with the [`G_DEBUG=gc-friendly`][G_DEBUG] environment
262 * variable.
263 *
264 * If @mem_block is %NULL, this function does nothing.
265 *
266 * Since GLib 2.76 this always uses the system free_sized() implementation
267 * internally.
268 *
269 * Since: 2.10
270 */
271 void
272 g_slice_free1 (gsize mem_size,
273 gpointer mem_block)
274 {
275 if (G_UNLIKELY (g_mem_gc_friendly && mem_block))
276 memset (mem_block, 0, mem_size);
277 g_free_sized (mem_block, mem_size);
278 TRACE (GLIB_SLICE_FREE((void*)mem_block, mem_size));
279 }
280
281 /**
282 * g_slice_free_chain_with_offset:
283 * @block_size: the size of the blocks
284 * @mem_chain: (nullable): a pointer to the first block of the chain
285 * @next_offset: the offset of the @next field in the blocks
286 *
287 * Frees a linked list of memory blocks of structure type @type.
288 *
289 * The memory blocks must be equal-sized, allocated via
290 * g_slice_alloc() or g_slice_alloc0() and linked together by a
291 * @next pointer (similar to #GSList). The offset of the @next
292 * field in each block is passed as third argument.
293 * Note that the exact release behaviour can be changed with the
294 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
295 *
296 * If @mem_chain is %NULL, this function does nothing.
297 *
298 * Since GLib 2.76 this always uses the system free_sized() implementation
299 * internally.
300 *
301 * Since: 2.10
302 */
303 void
304 g_slice_free_chain_with_offset (gsize mem_size,
305 gpointer mem_chain,
306 gsize next_offset)
307 {
308 gpointer slice = mem_chain;
309 while (slice)
310 {
311 guint8 *current = slice;
312 slice = *(gpointer *) (current + next_offset);
313 if (G_UNLIKELY (g_mem_gc_friendly))
314 memset (current, 0, mem_size);
315 g_free_sized (current, mem_size);
316 }
317 }
318
319 #ifdef G_ENABLE_DEBUG
320 void
321 g_slice_debug_tree_statistics (void)
322 {
323 g_fprintf (stderr, "GSlice: Implementation dropped in GLib 2.76\n");
324 }
325 #endif /* G_ENABLE_DEBUG */