Coverage Report

Created: 2025-11-24 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rauc/subprojects/glib-2.76.5/glib/gslice.c
Line
Count
Source
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
 * SECTION:memory_slices
35
 * @title: Memory Slices
36
 * @short_description: efficient way to allocate groups of equal-sized
37
 *     chunks of memory
38
 *
39
 * GSlice was a space-efficient and multi-processing scalable way to allocate
40
 * equal sized pieces of memory. Since GLib 2.76, its implementation has been
41
 * removed and it calls g_malloc() and g_free_sized(), because the performance
42
 * of the system-default allocators has improved on all platforms since GSlice
43
 * was written.
44
 *
45
 * The GSlice APIs have not been deprecated, as they are widely in use and doing
46
 * so would be very disruptive for little benefit.
47
 *
48
 * New code should be written using g_new()/g_malloc() and g_free_sized() or
49
 * g_free(). There is no particular benefit in porting existing code away from
50
 * g_slice_new()/g_slice_free() unless it’s being rewritten anyway.
51
 *
52
 * Here is an example for using the slice allocator:
53
 * |[<!-- language="C" --> 
54
 * gchar *mem[10000];
55
 * gint i;
56
 *
57
 * // Allocate 10000 blocks.
58
 * for (i = 0; i < 10000; i++)
59
 *   {
60
 *     mem[i] = g_slice_alloc (50);
61
 *
62
 *     // Fill in the memory with some junk.
63
 *     for (j = 0; j < 50; j++)
64
 *       mem[i][j] = i * j;
65
 *   }
66
 *
67
 * // Now free all of the blocks.
68
 * for (i = 0; i < 10000; i++)
69
 *   g_slice_free1 (50, mem[i]);
70
 * ]|
71
 *
72
 * And here is an example for using the using the slice allocator
73
 * with data structures:
74
 * |[<!-- language="C" --> 
75
 * GRealArray *array;
76
 *
77
 * // Allocate one block, using the g_slice_new() macro.
78
 * array = g_slice_new (GRealArray);
79
 *
80
 * // We can now use array just like a normal pointer to a structure.
81
 * array->data            = NULL;
82
 * array->len             = 0;
83
 * array->alloc           = 0;
84
 * array->zero_terminated = (zero_terminated ? 1 : 0);
85
 * array->clear           = (clear ? 1 : 0);
86
 * array->elt_size        = elt_size;
87
 *
88
 * // We can free the block, so it can be reused.
89
 * g_slice_free (GRealArray, array);
90
 * ]|
91
 */
92
93
/* --- auxiliary functions --- */
94
void
95
g_slice_set_config (GSliceConfig ckey,
96
                    gint64       value)
97
0
{
98
  /* deprecated, no implementation */
99
0
}
100
101
gint64
102
g_slice_get_config (GSliceConfig ckey)
103
0
{
104
  /* deprecated, no implementation */
105
0
  return 0;
106
0
}
107
108
gint64*
109
g_slice_get_config_state (GSliceConfig ckey,
110
                          gint64       address,
111
                          guint       *n_values)
112
0
{
113
  /* deprecated, no implementation */
114
0
  return NULL;
115
0
}
116
117
/* --- API functions --- */
118
119
/**
120
 * g_slice_new:
121
 * @type: the type to allocate, typically a structure name
122
 *
123
 * A convenience macro to allocate a block of memory from the
124
 * slice allocator.
125
 *
126
 * It calls g_slice_alloc() with `sizeof (@type)` and casts the
127
 * returned pointer to a pointer of the given type, avoiding a type
128
 * cast in the source code.
129
 *
130
 * This can never return %NULL as the minimum allocation size from
131
 * `sizeof (@type)` is 1 byte.
132
 *
133
 * Since GLib 2.76 this always uses the system malloc() implementation
134
 * internally.
135
 *
136
 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
137
 *    to @type
138
 *
139
 * Since: 2.10
140
 */
