1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | #if HAVE_CONFIG_H1 |
23 | #include "config.h" |
24 | #endif |
25 | |
26 | #include <rtems/system.h> |
27 | #include <rtems/score/sysstate.h> |
28 | #include <rtems/score/heap.h> |
29 | |
30 | #ifndef HEAP_PROTECTION |
31 | #define _Heap_Protection_free_delayed_blocks( heap, alloc_begin )0 false0 |
32 | #else |
33 | static bool_Bool _Heap_Protection_free_delayed_blocks(0 |
34 | Heap_Control *heap,0 |
35 | uintptr_t alloc_begin0 |
36 | )0 |
37 | { |
38 | bool_Bool search_again = false0; |
39 | uintptr_t const blocks_to_free_count = |
40 | (heap->Protection.delayed_free_block_count + 1) / 2; |
41 | |
42 | if ( alloc_begin == 0 && blocks_to_free_count > 0 ) { |
43 | Heap_Block *block_to_free = heap->Protection.first_delayed_free_block; |
44 | uintptr_t count = 0; |
45 | |
46 | for ( count = 0; count < blocks_to_free_count; ++count ) { |
47 | Heap_Block *next_block_to_free = |
48 | block_to_free->Protection_begin.next_delayed_free_block; |
49 | |
50 | block_to_free->Protection_begin.next_delayed_free_block = |
51 | HEAP_PROTECTION_OBOLUS; |
52 | |
53 | _Heap_Free( |
54 | heap, |
55 | (void *) _Heap_Alloc_area_of_block( block_to_free ) |
56 | ); |
57 | |
58 | block_to_free = next_block_to_free; |
59 | } |
60 | |
61 | heap->Protection.delayed_free_block_count -= blocks_to_free_count; |
62 | heap->Protection.first_delayed_free_block = block_to_free; |
63 | |
64 | search_again = true1; |
65 | } |
66 | |
67 | return search_again; |
68 | } |
69 | #endif |
70 | |
71 | #ifdef RTEMS_HEAP_DEBUG |
72 | static void _Heap_Check_allocation(((void) 0) |
73 | const Heap_Control *heap,((void) 0) |
74 | const Heap_Block *block,((void) 0) |
75 | uintptr_t alloc_begin,((void) 0) |
76 | uintptr_t alloc_size,((void) 0) |
77 | uintptr_t alignment,((void) 0) |
78 | uintptr_t boundary((void) 0) |
79 | )((void) 0) |
80 | { |
81 | uintptr_t const min_block_size = heap->min_block_size; |
82 | uintptr_t const page_size = heap->page_size; |
83 | |
84 | uintptr_t const block_begin = (uintptr_t) block; |
85 | uintptr_t const block_size = _Heap_Block_size( block ); |
86 | uintptr_t const block_end = block_begin + block_size; |
87 | |
88 | uintptr_t const alloc_end = alloc_begin + alloc_size; |
89 | |
90 | uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block ); |
91 | uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin; |
92 | |
93 | _HAssert( block_size >= min_block_size )((void) 0); |
94 | _HAssert( block_begin < block_end )((void) 0); |
95 | _HAssert(((void) 0) |
96 | _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )((void) 0) |
97 | )((void) 0); |
98 | _HAssert(((void) 0) |
99 | _Heap_Is_aligned( block_size, page_size )((void) 0) |
100 | )((void) 0); |
101 | |
102 | _HAssert( alloc_end <= block_end + HEAP_ALLOC_BONUS )((void) 0); |
103 | _HAssert( alloc_area_begin == block_begin + HEAP_BLOCK_HEADER_SIZE)((void) 0); |
104 | _HAssert( alloc_area_offset < page_size )((void) 0); |
105 | |
106 | _HAssert( _Heap_Is_aligned( alloc_area_begin, page_size ) )((void) 0); |
107 | if ( alignment == 0 ) { |
108 | _HAssert( alloc_begin == alloc_area_begin )((void) 0); |
109 | } else { |
110 | _HAssert( _Heap_Is_aligned( alloc_begin, alignment ) )((void) 0); |
111 | } |
112 | |
113 | if ( boundary != 0 ) { |
114 | uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary ); |
115 | |
116 | _HAssert( alloc_size <= boundary )((void) 0); |
117 | _HAssert( boundary_line <= alloc_begin || alloc_end <= boundary_line )((void) 0); |
118 | } |
119 | } |
120 | #else |
121 | #define _Heap_Check_allocation( h, b, ab, as, ag, bd )((void) 0) ((void) 0) |
122 | #endif |
123 | |
124 | static uintptr_t _Heap_Check_block( |
125 | const Heap_Control *heap, |
126 | const Heap_Block *block, |
127 | uintptr_t alloc_size, |
128 | uintptr_t alignment, |
129 | uintptr_t boundary |
130 | ) |
131 | { |
132 | uintptr_t const page_size = heap->page_size; |
133 | uintptr_t const min_block_size = heap->min_block_size; |
134 | |
135 | uintptr_t const block_begin = (uintptr_t) block; |
136 | uintptr_t const block_size = _Heap_Block_size( block ); |
137 | uintptr_t const block_end = block_begin + block_size; |
138 | |
139 | uintptr_t const alloc_begin_floor = _Heap_Alloc_area_of_block( block ); |
140 | uintptr_t const alloc_begin_ceiling = block_end - min_block_size |
141 | + HEAP_BLOCK_HEADER_SIZE(2 * sizeof(uintptr_t) + 0) + page_size - 1; |
142 | |
143 | uintptr_t alloc_end = block_end + HEAP_ALLOC_BONUSsizeof(uintptr_t); |
144 | uintptr_t alloc_begin = alloc_end - alloc_size; |
145 | |
146 | alloc_begin = _Heap_Align_down( alloc_begin, alignment ); |
147 | |
148 | |
149 | if ( alloc_begin > alloc_begin_ceiling ) { |
150 | alloc_begin = _Heap_Align_down( alloc_begin_ceiling, alignment ); |
151 | } |
152 | |
153 | alloc_end = alloc_begin + alloc_size; |
154 | |
155 | |
156 | if ( boundary != 0 ) { |
157 | uintptr_t const boundary_floor = alloc_begin_floor + alloc_size; |
158 | uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary ); |
159 | |
160 | while ( alloc_begin < boundary_line && boundary_line < alloc_end ) { |
161 | if ( boundary_line < boundary_floor ) { |
162 | return 0; |
163 | } |
164 | alloc_begin = boundary_line - alloc_size; |
165 | alloc_begin = _Heap_Align_down( alloc_begin, alignment ); |
166 | alloc_end = alloc_begin + alloc_size; |
167 | boundary_line = _Heap_Align_down( alloc_end, boundary ); |
168 | } |
169 | } |
170 | |
171 | |
172 | if ( alloc_begin >= alloc_begin_floor ) { |
173 | uintptr_t const alloc_block_begin = |
174 | (uintptr_t) _Heap_Block_of_alloc_area( alloc_begin, page_size ); |
175 | uintptr_t const free_size = alloc_block_begin - block_begin; |
176 | |
177 | if ( free_size >= min_block_size || free_size == 0 ) { |
178 | return alloc_begin; |
179 | } |
180 | } |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | void *_Heap_Allocate_aligned_with_boundary( |
186 | Heap_Control *heap, |
187 | uintptr_t alloc_size, |
188 | uintptr_t alignment, |
189 | uintptr_t boundary |
190 | ) |
191 | { |
192 | Heap_Statistics *const stats = &heap->stats; |
193 | uintptr_t const block_size_floor = alloc_size + HEAP_BLOCK_HEADER_SIZE(2 * sizeof(uintptr_t) + 0) |
194 | - HEAP_ALLOC_BONUSsizeof(uintptr_t); |
195 | uintptr_t const page_size = heap->page_size; |
196 | Heap_Block *block = NULL((void*)0); |
197 | uintptr_t alloc_begin = 0; |
198 | uint32_t search_count = 0; |
199 | bool_Bool search_again = false0; |
200 | |
201 | if ( block_size_floor < alloc_size ) { |
202 | |
203 | return NULL((void*)0); |
204 | } |
205 | |
206 | if ( boundary != 0 ) { |
207 | if ( boundary < alloc_size ) { |
208 | return NULL((void*)0); |
209 | } |
210 | |
211 | if ( alignment == 0 ) { |
212 | alignment = page_size; |
213 | } |
214 | } |
215 | |
216 | do { |
217 | Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap ); |
218 | |
219 | block = _Heap_Free_list_first( heap ); |
220 | while ( block != free_list_tail ) { |
221 | _HAssert( _Heap_Is_prev_used( block ) )((void) 0); |
222 | |
223 | _Heap_Protection_block_check( heap, block )((void) 0); |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | if ( block->size_and_flag > block_size_floor ) { |
231 | if ( alignment == 0 ) { |
232 | alloc_begin = _Heap_Alloc_area_of_block( block ); |
233 | } else { |
234 | alloc_begin = _Heap_Check_block( |
235 | heap, |
236 | block, |
237 | alloc_size, |
238 | alignment, |
239 | boundary |
240 | ); |
241 | } |
242 | } |
243 | |
244 | |
245 | ++search_count; |
246 | |
247 | if ( alloc_begin != 0 ) { |
248 | break; |
249 | } |
250 | |
251 | block = block->next; |
252 | } |
253 | |
254 | search_again = _Heap_Protection_free_delayed_blocks( heap, alloc_begin )0; |
255 | } while ( search_again ); |
256 | |
257 | if ( alloc_begin != 0 ) { |
258 | |
259 | ++stats->allocs; |
260 | stats->searches += search_count; |
261 | |
262 | block = _Heap_Block_allocate( heap, block, alloc_begin, alloc_size ); |
| Value stored to 'block' is never read |
263 | |
264 | _Heap_Check_allocation(((void) 0) |
265 | heap,((void) 0) |
266 | block,((void) 0) |
267 | alloc_begin,((void) 0) |
268 | alloc_size,((void) 0) |
269 | alignment,((void) 0) |
270 | boundary((void) 0) |
271 | )((void) 0); |
272 | } |
273 | |
274 | |
275 | if ( stats->max_search < search_count ) { |
276 | stats->max_search = search_count; |
277 | } |
278 | |
279 | return (void *) alloc_begin; |
280 | } |