1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/*
* libc/stdlib/malloc/malloc.h -- small malloc implementation
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License. See the file COPYING.LIB in the main
* directory of this archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
/* The alignment we guarantee for malloc return values. */
#define MALLOC_ALIGNMENT (sizeof (double))
/* The system pagesize we assume; we really ought to get it with
getpagesize, but gee, how annoying. */
#define MALLOC_PAGE_SIZE 4096
/* The minimum size of block we request from the the system to extend the
heap for small allocations (we may request a bigger block if necessary to
satisfy a particularly big request). */
#define MALLOC_HEAP_EXTEND_SIZE MALLOC_PAGE_SIZE
/* When a heap free-area grows above this size, try to unmap it, releasing
the memory back to the system. */
#define MALLOC_UNMAP_THRESHOLD (8*MALLOC_PAGE_SIZE)
/* When unmapping a free-area, retain this many bytes if it's the only one,
to avoid completely emptying the heap. This is only a heuristic -- the
existance of another free area, even if it's smaller than
MALLOC_MIN_SIZE, will cause us not to reserve anything. */
#define MALLOC_MIN_SIZE (2*MALLOC_PAGE_SIZE)
/* When realloc shrinks an allocation, it only does so if more than this
many bytes will be freed; it must at at least HEAP_MIN_SIZE. Larger
values increase speed (by reducing heap fragmentation) at the expense of
space. */
#define MALLOC_REALLOC_MIN_FREE_SIZE (HEAP_MIN_SIZE + 16)
/* For systems with an MMU, use sbrk to map/unmap memory for the malloc
heap, instead of mmap/munmap. This is a tradeoff -- sbrk is faster than
mmap/munmap, and guarantees contiguous allocation, but is also less
flexible, and causes the heap to only be shrinkable from the end. */
#ifdef __UCLIBC_HAS_MMU__
# define MALLOC_USE_SBRK
#endif
/* The size of a malloc allocation is stored in a size_t word
MALLOC_ALIGNMENT bytes prior to the start address of the allocation:
+--------+---------+-------------------+
| SIZE |(unused) | allocation ... |
+--------+---------+-------------------+
^ BASE ^ ADDR
^ ADDR - MALLOC_ALIGN
*/
/* The amount of extra space used by the malloc header. */
#define MALLOC_HEADER_SIZE MALLOC_ALIGNMENT
/* Set up the malloc header, and return the user address of a malloc block. */
#define MALLOC_SETUP(base, size) \
(MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE))
/* Set the size of a malloc allocation, given the base address. */
#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size))
/* Return base-address of a malloc allocation, given the user address. */
#define MALLOC_BASE(addr) ((void *)((char *)addr - MALLOC_HEADER_SIZE))
/* Return the size of a malloc allocation, given the user address. */
#define MALLOC_SIZE(addr) (*(size_t *)MALLOC_BASE(addr))
/* Locking for multithreaded apps. */
#ifdef __UCLIBC_HAS_THREADS__
# include <pthread.h>
# define MALLOC_USE_LOCKING
typedef pthread_mutex_t malloc_mutex_t;
# define MALLOC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
/* The main malloc lock. This must be hold while accessing __malloc_heap,
and in order to gain __malloc_sbrk_lock. */
extern malloc_mutex_t __malloc_lock;
# define __malloc_lock() pthread_mutex_lock (&__malloc_lock)
# define __malloc_unlock() pthread_mutex_unlock (&__malloc_lock)
# ifdef MALLOC_USE_SBRK
/* This lock is used to serialize uses of the `sbrk' function (in both
malloc and free, sbrk may be used several times in succession, and
things will break if these multiple calls are interleaved with another
thread's use of sbrk!). */
extern malloc_mutex_t __malloc_sbrk_lock;
# define __malloc_lock_sbrk() pthread_mutex_lock (&__malloc_sbrk_lock)
# define __malloc_unlock_sbrk() pthread_mutex_unlock (&__malloc_sbrk_lock)
# endif /* MALLOC_USE_SBRK */
#else /* !__UCLIBC_HAS_THREADS__ */
/* Without threads, mutex operations are a nop. */
# define __malloc_lock() (void)0
# define __malloc_unlock() (void)0
# define __malloc_lock_sbrk() (void)0
# define __malloc_unlock_sbrk() (void)0
#endif /* __UCLIBC_HAS_THREADS__ */
/* branch-prediction macros; they may already be defined by libc. */
#ifndef likely
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
#define likely(cond) __builtin_expect(!!(int)(cond), 1)
#define unlikely(cond) __builtin_expect((int)(cond), 0)
#else
#define likely(cond) (cond)
#define unlikely(cond) (cond)
#endif
#endif /* !likely */
/* Define MALLOC_DEBUGGING to cause malloc to emit debugging info to stderr
when the variable __malloc_debug is set to true. */
#ifdef MALLOC_DEBUGGING
#include <stdio.h>
extern int __malloc_debug;
#define MALLOC_DEBUG(fmt, args...) \
(__malloc_debug ? fprintf (stderr, fmt , ##args) : 0)
#else
#define MALLOC_DEBUG(fmt, args...) (void)0
#endif
/* Return SZ rounded down to POWER_OF_2_SIZE (which must be power of 2). */
#define MALLOC_ROUND_DOWN(sz, power_of_2_size) \
((sz) & ~(power_of_2_size - 1))
/* Return SZ rounded to POWER_OF_2_SIZE (which must be power of 2). */
#define MALLOC_ROUND_UP(sz, power_of_2_size) \
MALLOC_ROUND_DOWN ((sz) + (power_of_2_size - 1), (power_of_2_size))
/* Return SZ rounded down to a multiple MALLOC_PAGE_SIZE. */
#define MALLOC_ROUND_DOWN_TO_PAGE_SIZE(sz) \
MALLOC_ROUND_DOWN (sz, MALLOC_PAGE_SIZE)
/* Return SZ rounded up to a multiple MALLOC_PAGE_SIZE. */
#define MALLOC_ROUND_UP_TO_PAGE_SIZE(sz) \
MALLOC_ROUND_UP (sz, MALLOC_PAGE_SIZE)
/* The malloc heap. */
extern struct heap __malloc_heap;
|