Annotation of embedaddon/libiconv/srclib/malloca.c, revision 1.1.1.3
1.1 misho 1: /* Safe automatic memory allocation.
1.1.1.3 ! misho 2: Copyright (C) 2003, 2006-2007, 2009-2019 Free Software Foundation, Inc.
! 3: Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
1.1 misho 4:
5: This program is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by
7: the Free Software Foundation; either version 3, or (at your option)
8: any later version.
9:
10: This program is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
1.1.1.3 ! misho 16: along with this program; if not, see <https://www.gnu.org/licenses/>. */
1.1 misho 17:
1.1.1.2 misho 18: #define _GL_USE_STDLIB_ALLOC 1
1.1 misho 19: #include <config.h>
20:
21: /* Specification. */
22: #include "malloca.h"
23:
1.1.1.2 misho 24: #include "verify.h"
25:
1.1 misho 26: /* The speed critical point in this file is freea() applied to an alloca()
27: result: it must be fast, to match the speed of alloca(). The speed of
28: mmalloca() and freea() in the other case are not critical, because they
1.1.1.3 ! misho 29: are only invoked for big memory sizes.
! 30: Here we use a bit in the address as an indicator, an idea by Ondřej Bílka.
! 31: malloca() can return three types of pointers:
! 32: - Pointers ≡ 0 mod 2*sa_alignment_max come from stack allocation.
! 33: - Pointers ≡ sa_alignment_max mod 2*sa_alignment_max come from heap
! 34: allocation.
! 35: - NULL comes from a failed heap allocation. */
! 36:
! 37: /* Type for holding very small pointer differences. */
! 38: typedef unsigned char small_t;
! 39: /* Verify that it is wide enough. */
! 40: verify (2 * sa_alignment_max - 1 <= (small_t) -1);
1.1 misho 41:
42: void *
43: mmalloca (size_t n)
44: {
45: #if HAVE_ALLOCA
1.1.1.3 ! misho 46: /* Allocate one more word, used to determine the address to pass to freea(),
! 47: and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max. */
! 48: size_t nplus = n + sizeof (small_t) + 2 * sa_alignment_max - 1;
1.1 misho 49:
50: if (nplus >= n)
51: {
1.1.1.3 ! misho 52: char *mem = (char *) malloc (nplus);
1.1 misho 53:
1.1.1.3 ! misho 54: if (mem != NULL)
1.1.1.2 misho 55: {
1.1.1.3 ! misho 56: char *p =
! 57: (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1)
! 58: & ~(uintptr_t)(2 * sa_alignment_max - 1))
! 59: + sa_alignment_max);
! 60: /* Here p >= mem + sizeof (small_t),
! 61: and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
! 62: hence p + n <= mem + nplus.
! 63: So, the memory range [p, p+n) lies in the allocated memory range
! 64: [mem, mem + nplus). */
! 65: ((small_t *) p)[-1] = p - mem;
! 66: /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */
1.1.1.2 misho 67: return p;
68: }
1.1 misho 69: }
70: /* Out of memory. */
71: return NULL;
72: #else
73: # if !MALLOC_0_IS_NONNULL
74: if (n == 0)
75: n = 1;
76: # endif
77: return malloc (n);
78: #endif
79: }
80:
81: #if HAVE_ALLOCA
82: void
83: freea (void *p)
84: {
1.1.1.3 ! misho 85: /* Check argument. */
! 86: if ((uintptr_t) p & (sa_alignment_max - 1))
1.1 misho 87: {
1.1.1.3 ! misho 88: /* p was not the result of a malloca() call. Invalid argument. */
! 89: abort ();
! 90: }
! 91: /* Determine whether p was a non-NULL pointer returned by mmalloca(). */
! 92: if ((uintptr_t) p & sa_alignment_max)
! 93: {
! 94: void *mem = (char *) p - ((small_t *) p)[-1];
! 95: free (mem);
1.1 misho 96: }
97: }
98: #endif
1.1.1.3 ! misho 99:
! 100: /*
! 101: * Hey Emacs!
! 102: * Local Variables:
! 103: * coding: utf-8
! 104: * End:
! 105: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>