141
142
/**
143
 * g_slice_new0:
144
 * @type: the type to allocate, typically a structure name
145
 *
146
 * A convenience macro to allocate a block of memory from the
147
 * slice allocator and set the memory to 0.
148
 *
149
 * It calls g_slice_alloc0() with `sizeof (@type)`
150
 * and casts the returned pointer to a pointer of the given type,
151
 * avoiding a type cast in the source code.
152
 *
153
 * This can never return %NULL as the minimum allocation size from
154
 * `sizeof (@type)` is 1 byte.
155
 *
156
 * Since GLib 2.76 this always uses the system malloc() implementation
157
 * internally.
158
 *
159
 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
160
 *    to @type
161
 *
162
 * Since: 2.10
163
 */
164
165
/**
166
 * g_slice_dup:
167
 * @type: the type to duplicate, typically a structure name
168
 * @mem: (not nullable): the memory to copy into the allocated block
169
 *
170
 * A convenience macro to duplicate a block of memory using
171
 * the slice allocator.
172
 *
173
 * It calls g_slice_copy() with `sizeof (@type)`
174
 * and casts the returned pointer to a pointer of the given type,
175
 * avoiding a type cast in the source code.
176
 *
177
 * This can never return %NULL.
178
 *
179
 * Since GLib 2.76 this always uses the system malloc() implementation
180
 * internally.
181
 *
182
 * Returns: (not nullable): a pointer to the allocated block, cast to a pointer
183
 *    to @type
184
 *
185
 * Since: 2.14
186
 */
187
188
/**
189
 * g_slice_free:
190
 * @type: the type of the block to free, typically a structure name
191
 * @mem: (nullable): a pointer to the block to free
192
 *
193
 * A convenience macro to free a block of memory that has
194
 * been allocated from the slice allocator.
195
 *
196
 * It calls g_slice_free1() using `sizeof (type)`
197
 * as the block size.
198
 * Note that the exact release behaviour can be changed with the
199
 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
200
 *
201
 * If @mem is %NULL, this macro does nothing.
202
 *
203
 * Since GLib 2.76 this always uses the system free() implementation internally.
204
 *
205
 * Since: 2.10
206
 */
207
208
/**
209
 * g_slice_free_chain:
210
 * @type: the type of the @mem_chain blocks
211
 * @mem_chain: (nullable): a pointer to the first block of the chain
212
 * @next: the field name of the next pointer in @type
213
 *
214
 * Frees a linked list of memory blocks of structure type @type.
215
 *
216
 * The memory blocks must be equal-sized, allocated via
217
 * g_slice_alloc() or g_slice_alloc0() and linked together by
218
 * a @next pointer (similar to #GSList). The name of the
219
 * @next field in @type is passed as third argument.
220
 * Note that the exact release behaviour can be changed with the
221
 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
222
 *
223
 * If @mem_chain is %NULL, this function does nothing.
224
 *
225
 * Since GLib 2.76 this always uses the system free() implementation internally.
226
 *
227
 * Since: 2.10
228
 */
229
230
/**
231
 * g_slice_alloc:
232
 * @block_size: the number of bytes to allocate
233
 *
234
 * Allocates a block of memory from the libc allocator.
235
 *
236
 * The block address handed out can be expected to be aligned
237
 * to at least `1 * sizeof (void*)`.
238
 *
239
 * Since GLib 2.76 this always uses the system malloc() implementation
240
 * internally.
241
 *
242
 * Returns: (nullable): a pointer to the allocated memory block, which will
243
 *   be %NULL if and only if @mem_size is 0
244
 *
245
 * Since: 2.10
246
 */
247
gpointer
248
g_slice_alloc (gsize mem_size)
249
4.68M
{
250
4.68M
  gpointer mem;
251
252
4.68M
  mem = g_malloc (mem_size);
253
4.68M
  TRACE (GLIB_SLICE_ALLOC((void*)mem, mem_size));
254
255
4.68M
  return mem;
256
4.68M
}
257
258
/**
259
 * g_slice_alloc0:
260
 * @block_size: the number of bytes to allocate
261
 *
262
 * Allocates a block of memory via g_slice_alloc() and initializes
263
 * the returned memory to 0.
264
 *
265
 * Since GLib 2.76 this always uses the system malloc() implementation
266
 * internally.
267
 *
268
 * Returns: (nullable): a pointer to the allocated block, which will be %NULL
269
 *    if and only if @mem_size is 0
270
 *
271
 * Since: 2.10
272
 */
