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