(root)/
glib-2.79.0/
glib/
gslice.c
       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 */