273
gpointer
274
g_slice_alloc0 (gsize mem_size)
275
174k
{
276
174k
  gpointer mem = g_slice_alloc (mem_size);
277
174k
  if (mem)
278
174k
    memset (mem, 0, mem_size);
279
174k
  return mem;
280
174k
}
281
282
/**
283
 * g_slice_copy:
284
 * @block_size: the number of bytes to allocate
285
 * @mem_block: the memory to copy
286
 *
287
 * Allocates a block of memory from the slice allocator
288
 * and copies @block_size bytes into it from @mem_block.
289
 *
290
 * @mem_block must be non-%NULL if @block_size is non-zero.
291
 *
292
 * Since GLib 2.76 this always uses the system malloc() implementation
293
 * internally.
294
 *
295
 * Returns: (nullable): a pointer to the allocated memory block,
296
 *    which will be %NULL if and only if @mem_size is 0
297
 *
298
 * Since: 2.14
299
 */
300
gpointer
301
g_slice_copy (gsize         mem_size,
302
              gconstpointer mem_block)
303
0
{
304
0
  gpointer mem = g_slice_alloc (mem_size);
305
0
  if (mem)
306
0
    memcpy (mem, mem_block, mem_size);
307
0
  return mem;
308
0
}
309
310
/**
311
 * g_slice_free1:
312
 * @block_size: the size of the block
313
 * @mem_block: (nullable): a pointer to the block to free
314
 *
315
 * Frees a block of memory.
316
 *
317
 * The memory must have been allocated via g_slice_alloc() or
318
 * g_slice_alloc0() and the @block_size has to match the size
319
 * specified upon allocation. Note that the exact release behaviour
320
 * can be changed with the [`G_DEBUG=gc-friendly`][G_DEBUG] environment
321
 * variable.
322
 *
323
 * If @mem_block is %NULL, this function does nothing.
324
 *
325
 * Since GLib 2.76 this always uses the system free_sized() implementation
326
 * internally.
327
 *
328
 * Since: 2.10
329
 */
330
void
331
g_slice_free1 (gsize    mem_size,
332
               gpointer mem_block)
333
1.34M
{
334
1.34M
  if (G_UNLIKELY (g_mem_gc_friendly && mem_block))
335
0
    memset (mem_block, 0, mem_size);
336
1.34M
  g_free_sized (mem_block, mem_size);
337
1.34M
  TRACE (GLIB_SLICE_FREE((void*)mem_block, mem_size));
338
1.34M
}
339
340
/**
341
 * g_slice_free_chain_with_offset:
342
 * @block_size: the size of the blocks
343
 * @mem_chain: (nullable):  a pointer to the first block of the chain
344
 * @next_offset: the offset of the @next field in the blocks
345
 *
346
 * Frees a linked list of memory blocks of structure type @type.
347
 *
348
 * The memory blocks must be equal-sized, allocated via
349
 * g_slice_alloc() or g_slice_alloc0() and linked together by a
350
 * @next pointer (similar to #GSList). The offset of the @next
351
 * field in each block is passed as third argument.
352
 * Note that the exact release behaviour can be changed with the
353
 * [`G_DEBUG=gc-friendly`][G_DEBUG] environment variable.
354
 *
355
 * If @mem_chain is %NULL, this function does nothing.
356
 *
357
 * Since GLib 2.76 this always uses the system free_sized() implementation
358
 * internally.
359
 *
360
 * Since: 2.10
361
 */
362
void
363
g_slice_free_chain_with_offset (gsize    mem_size,
364
                                gpointer mem_chain,
365
                                gsize    next_offset)
366
31.6k
{
367
31.6k
  gpointer slice = mem_chain;
368
3.36M
  while (slice)
369
3.33M
    {
370
3.33M
      guint8 *current = slice;
371
3.33M
      slice = *(gpointer *) (current + next_offset);
372
3.33M
      if (G_UNLIKELY (g_mem_gc_friendly))
373
0
        memset (current, 0, mem_size);
374
3.33M
      g_free_sized (current, mem_size);
375
3.33M
    }
376
31.6k
}
377
378
#ifdef G_ENABLE_DEBUG
379
void
380
g_slice_debug_tree_statistics (void)
381
{
382
  g_fprintf (stderr, "GSlice: Implementation dropped in GLib 2.76\n");
383
}
384
#endif /* G_ENABLE_DEBUG */