blob: 25f7409bfaf65c205a1779374aaa0802d4d1dcc8 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * libc/stdlib/malloc/malloc.h -- small malloc implementation
3 *
4 * Copyright (C) 2002 NEC Corporation
5 * Copyright (C) 2002 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU Lesser
8 * General Public License. See the file COPYING.LIB in the main
9 * directory of this archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14/* The alignment we guarantee for malloc return values. We prefer this
15 to be at least sizeof (size_t) bytes because (a) we have to allocate
16 that many bytes for the header anyway and (b) guaranteeing word
17 alignment can be a significant win on targets like m68k and Coldfire,
18 where __alignof__(double) == 2. */
19#define MALLOC_ALIGNMENT \
20 (__alignof__ (double) > sizeof (size_t) ? __alignof__ (double) : sizeof (size_t))
21
22/* The system pagesize... */
23extern size_t __pagesize;
24#define MALLOC_PAGE_SIZE __pagesize
25
26/* The minimum size of block we request from the the system to extend the
27 heap for small allocations (we may request a bigger block if necessary to
28 satisfy a particularly big request). */
29#define MALLOC_HEAP_EXTEND_SIZE MALLOC_PAGE_SIZE
30
31/* When a heap free-area grows above this size, try to unmap it, releasing
32 the memory back to the system. */
33#define MALLOC_UNMAP_THRESHOLD (8*MALLOC_PAGE_SIZE)
34/* When unmapping a free-area, retain this many bytes if it's the only one,
35 to avoid completely emptying the heap. This is only a heuristic -- the
36 existance of another free area, even if it's smaller than
37 MALLOC_MIN_SIZE, will cause us not to reserve anything. */
38#define MALLOC_MIN_SIZE (2*MALLOC_PAGE_SIZE)
39
40/* When realloc shrinks an allocation, it only does so if more than this
41 many bytes will be freed; it must at at least HEAP_MIN_SIZE. Larger
42 values increase speed (by reducing heap fragmentation) at the expense of
43 space. */
44#define MALLOC_REALLOC_MIN_FREE_SIZE (HEAP_MIN_SIZE + 16)
45
46
47/* For systems with an MMU, use sbrk to map/unmap memory for the malloc
48 heap, instead of mmap/munmap. This is a tradeoff -- sbrk is faster than
49 mmap/munmap, and guarantees contiguous allocation, but is also less
50 flexible, and causes the heap to only be shrinkable from the end. */
51#ifdef __ARCH_USE_MMU__
52# define MALLOC_USE_SBRK
53#endif
54
55
56/* The current implementation of munmap in uClinux doesn't work correctly:
57 it requires that ever call to munmap exactly match a corresponding call
58 to mmap (that is, it doesn't allow you to unmap only part of a
59 previously allocated block, or to unmap two contiguous blocks with a
60 single call to munmap). This behavior is broken, and uClinux should be
61 fixed; however, until it is, we add code to work around the problem in
62 malloc. */
63#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
64
65/* A structure recording a block of memory mmapped by malloc. */
66struct malloc_mmb
67{
68 void *mem; /* the mmapped block */
69 size_t size; /* its size */
70 struct malloc_mmb *next;
71};
72
73/* A list of all malloc_mmb structures describing blocks that malloc has
74 mmapped, ordered by the block address. */
75extern struct malloc_mmb *__malloc_mmapped_blocks;
76
77/* A heap used for allocating malloc_mmb structures. We could allocate
78 them from the main heap, but that tends to cause heap fragmentation in
79 annoying ways. */
80extern struct heap_free_area *__malloc_mmb_heap;
81
82/* Define MALLOC_MMB_DEBUGGING to cause malloc to emit debugging info about
83 about mmap block allocation/freeing by the `uclinux broken munmap' code
84 to stderr, when the variable __malloc_mmb_debug is set to true. */
85#ifdef MALLOC_MMB_DEBUGGING
86# include <stdio.h>
87
88extern int __malloc_mmb_debug;
89# define MALLOC_MMB_DEBUG(indent, fmt, args...) \
90 (__malloc_mmb_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0)
91# define MALLOC_MMB_DEBUG_INDENT(indent) \
92 (__malloc_mmb_debug ? __malloc_debug_indent (indent) : 0)
93# ifndef MALLOC_DEBUGGING
94# define MALLOC_DEBUGGING
95# endif
96#else /* !MALLOC_MMB_DEBUGGING */
97# define MALLOC_MMB_DEBUG(fmt, args...) (void)0
98# define MALLOC_MMB_DEBUG_INDENT(indent) (void)0
99#endif /* MALLOC_MMB_DEBUGGING */
100
101#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
102
103
104/* The size of a malloc allocation is stored in a size_t word
105 MALLOC_HEADER_SIZE bytes prior to the start address of the allocation:
106
107 +--------+---------+-------------------+
108 | SIZE |(unused) | allocation ... |
109 +--------+---------+-------------------+
110 ^ BASE ^ ADDR
111 ^ ADDR - MALLOC_HEADER_SIZE
112*/
113
114/* The amount of extra space used by the malloc header. */
115#define MALLOC_HEADER_SIZE \
116 (MALLOC_ALIGNMENT < sizeof (size_t) \
117 ? sizeof (size_t) \
118 : MALLOC_ALIGNMENT)
119
120/* Set up the malloc header, and return the user address of a malloc block. */
121#define MALLOC_SETUP(base, size) \
122 (MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE))
123/* Set the size of a malloc allocation, given the base address. */
124#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size))
125
126/* Return base-address of a malloc allocation, given the user address. */
127#define MALLOC_BASE(addr) ((void *)((char *)addr - MALLOC_HEADER_SIZE))
128/* Return the size of a malloc allocation, given the user address. */
129#define MALLOC_SIZE(addr) (*(size_t *)MALLOC_BASE(addr))
130
131
132/* Locking for multithreaded apps. */
133#ifdef __UCLIBC_HAS_THREADS__
134
135# include <bits/uClibc_mutex.h>
136
137# define MALLOC_USE_LOCKING
138
139typedef __UCLIBC_MUTEX_TYPE malloc_mutex_t;
140# define MALLOC_MUTEX_INIT __UCLIBC_MUTEX_INITIALIZER
141
142# ifdef MALLOC_USE_SBRK
143/* This lock is used to serialize uses of the `sbrk' function (in both
144 malloc and free, sbrk may be used several times in succession, and
145 things will break if these multiple calls are interleaved with another
146 thread's use of sbrk!). */
147extern malloc_mutex_t __malloc_sbrk_lock;
148# define __malloc_lock_sbrk() __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE (__malloc_sbrk_lock)
149# define __malloc_unlock_sbrk() __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE (__malloc_sbrk_lock)
150# endif /* MALLOC_USE_SBRK */
151
152#else /* !__UCLIBC_HAS_THREADS__ */
153
154/* Without threads, mutex operations are a nop. */
155# define __malloc_lock_sbrk() (void)0
156# define __malloc_unlock_sbrk() (void)0
157
158#endif /* __UCLIBC_HAS_THREADS__ */
159
160
161/* branch-prediction macros; they may already be defined by libc. */
162#ifndef likely
163#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
164#define likely(cond) __builtin_expect(!!(int)(cond), 1)
165#define unlikely(cond) __builtin_expect((int)(cond), 0)
166#else
167#define likely(cond) (cond)
168#define unlikely(cond) (cond)
169#endif
170#endif /* !likely */
171
172
173/* Define MALLOC_DEBUGGING to cause malloc to emit debugging info to stderr
174 when the variable __malloc_debug is set to true. */
175#ifdef MALLOC_DEBUGGING
176
177extern void __malloc_debug_init (void);
178
179/* The number of spaces in a malloc debug indent level. */
180#define MALLOC_DEBUG_INDENT_SIZE 3
181
182extern int __malloc_debug, __malloc_check;
183
184# define MALLOC_DEBUG(indent, fmt, args...) \
185 (__malloc_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0)
186# define MALLOC_DEBUG_INDENT(indent) \
187 (__malloc_debug ? __malloc_debug_indent (indent) : 0)
188
189extern int __malloc_debug_cur_indent;
190
191/* Print FMT and args indented at the current debug print level, followed
192 by a newline, and change the level by INDENT. */
193extern void __malloc_debug_printf (int indent, const char *fmt, ...);
194
195/* Change the current debug print level by INDENT, and return the value. */
196#define __malloc_debug_indent(indent) (__malloc_debug_cur_indent += indent)
197
198/* Set the current debug print level to LEVEL. */
199#define __malloc_debug_set_indent(level) (__malloc_debug_cur_indent = level)
200
201#else /* !MALLOC_DEBUGGING */
202# define MALLOC_DEBUG(fmt, args...) (void)0
203# define MALLOC_DEBUG_INDENT(indent) (void)0
204#endif /* MALLOC_DEBUGGING */
205
206
207/* Return SZ rounded down to POWER_OF_2_SIZE (which must be power of 2). */
208#define MALLOC_ROUND_DOWN(sz, power_of_2_size) \
209 ((sz) & ~(power_of_2_size - 1))
210/* Return SZ rounded to POWER_OF_2_SIZE (which must be power of 2). */
211#define MALLOC_ROUND_UP(sz, power_of_2_size) \
212 MALLOC_ROUND_DOWN ((sz) + (power_of_2_size - 1), (power_of_2_size))
213
214/* Return SZ rounded down to a multiple MALLOC_PAGE_SIZE. */
215#define MALLOC_ROUND_DOWN_TO_PAGE_SIZE(sz) \
216 MALLOC_ROUND_DOWN (sz, MALLOC_PAGE_SIZE)
217/* Return SZ rounded up to a multiple MALLOC_PAGE_SIZE. */
218#define MALLOC_ROUND_UP_TO_PAGE_SIZE(sz) \
219 MALLOC_ROUND_UP (sz, MALLOC_PAGE_SIZE)
220
221
222/* The malloc heap. */
223extern struct heap_free_area *__malloc_heap;
224#ifdef __UCLIBC_HAS_THREADS__
225extern malloc_mutex_t __malloc_heap_lock;
226#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
227extern malloc_mutex_t __malloc_mmb_heap_lock;
228#endif
229#endif