1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2015 Google, Inc. All rights reserved
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7
8 #include <lib/cmpctmalloc.h>
9
10 #include <assert.h>
11 #include <inttypes.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <debug.h>
17 #include <err.h>
18 #include <kernel/mutex.h>
19 #include <kernel/spinlock.h>
20 #include <kernel/thread.h>
21 #include <lib/counters.h>
22 #include <lib/heap.h>
23 #include <platform.h>
24 #include <trace.h>
25 #include <vm/vm.h>
26
27 // Malloc implementation tuned for space.
28 //
29 // Allocation strategy takes place with a global mutex. Freelist entries are
30 // kept in linked lists with 8 different sizes per binary order of magnitude
31 // and the header size is two words with eager coalescing on free.
32 //
33 // ## Concepts ##
34 //
35 // OS allocation:
36 // A contiguous range of pages allocated from the OS using heap_page_alloc(),
37 // typically via heap_grow(). Initial layout:
38 //
39 // Low addr =>
40 // header_t left_sentinel -- Marked as allocated, |left| pointer NULL.
41 // free_t memory_area -- Marked as free, with appropriate size,
42 // and pointed to by a free bucket.
43 // [bulk of usable memory]
44 // header_t right_sentinel -- Marked as allocated, size zero
45 // <= High addr
46 //
47 // For a normal allocation, the free memory area is added to the
48 // appropriate free bucket and picked up later in the cmpct_alloc()
49 // logic. For a large allocation, the area skips the primary free buckets
50 // and is returned directly via a |free_t** bucket| param.
51 //
52 // cmpctmalloc does not keep a list of OS allocations; each is meant to free
53 // itself to the OS when all of its memory areas become free.
54 //
55 // Memory area:
56 // A sub-range of an OS allocation. Used to satisfy
57 // cmpct_alloc()/cmpct_memalign() calls. Can be free and live in a free
58 // bucket, or can be allocated and managed by the user.
59 //
60 // Memory areas, both free and allocated, always begin with a header_t,
61 // followed by the area's usable memory. header_t.size includes the size of
62 // the header. untag(header_t.left) points to the preceding area's header_t.
63 //
64 // The low bits of header_t.left hold additional flags about the area:
65 // - FREE_BIT: The area is free, and lives in a free bucket.
66 // These bits shouldn't be checked directly; use the is_tagged_as_*()
67 // functions.
68 //
69 // If the area is free (is_tagged_as_free(header_t*)), the area's header
70 // includes the doubly-linked free list pointers defined by free_t (which is a
71 // header_t overlay). Those pointers are used to chain the free area off of
72 // the appropriately-sized free bucket.
73 //
74 // Normal (small/non-large) allocation:
75 // An alloction of less than HEAP_LARGE_ALLOC_BYTES, which can fit in a free
76 // bucket.
77 //
78 // Large allocation:
79 // An alloction of more than HEAP_LARGE_ALLOC_BYTES. This is no longer allowed.
80 //
81 // Free buckets:
82 // Freelist entries are kept in linked lists with 8 different sizes per binary
83 // order of magnitude: heap.free_lists[NUMBER_OF_BUCKETS]
84 //
85 // Allocations are always rounded up to the nearest bucket size. This would
86 // appear to waste memory, but in fact it avoids some fragmentation.
87 //
88 // Consider two buckets with size 512 and 576 (512 + 64). Perhaps the program
89 // often allocates 528 byte objects for some reason. When we need to allocate
90 // 528 bytes, we round that up to 576 bytes. When it is freed, it goes in the
91 // 576 byte bucket, where it is available for the next of the common 528 byte
92 // allocations.
93 //
94 // If we did not round up allocations, then (assuming no coalescing is
95 // possible) we would have to place the freed 528 bytes in the 512 byte
96 // bucket, since only memory areas greater than or equal to 576 bytes can go
97 // in the 576 byte bucket. The next time we need to allocate a 528 byte object
98 // we do not look in the 512 byte bucket, because we want to be sure the first
99 // memory area we look at is big enough, to avoid searching a long chain of
100 // just-too-small memory areas on the free list. We would not find the 528
101 // byte space and would have to carve out a new 528 byte area from a large
102 // free memory area, making fragmentation worse.
103 //
104 // cmpct_free() behavior:
105 // Freed memory areas are eagerly coalesced with free left/right neighbors. If
106 // the new free area covers an entire OS allocation (i.e., its left and right
107 // neighbors are both sentinels), the OS allocation is returned to the OS.
108 //
109 // Exception: to avoid OS free/alloc churn when right on the edge, the heap
110 // will try to hold onto one entirely-free, non-large OS allocation instead of
111 // returning it to the OS. See cached_os_alloc.
112
113 #if defined(DEBUG) || LK_DEBUGLEVEL > 2
114 #define CMPCT_DEBUG
115 #endif
116
117 #define LOCAL_TRACE 0
118
119 KCOUNTER_MAX(max_allocation, "kernel.heap.max_allocation");
120
121 // Use HEAP_ENABLE_TESTS to enable internal testing. The tests are not useful
122 // when the target system is up. By that time we have done hundreds of allocations
123 // already.
124
125 #define ALLOC_FILL 0x99
126 #define FREE_FILL 0x77
127 #define PADDING_FILL 0x55
128
129 #if !defined(HEAP_GROW_SIZE)
130 #define HEAP_GROW_SIZE (1 * 1024 * 1024) /* Grow aggressively */
131 #endif
132
133 static_assert(IS_PAGE_ALIGNED(HEAP_GROW_SIZE), "");
134
135 #define HEAP_ALLOC_VIRTUAL_BITS 22
136 #define HEAP_LARGE_ALLOC_BYTES (1u << HEAP_ALLOC_VIRTUAL_BITS)
137
138 // When we grow the heap we have to have somewhere in the freelist to put the
139 // resulting freelist entry, so the freelist has to have a certain number of
140 // buckets.
141 static_assert(HEAP_GROW_SIZE <= HEAP_LARGE_ALLOC_BYTES, "");
142
143 // Buckets for allocations. The smallest 15 buckets are 8, 16, 24, etc. up to
144 // 120 bytes. After that we round up to the nearest size that can be written
145 // /^0*1...0*$/, giving 8 buckets per order of binary magnitude. The freelist
146 // entries in a given bucket have at least the given size, plus the header
147 // size. On 64 bit, the 8 byte bucket is useless, since the freelist header
148 // is 16 bytes larger than the header, but we have it for simplicity.
149 #define NUMBER_OF_BUCKETS (1 + 15 + (HEAP_ALLOC_VIRTUAL_BITS - 7) * 8)
150
151 // If a header's |left| field has this bit set, it is free and lives in
152 // a free bucket.
153 #define FREE_BIT (1 << 0)
154
155 #define HEADER_LEFT_BIT_MASK (FREE_BIT)
156
157 // All individual memory areas on the heap start with this.
158 typedef struct header_struct {
159 // Pointer to the previous area in memory order. The lower bit is used
160 // to store extra state: see FREE_BIT. The left sentinel will have
161 // NULL in the address portion of this field. Left and right sentinels
162 // will always be marked as "allocated" to avoid coalescing.
163 struct header_struct* left;
164 // The size of the memory area in bytes, including this header.
165 // The right sentinel will have 0 in this field.
166 size_t size;
167 } header_t;
168
169 typedef struct free_struct {
170 header_t header;
171 struct free_struct* next;
172 struct free_struct* prev;
173 } free_t;
174
175 struct heap {
176 // Total bytes allocated from the OS for the heap.
177 size_t size;
178
179 // Bytes of usable free space in the heap.
180 size_t remaining;
181
182 // A non-large OS allocation that could have been freed to the OS but
183 // wasn't. We will attempt to use this before allocating more memory from
184 // the OS, to reduce churn. May be null. If non-null, cached_os_alloc->size
185 // holds the total size allocated from the OS for this block.
186 header_t* cached_os_alloc;
187
188 // Guards all elements in this structure. See lock(), unlock().
189 mutex_t lock;
190
191 // Free lists, bucketed by size. See size_to_index_helper().
192 free_t* free_lists[NUMBER_OF_BUCKETS];
193
194 // Bitmask that tracks whether a given free_lists entry has any elements.
195 // See set_free_list_bit(), clear_free_list_bit().
196 #define BUCKET_WORDS (((NUMBER_OF_BUCKETS) + 31) >> 5)
197 uint32_t free_list_bits[BUCKET_WORDS];
198 };
199
200 // Heap static vars.
201 static struct heap theheap;
202
203 static ssize_t heap_grow(size_t len);
204
lock(void)205 static void lock(void) TA_ACQ(theheap.lock) {
206 mutex_acquire(&theheap.lock);
207 }
208
unlock(void)209 static void unlock(void) TA_REL(theheap.lock) {
210 mutex_release(&theheap.lock);
211 }
212
dump_free(header_t * header)213 static void dump_free(header_t* header) {
214 dprintf(INFO, "\t\tbase %p, end %#" PRIxPTR ", len %#zx (%zu)\n",
215 header, (vaddr_t)header + header->size, header->size, header->size);
216 }
217
cmpct_dump(bool panic_time)218 void cmpct_dump(bool panic_time) TA_NO_THREAD_SAFETY_ANALYSIS {
219 if (!panic_time) {
220 lock();
221 }
222
223 dprintf(INFO, "Heap dump (using cmpctmalloc):\n");
224 dprintf(INFO, "\tsize %lu, remaining %lu, cached free %lu\n",
225 (unsigned long)theheap.size,
226 (unsigned long)theheap.remaining,
227 theheap.cached_os_alloc ? theheap.cached_os_alloc->size : 0);
228
229 dprintf(INFO, "\tfree list:\n");
230 for (int i = 0; i < NUMBER_OF_BUCKETS; i++) {
231 bool header_printed = false;
232 free_t* free_area = theheap.free_lists[i];
233 for (; free_area != NULL; free_area = free_area->next) {
234 ASSERT(free_area != free_area->next);
235 if (!header_printed) {
236 dprintf(INFO, "\tbucket %d\n", i);
237 header_printed = true;
238 }
239 dump_free(&free_area->header);
240 }
241 }
242
243 if (!panic_time) {
244 unlock();
245 }
246 }
247
cmpct_get_info(size_t * size_bytes,size_t * free_bytes)248 void cmpct_get_info(size_t* size_bytes, size_t* free_bytes) {
249 lock();
250 *size_bytes = theheap.size;
251 *free_bytes = theheap.remaining;
252 unlock();
253 }
254
255 // Operates in sizes that don't include the allocation header;
256 // i.e., the usable portion of a memory area.
size_to_index_helper(size_t size,size_t * rounded_up_out,int adjust,int increment)257 static int size_to_index_helper(
258 size_t size, size_t* rounded_up_out, int adjust, int increment) {
259 // First buckets are simply 8-spaced up to 128.
260 if (size <= 128) {
261 if (sizeof(size_t) == 8u && size <= sizeof(free_t) - sizeof(header_t)) {
262 *rounded_up_out = sizeof(free_t) - sizeof(header_t);
263 } else {
264 *rounded_up_out = size;
265 }
266 // No allocation is smaller than 8 bytes, so the first bucket is for 8
267 // byte spaces (not including the header). For 64 bit, the free list
268 // struct is 16 bytes larger than the header, so no allocation can be
269 // smaller than that (otherwise how to free it), but we have empty 8
270 // and 16 byte buckets for simplicity.
271 return (int)((size >> 3) - 1);
272 }
273
274 // We are going to go up to the next size to round up, but if we hit a
275 // bucket size exactly we don't want to go up. By subtracting 8 here, we
276 // will do the right thing (the carry propagates up for the round numbers
277 // we are interested in).
278 size += adjust;
279 // After 128 the buckets are logarithmically spaced, every 16 up to 256,
280 // every 32 up to 512 etc. This can be thought of as rows of 8 buckets.
281 // GCC intrinsic count-leading-zeros.
282 // Eg. 128-255 has 24 leading zeros and we want row to be 4.
283 unsigned row = (unsigned)(sizeof(size_t) * 8 - 4 - __builtin_clzl(size));
284 // For row 4 we want to shift down 4 bits.
285 unsigned column = (size >> row) & 7;
286 int row_column = (row << 3) | column;
287 row_column += increment;
288 size = (8 + (row_column & 7)) << (row_column >> 3);
289 *rounded_up_out = size;
290 // We start with 15 buckets, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96,
291 // 104, 112, 120. Then we have row 4, sizes 128 and up, with the
292 // row-column 8 and up.
293 int answer = row_column + 15 - 32;
294 DEBUG_ASSERT(answer < NUMBER_OF_BUCKETS);
295 return answer;
296 }
297
298 // Round up size to next bucket when allocating.
size_to_index_allocating(size_t size,size_t * rounded_up_out)299 static int size_to_index_allocating(size_t size, size_t* rounded_up_out) {
300 size_t rounded = ROUNDUP(size, 8);
301 return size_to_index_helper(rounded, rounded_up_out, -8, 1);
302 }
303
304 // Round down size to next bucket when freeing.
size_to_index_freeing(size_t size)305 static int size_to_index_freeing(size_t size) {
306 size_t dummy;
307 return size_to_index_helper(size, &dummy, 0, 0);
308 }
309
tag_as_free(void * left)310 static inline header_t* tag_as_free(void* left) {
311 return (header_t*)((uintptr_t)left | FREE_BIT);
312 }
313
314 // Returns true if this header_t is marked as free.
is_tagged_as_free(const header_t * header)315 static inline bool is_tagged_as_free(const header_t* header) {
316 // The free bit is stashed in the lower bit of header->left.
317 return ((uintptr_t)(header->left) & FREE_BIT) != 0;
318 }
319
untag(const void * left)320 static inline header_t* untag(const void* left) {
321 return (header_t*)((uintptr_t)left & ~HEADER_LEFT_BIT_MASK);
322 }
323
right_header(header_t * header)324 static inline header_t* right_header(header_t* header) {
325 return (header_t*)((char*)header + header->size);
326 }
327
set_free_list_bit(int index)328 static inline void set_free_list_bit(int index) {
329 theheap.free_list_bits[index >> 5] |= (1u << (31 - (index & 0x1f)));
330 }
331
clear_free_list_bit(int index)332 static inline void clear_free_list_bit(int index) {
333 theheap.free_list_bits[index >> 5] &= ~(1u << (31 - (index & 0x1f)));
334 }
335
find_nonempty_bucket(int index)336 static int find_nonempty_bucket(int index) {
337 uint32_t mask = (1u << (31 - (index & 0x1f))) - 1;
338 mask = mask * 2 + 1;
339 mask &= theheap.free_list_bits[index >> 5];
340 if (mask != 0) {
341 return (index & ~0x1f) + __builtin_clz(mask);
342 }
343 for (index = ROUNDUP(index + 1, 32);
344 index <= NUMBER_OF_BUCKETS; index += 32) {
345 mask = theheap.free_list_bits[index >> 5];
346 if (mask != 0u) {
347 return index + __builtin_clz(mask);
348 }
349 }
350 return -1;
351 }
352
is_start_of_os_allocation(const header_t * header)353 static bool is_start_of_os_allocation(const header_t* header) {
354 return untag(header->left) == untag(NULL);
355 }
356
create_free_area(void * address,void * left,size_t size)357 static void create_free_area(void* address, void* left, size_t size) {
358 free_t* free_area = (free_t*)address;
359 free_area->header.size = size;
360 free_area->header.left = tag_as_free(left);
361
362 int index = size_to_index_freeing(size - sizeof(header_t));
363 set_free_list_bit(index);
364 free_t** bucket = &theheap.free_lists[index];
365
366 free_t* old_head = *bucket;
367 if (old_head != NULL) {
368 old_head->prev = free_area;
369 }
370 free_area->next = old_head;
371 free_area->prev = NULL;
372 *bucket = free_area;
373 theheap.remaining += size;
374 #ifdef CMPCT_DEBUG
375 memset(free_area + 1, FREE_FILL, size - sizeof(free_t));
376 #endif
377 }
378
is_end_of_os_allocation(char * address)379 static bool is_end_of_os_allocation(char* address) {
380 return ((header_t*)address)->size == 0;
381 }
382
free_to_os(void * ptr,size_t size)383 static void free_to_os(void* ptr, size_t size) {
384 DEBUG_ASSERT(IS_PAGE_ALIGNED(ptr));
385 DEBUG_ASSERT(IS_PAGE_ALIGNED(size));
386 heap_page_free(ptr, size >> PAGE_SIZE_SHIFT);
387 theheap.size -= size;
388 }
389
390 // May call free_to_os(), or may cache the (non-large) OS allocation in
391 // cached_os_alloc. |left_sentinel| is the start of the OS allocation, and
392 // |total_size| is the (page-aligned) number of bytes that were originally
393 // allocated from the OS.
possibly_free_to_os(header_t * left_sentinel,size_t total_size)394 static void possibly_free_to_os(header_t *left_sentinel, size_t total_size) {
395 if (theheap.cached_os_alloc == NULL) {
396 LTRACEF("Keeping 0x%zx-byte OS alloc @%p\n", total_size, left_sentinel);
397 theheap.cached_os_alloc = left_sentinel;
398 theheap.cached_os_alloc->left = NULL;
399 theheap.cached_os_alloc->size = total_size;
400 } else {
401 LTRACEF("Returning 0x%zx bytes @%p to OS\n",
402 total_size, left_sentinel);
403 free_to_os(left_sentinel, total_size);
404 }
405 }
406
407 // Frees |size| bytes starting at |address|, either to a free bucket or to the
408 // OS (in which case the left/right sentinels are freed as well). |address|
409 // should point to what would be the header_t of the memory area to free, and
410 // |left| and |size| should be set to the values that the header_t would have
411 // contained. This is broken out because the header_t will not contain the
412 // proper size when coalescing neighboring areas.
free_memory(void * address,void * left,size_t size)413 static void free_memory(void* address, void* left, size_t size) {
414 left = untag(left);
415 if (IS_PAGE_ALIGNED(left) &&
416 is_start_of_os_allocation((const header_t*)left) &&
417 is_end_of_os_allocation((char*)address + size)) {
418
419 // Assert that it's safe to do a simple 2*sizeof(header_t)) below.
420 DEBUG_ASSERT_MSG(((header_t*)left)->size == sizeof(header_t),
421 "Unexpected left sentinel size %zu != header size %zu",
422 ((header_t*)left)->size, sizeof(header_t));
423 possibly_free_to_os((header_t*)left, size + 2 * sizeof(header_t));
424 } else {
425 create_free_area(address, left, size);
426 }
427 }
428
unlink_free(free_t * free_area,int bucket)429 static void unlink_free(free_t* free_area, int bucket) {
430 theheap.remaining -= free_area->header.size;
431 ASSERT(theheap.remaining < 4000000000u);
432 free_t* next = free_area->next;
433 free_t* prev = free_area->prev;
434 if (theheap.free_lists[bucket] == free_area) {
435 theheap.free_lists[bucket] = next;
436 if (next == NULL) {
437 clear_free_list_bit(bucket);
438 }
439 }
440 if (prev != NULL) {
441 prev->next = next;
442 }
443 if (next != NULL) {
444 next->prev = prev;
445 }
446 }
447
unlink_free_unknown_bucket(free_t * free_area)448 static void unlink_free_unknown_bucket(free_t* free_area) {
449 return unlink_free(
450 free_area,
451 size_to_index_freeing(free_area->header.size - sizeof(header_t)));
452 }
453
create_allocation_header(void * address,size_t offset,size_t size,void * left)454 static void* create_allocation_header(
455 void* address, size_t offset, size_t size, void* left) {
456
457 header_t* standalone = (header_t*)((char*)address + offset);
458 standalone->left = untag(left);
459 standalone->size = size;
460 return standalone + 1;
461 }
462
FixLeftPointer(header_t * right,header_t * new_left)463 static void FixLeftPointer(header_t* right, header_t* new_left) {
464 int tag = (uintptr_t)right->left & 1;
465 right->left = (header_t*)(((uintptr_t)new_left & ~1) | tag);
466 }
467
check_free_fill(void * ptr,size_t size)468 static void check_free_fill(void* ptr, size_t size) {
469 // The first 16 bytes of the region won't have free fill due to overlap
470 // with the allocator bookkeeping.
471 const size_t start = sizeof(free_t) - sizeof(header_t);
472 for (size_t i = start; i < size; ++i) {
473 uint8_t byte = ((uint8_t*)ptr)[i];
474 if (byte != FREE_FILL) {
475 platform_panic_start();
476 printf("Heap free fill check fail. Allocated region:\n");
477 hexdump8(ptr, size);
478 panic("allocating %lu bytes, fill was %02x, offset %lu\n",
479 size, byte, i);
480 }
481 }
482 }
483
484 #ifdef HEAP_ENABLE_TESTS
485
WasteFreeMemory(void)486 static void WasteFreeMemory(void) {
487 while (theheap.remaining != 0) {
488 cmpct_alloc(1);
489 }
490 }
491
492 // If we just make a big allocation it gets rounded off. If we actually
493 // want to use a reasonably accurate amount of memory for test purposes, we
494 // have to do many small allocations.
TestTrimHelper(ssize_t target)495 static void* TestTrimHelper(ssize_t target) {
496 char* answer = NULL;
497 size_t remaining = theheap.remaining;
498 while (theheap.remaining - target > 512) {
499 char* next_block = cmpct_alloc(8 + ((theheap.remaining - target) >> 2));
500 *(char**)next_block = answer;
501 answer = next_block;
502 if (theheap.remaining > remaining) {
503 return answer;
504 }
505 // Abandon attempt to hit particular freelist entry size if we
506 // accidentally got more memory from the OS.
507 remaining = theheap.remaining;
508 }
509 return answer;
510 }
511
TestTrimFreeHelper(char * block)512 static void TestTrimFreeHelper(char* block) {
513 while (block) {
514 char* next_block = *(char**)block;
515 cmpct_free(block);
516 block = next_block;
517 }
518 }
519
cmpct_test_trim(void)520 static void cmpct_test_trim(void) {
521 // XXX: Re-enable this test if we want, disabled due to float math
522 return;
523 WasteFreeMemory();
524
525 size_t test_sizes[200];
526 int sizes = 0;
527
528 for (size_t s = 1; s < PAGE_SIZE * 4; s = (s + 1) * 1.1) {
529 test_sizes[sizes++] = s;
530 ASSERT(sizes < 200);
531 }
532 for (ssize_t s = -32; s <= 32; s += 8) {
533 test_sizes[sizes++] = PAGE_SIZE + s;
534 ASSERT(sizes < 200);
535 }
536
537 // Test allocations at the start of an OS allocation.
538 for (int with_second_alloc = 0;
539 with_second_alloc < 2; with_second_alloc++) {
540 for (int i = 0; i < sizes; i++) {
541 size_t s = test_sizes[i];
542
543 char *a, *a2 = NULL;
544 a = cmpct_alloc(s);
545 if (with_second_alloc) {
546 a2 = cmpct_alloc(1);
547 if (s<PAGE_SIZE>> 1) {
548 // It is the intention of the test that a is at the start
549 // of an OS allocation and that a2 is "right after" it.
550 // Otherwise we are not testing what I thought. OS
551 // allocations are certainly not smaller than a page, so
552 // check in that case.
553 ASSERT((uintptr_t)(a2 - a) < s * 1.13 + 48);
554 }
555 }
556 cmpct_trim();
557 size_t remaining = theheap.remaining;
558 // We should have < 1 page on either side of the a allocation.
559 ASSERT(remaining < PAGE_SIZE * 2);
560 cmpct_free(a);
561 if (with_second_alloc) {
562 // Now only a2 is holding onto the OS allocation.
563 ASSERT(theheap.remaining > remaining);
564 } else {
565 ASSERT(theheap.remaining == 0);
566 }
567 remaining = theheap.remaining;
568 cmpct_trim();
569 ASSERT(theheap.remaining <= remaining);
570 // If a was at least one page then the trim should have freed up
571 // that page.
572 if (s >= PAGE_SIZE && with_second_alloc) {
573 ASSERT(theheap.remaining < remaining);
574 }
575 if (with_second_alloc) {
576 cmpct_free(a2);
577 }
578 }
579 ASSERT(theheap.remaining == 0);
580 }
581
582 ASSERT(theheap.remaining == 0);
583
584 // Now test allocations near the end of an OS allocation.
585 for (ssize_t wobble = -64; wobble <= 64; wobble += 8) {
586 for (int i = 0; i < sizes; i++) {
587 size_t s = test_sizes[i];
588
589 if ((ssize_t)s + wobble < 0) {
590 continue;
591 }
592
593 char* start_of_os_alloc = cmpct_alloc(1);
594
595 // If the OS allocations are very small this test does not make
596 // sense.
597 if (theheap.remaining <= s + wobble) {
598 cmpct_free(start_of_os_alloc);
599 continue;
600 }
601
602 char* big_bit_in_the_middle = TestTrimHelper(s + wobble);
603 size_t remaining = theheap.remaining;
604
605 // If the remaining is big we started a new OS allocation and the
606 // test makes no sense.
607 if (remaining > 128 + s * 1.13 + wobble) {
608 cmpct_free(start_of_os_alloc);
609 TestTrimFreeHelper(big_bit_in_the_middle);
610 continue;
611 }
612
613 cmpct_free(start_of_os_alloc);
614 remaining = theheap.remaining;
615
616 // This trim should sometimes trim a page off the end of the OS
617 // allocation.
618 cmpct_trim();
619 ASSERT(theheap.remaining <= remaining);
620 remaining = theheap.remaining;
621
622 // We should have < 1 page on either side of the big allocation.
623 ASSERT(remaining < PAGE_SIZE * 2);
624
625 TestTrimFreeHelper(big_bit_in_the_middle);
626 }
627 }
628 }
629
cmpct_test_buckets(void)630 static void cmpct_test_buckets(void) {
631 size_t rounded;
632 unsigned bucket;
633 // Check for the 8-spaced buckets up to 128.
634 for (unsigned i = 1; i <= 128; i++) {
635 // Round up when allocating.
636 bucket = size_to_index_allocating(i, &rounded);
637 unsigned expected = (ROUNDUP(i, 8) >> 3) - 1;
638 ASSERT(bucket == expected);
639 ASSERT(IS_ALIGNED(rounded, 8));
640 ASSERT(rounded >= i);
641 if (i >= sizeof(free_t) - sizeof(header_t)) {
642 // Once we get above the size of the free area struct (4 words), we
643 // won't round up much for these small size.
644 ASSERT(rounded - i < 8);
645 }
646 // Only rounded sizes are freed.
647 if ((i & 7) == 0) {
648 // Up to size 128 we have exact buckets for each multiple of 8.
649 ASSERT(bucket == (unsigned)size_to_index_freeing(i));
650 }
651 }
652 int bucket_base = 7;
653 for (unsigned j = 16; j < 1024; j *= 2, bucket_base += 8) {
654 // Note the "<=", which ensures that we test the powers of 2 twice to
655 // ensure that both ways of calculating the bucket number match.
656 for (unsigned i = j * 8; i <= j * 16; i++) {
657 // Round up to j multiple in this range when allocating.
658 bucket = size_to_index_allocating(i, &rounded);
659 unsigned expected = bucket_base + ROUNDUP(i, j) / j;
660 ASSERT(bucket == expected);
661 ASSERT(IS_ALIGNED(rounded, j));
662 ASSERT(rounded >= i);
663 ASSERT(rounded - i < j);
664 // Only 8-rounded sizes are freed or chopped off the end of a free
665 // area when allocating.
666 if ((i & 7) == 0) {
667 // When freeing, if we don't hit the size of the bucket
668 // precisely, we have to put the free space into a smaller
669 // bucket, because the buckets have entries that will always
670 // be big enough for the corresponding allocation size (so we
671 // don't have to traverse the free chains to find a big enough
672 // one).
673 if ((i % j) == 0) {
674 ASSERT((int)bucket == size_to_index_freeing(i));
675 } else {
676 ASSERT((int)bucket - 1 == size_to_index_freeing(i));
677 }
678 }
679 }
680 }
681 }
682
cmpct_test_get_back_newly_freed_helper(size_t size)683 static void cmpct_test_get_back_newly_freed_helper(size_t size) {
684 void* allocated = cmpct_alloc(size);
685 if (allocated == NULL) {
686 return;
687 }
688 char* allocated2 = cmpct_alloc(8);
689 char* expected_position = (char*)allocated + size;
690 if (allocated2 < expected_position ||
691 allocated2 > expected_position + 128) {
692 // If the allocated2 allocation is not in the same OS allocation as the
693 // first allocation then the test may not work as expected (the memory
694 // may be returned to the OS when we free the first allocation, and we
695 // might not get it back).
696 cmpct_free(allocated);
697 cmpct_free(allocated2);
698 return;
699 }
700
701 cmpct_free(allocated);
702 void* allocated3 = cmpct_alloc(size);
703 // To avoid churn and fragmentation we would want to get the newly freed
704 // memory back again when we allocate the same size shortly after.
705 ASSERT(allocated3 == allocated);
706 cmpct_free(allocated2);
707 cmpct_free(allocated3);
708 }
709
cmpct_test_get_back_newly_freed(void)710 static void cmpct_test_get_back_newly_freed(void) {
711 size_t increment = 16;
712 for (size_t i = 128; i <= 0x8000000; i *= 2, increment *= 2) {
713 for (size_t j = i; j < i * 2; j += increment) {
714 cmpct_test_get_back_newly_freed_helper(i - 8);
715 cmpct_test_get_back_newly_freed_helper(i);
716 cmpct_test_get_back_newly_freed_helper(i + 1);
717 }
718 }
719 for (size_t i = 1024; i <= 2048; i++) {
720 cmpct_test_get_back_newly_freed_helper(i);
721 }
722 }
723
cmpct_test_return_to_os(void)724 static void cmpct_test_return_to_os(void) {
725 cmpct_trim();
726 size_t remaining = theheap.remaining;
727 // This goes in a new OS allocation since the trim above removed any free
728 // area big enough to contain it.
729 void* a = cmpct_alloc(5000);
730 void* b = cmpct_alloc(2500);
731 cmpct_free(a);
732 cmpct_free(b);
733 // If things work as expected the new allocation is at the start of an OS
734 // allocation. There's just one sentinel and one header to the left of it.
735 // It that's not the case then the allocation was met from some space in
736 // the middle of an OS allocation, and our test won't work as expected, so
737 // bail out.
738 if (((uintptr_t)a & (PAGE_SIZE - 1)) != sizeof(header_t) * 2) {
739 return;
740 }
741 // No trim needed when the entire OS allocation is free.
742 ASSERT(remaining == theheap.remaining);
743 }
744
cmpct_test(void)745 void cmpct_test(void) {
746 cmpct_test_buckets();
747 cmpct_test_get_back_newly_freed();
748 cmpct_test_return_to_os();
749 cmpct_test_trim();
750 cmpct_dump(false);
751 void* ptr[16];
752
753 ptr[0] = cmpct_alloc(8);
754 ptr[1] = cmpct_alloc(32);
755 ptr[2] = cmpct_alloc(7);
756 cmpct_trim();
757 ptr[3] = cmpct_alloc(0);
758 ptr[4] = cmpct_alloc(98713);
759 ptr[5] = cmpct_alloc(16);
760
761 cmpct_free(ptr[5]);
762 cmpct_free(ptr[1]);
763 cmpct_free(ptr[3]);
764 cmpct_free(ptr[0]);
765 cmpct_free(ptr[4]);
766 cmpct_free(ptr[2]);
767
768 cmpct_dump(false);
769 cmpct_trim();
770 cmpct_dump(false);
771
772 int i;
773 for (i = 0; i < 16; i++)
774 ptr[i] = 0;
775
776 for (i = 0; i < 32768; i++) {
777 unsigned int index = (unsigned int)rand() % 16;
778
779 if ((i % (16 * 1024)) == 0) {
780 printf("pass %d\n", i);
781 }
782
783 // printf("index 0x%x\n", index);
784 if (ptr[index]) {
785 // printf("freeing ptr[0x%x] = %p\n", index, ptr[index]);
786 cmpct_free(ptr[index]);
787 ptr[index] = 0;
788 }
789 unsigned int align = 1 << ((unsigned int)rand() % 8);
790 ptr[index] = cmpct_memalign((unsigned int)rand() % 32768, align);
791 // printf("ptr[0x%x] = %p, align 0x%x\n", index, ptr[index], align);
792
793 DEBUG_ASSERT(((addr_t)ptr[index] % align) == 0);
794 // cmpct_dump(false);
795 }
796
797 for (i = 0; i < 16; i++) {
798 if (ptr[i]) {
799 cmpct_free(ptr[i]);
800 }
801 }
802
803 cmpct_dump(false);
804 }
805
806 #else
cmpct_test(void)807 void cmpct_test(void) {}
808 #endif // HEAP_ENABLE_TESTS
809
cmpct_trim(void)810 void cmpct_trim(void) {
811 // Look at free list entries that are at least as large as one page plus a
812 // header. They might be at the start or the end of a block, so we can trim
813 // them and free the page(s).
814 lock();
815 for (int bucket = size_to_index_freeing(PAGE_SIZE);
816 bucket < NUMBER_OF_BUCKETS;
817 bucket++) {
818 free_t* next;
819 for (free_t* free_area = theheap.free_lists[bucket];
820 free_area != NULL;
821 free_area = next) {
822 DEBUG_ASSERT(
823 free_area->header.size >= PAGE_SIZE + sizeof(header_t));
824 next = free_area->next;
825 header_t* right = right_header(&free_area->header);
826 if (is_end_of_os_allocation((char*)right)) {
827 char* old_os_allocation_end =
828 (char*)ROUNDUP((uintptr_t)right, PAGE_SIZE);
829 // The page will end with a smaller free list entry and a
830 // header-sized sentinel.
831 char* new_os_allocation_end =
832 (char*)ROUNDUP(
833 (uintptr_t)free_area +
834 sizeof(header_t) +
835 sizeof(free_t),
836 PAGE_SIZE);
837 size_t freed_up = old_os_allocation_end - new_os_allocation_end;
838 DEBUG_ASSERT(IS_PAGE_ALIGNED(freed_up));
839 // Rare, because we only look at large freelist entries, but
840 // unlucky rounding could mean we can't actually free anything
841 // here.
842 if (freed_up == 0) {
843 continue;
844 }
845 unlink_free(free_area, bucket);
846 size_t new_free_size = free_area->header.size - freed_up;
847 DEBUG_ASSERT(new_free_size >= sizeof(free_t));
848 // Right sentinel, not free, stops attempts to coalesce right.
849 create_allocation_header(
850 free_area, new_free_size, 0, free_area);
851 // Also puts it in the correct bucket.
852 create_free_area(free_area, untag(free_area->header.left),
853 new_free_size);
854 heap_page_free(new_os_allocation_end,
855 freed_up >> PAGE_SIZE_SHIFT);
856 theheap.size -= freed_up;
857 } else if (is_start_of_os_allocation(
858 untag(free_area->header.left))) {
859 char* old_os_allocation_start =
860 (char*)ROUNDDOWN((uintptr_t)free_area, PAGE_SIZE);
861 // For the sentinel, we need at least one header-size of space
862 // between the page edge and the first allocation to the right
863 // of the free area.
864 char* new_os_allocation_start =
865 (char*)ROUNDDOWN((uintptr_t)(right - 1), PAGE_SIZE);
866 size_t freed_up =
867 new_os_allocation_start - old_os_allocation_start;
868 DEBUG_ASSERT(IS_PAGE_ALIGNED(freed_up));
869 // This should not happen because we only look at the large
870 // free list buckets.
871 if (freed_up == 0) {
872 continue;
873 }
874 unlink_free(free_area, bucket);
875 size_t sentinel_size = sizeof(header_t);
876 size_t new_free_size = free_area->header.size - freed_up;
877 if (new_free_size < sizeof(free_t)) {
878 sentinel_size += new_free_size;
879 new_free_size = 0;
880 }
881 // Left sentinel, not free, stops attempts to coalesce left.
882 create_allocation_header(new_os_allocation_start, 0,
883 sentinel_size, NULL);
884 if (new_free_size == 0) {
885 FixLeftPointer(right, (header_t*)new_os_allocation_start);
886 } else {
887 DEBUG_ASSERT(new_free_size >= sizeof(free_t));
888 char* new_free = new_os_allocation_start + sentinel_size;
889 // Also puts it in the correct bucket.
890 create_free_area(new_free, new_os_allocation_start,
891 new_free_size);
892 FixLeftPointer(right, (header_t*)new_free);
893 }
894 heap_page_free(old_os_allocation_start,
895 freed_up >> PAGE_SIZE_SHIFT);
896 theheap.size -= freed_up;
897 }
898 }
899 }
900 unlock();
901 }
902
cmpct_alloc(size_t size)903 void* cmpct_alloc(size_t size) {
904 if (size == 0u) {
905 return NULL;
906 }
907
908 kcounter_max(max_allocation, size);
909
910 // Large allocations are no longer allowed. See ZX-1318 for details.
911 if (size > (HEAP_LARGE_ALLOC_BYTES - sizeof(header_t))) {
912 return NULL;
913 }
914
915 size_t rounded_up;
916 int start_bucket = size_to_index_allocating(size, &rounded_up);
917
918 rounded_up += sizeof(header_t);
919
920 lock();
921 int bucket = find_nonempty_bucket(start_bucket);
922 if (bucket == -1) {
923 // Grow heap by at least 12% if we can.
924 size_t growby = MIN(HEAP_LARGE_ALLOC_BYTES,
925 MAX(theheap.size >> 3,
926 MAX(HEAP_GROW_SIZE, rounded_up)));
927 // Try to add a new OS allocation to the heap, reducing the size until
928 // we succeed or get too small.
929 while (heap_grow(growby) < 0) {
930 if (growby <= rounded_up) {
931 unlock();
932 return NULL;
933 }
934 growby = MAX(growby >> 1, rounded_up);
935 }
936 bucket = find_nonempty_bucket(start_bucket);
937 }
938 free_t* head = theheap.free_lists[bucket];
939 size_t left_over = head->header.size - rounded_up;
940 // We can't carve off the rest for a new free space if it's smaller than the
941 // free-list linked structure. We also don't carve it off if it's less than
942 // 1.6% the size of the allocation. This is to avoid small long-lived
943 // allocations being placed right next to large allocations, hindering
944 // coalescing and returning pages to the OS.
945 if (left_over >= sizeof(free_t) && left_over > (size >> 6)) {
946 header_t* right = right_header(&head->header);
947 unlink_free(head, bucket);
948 void* free = (char*)head + rounded_up;
949 create_free_area(free, head, left_over);
950 FixLeftPointer(right, (header_t*)free);
951 head->header.size -= left_over;
952 } else {
953 unlink_free(head, bucket);
954 }
955 void* result =
956 create_allocation_header(head, 0, head->header.size, head->header.left);
957 #ifdef CMPCT_DEBUG
958 check_free_fill(result, size);
959 memset(result, ALLOC_FILL, size);
960 memset(((char*)result) + size, PADDING_FILL,
961 rounded_up - size - sizeof(header_t));
962 #endif
963 unlock();
964 return result;
965 }
966
cmpct_memalign(size_t size,size_t alignment)967 void* cmpct_memalign(size_t size, size_t alignment) {
968 if (alignment < 8) {
969 return cmpct_alloc(size);
970 }
971
972 size_t padded_size =
973 size + alignment + sizeof(free_t) + sizeof(header_t);
974
975 char* unaligned = (char*)cmpct_alloc(padded_size);
976 if (unaligned == NULL) {
977 return NULL;
978 }
979
980 lock();
981 size_t mask = alignment - 1;
982 uintptr_t payload_int = (uintptr_t)unaligned + sizeof(free_t) +
983 sizeof(header_t) + mask;
984 char* payload = (char*)(payload_int & ~mask);
985 if (unaligned != payload) {
986 header_t* unaligned_header = (header_t*)unaligned - 1;
987 header_t* header = (header_t*)payload - 1;
988 size_t left_over = payload - unaligned;
989 create_allocation_header(
990 header, 0, unaligned_header->size - left_over, unaligned_header);
991 header_t* right = right_header(unaligned_header);
992 unaligned_header->size = left_over;
993 FixLeftPointer(right, header);
994 unlock();
995 cmpct_free(unaligned);
996 } else {
997 unlock();
998 }
999 // TODO: Free the part after the aligned allocation.
1000 return payload;
1001 }
1002
cmpct_free(void * payload)1003 void cmpct_free(void* payload) {
1004 if (payload == NULL) {
1005 return;
1006 }
1007 header_t* header = (header_t*)payload - 1;
1008 DEBUG_ASSERT(!is_tagged_as_free(header)); // Double free!
1009 size_t size = header->size;
1010 lock();
1011 header_t* left = header->left;
1012 if (left != NULL && is_tagged_as_free(left)) {
1013 // Coalesce with left free object.
1014 unlink_free_unknown_bucket((free_t*)left);
1015 header_t* right = right_header(header);
1016 if (is_tagged_as_free(right)) {
1017 // Coalesce both sides.
1018 unlink_free_unknown_bucket((free_t*)right);
1019 header_t* right_right = right_header(right);
1020 FixLeftPointer(right_right, left);
1021 free_memory(left, left->left, left->size + size + right->size);
1022 } else {
1023 // Coalesce only left.
1024 FixLeftPointer(right, left);
1025 free_memory(left, left->left, left->size + size);
1026 }
1027 } else {
1028 header_t* right = right_header(header);
1029 if (is_tagged_as_free(right)) {
1030 // Coalesce only right.
1031 header_t* right_right = right_header(right);
1032 unlink_free_unknown_bucket((free_t*)right);
1033 FixLeftPointer(right_right, header);
1034 free_memory(header, left, size + right->size);
1035 } else {
1036 free_memory(header, left, size);
1037 }
1038 }
1039 unlock();
1040 }
1041
cmpct_realloc(void * payload,size_t size)1042 void* cmpct_realloc(void* payload, size_t size) {
1043 if (payload == NULL) {
1044 return cmpct_alloc(size);
1045 }
1046 header_t* header = (header_t*)payload - 1;
1047 size_t old_size = header->size - sizeof(header_t);
1048
1049 void* new_payload = cmpct_alloc(size);
1050 if (new_payload == NULL) {
1051 return NULL;
1052 }
1053
1054 memcpy(new_payload, payload, MIN(size, old_size));
1055 cmpct_free(payload);
1056 return new_payload;
1057 }
1058
add_to_heap(void * new_area,size_t size)1059 static void add_to_heap(void* new_area, size_t size) {
1060 char* top = (char*)new_area + size;
1061 // Set up the left sentinel. Its |left| field will not have FREE_BIT set,
1062 // stopping attempts to coalesce left.
1063 header_t* left_sentinel = (header_t*)new_area;
1064 create_allocation_header(left_sentinel, 0, sizeof(header_t), NULL);
1065
1066 // Set up the usable memory area, which will be marked free.
1067 header_t* new_header = left_sentinel + 1;
1068 size_t free_size = size - 2 * sizeof(header_t);
1069 create_free_area(new_header, left_sentinel, free_size);
1070
1071 // Set up the right sentinel. Its |left| field will not have FREE_BIT bit
1072 // set, stopping attempts to coalesce right.
1073 header_t* right_sentinel = (header_t*)(top - sizeof(header_t));
1074 create_allocation_header(right_sentinel, 0, 0, new_header);
1075 }
1076
1077 // Create a new free-list entry of at least size bytes (including the
1078 // allocation header). Called with the lock, apart from during init.
heap_grow(size_t size)1079 static ssize_t heap_grow(size_t size) {
1080 // The new free list entry will have a header on each side (the
1081 // sentinels) so we need to grow the gross heap size by this much more.
1082 size += 2 * sizeof(header_t);
1083 size = ROUNDUP(size, PAGE_SIZE);
1084
1085 void* ptr = NULL;
1086
1087 header_t* os_alloc = (header_t*)theheap.cached_os_alloc;
1088 if (os_alloc != NULL) {
1089 if (os_alloc->size >= size) {
1090 LTRACEF("Using saved 0x%zx-byte OS alloc @%p (>=0x%zx bytes)\n",
1091 os_alloc->size, os_alloc, size);
1092 ptr = os_alloc;
1093 size = os_alloc->size;
1094 DEBUG_ASSERT_MSG(IS_PAGE_ALIGNED(ptr),
1095 "0x%zx bytes @%p", size, ptr);
1096 DEBUG_ASSERT_MSG(IS_PAGE_ALIGNED(size),
1097 "0x%zx bytes @%p", size, ptr);
1098 } else {
1099 // We need to allocate more from the OS. Return the cached OS
1100 // allocation, in case we're holding an unusually-small block
1101 // that's unlikely to satisfy future calls to heap_grow().
1102 LTRACEF("Returning too-small saved 0x%zx-byte OS alloc @%p "
1103 "(<0x%zx bytes)\n",
1104 os_alloc->size, os_alloc, size);
1105 free_to_os(os_alloc, os_alloc->size);
1106 }
1107 theheap.cached_os_alloc = NULL;
1108 }
1109 if (ptr == NULL) {
1110 ptr = heap_page_alloc(size >> PAGE_SIZE_SHIFT);
1111 if (ptr == NULL) {
1112 return ZX_ERR_NO_MEMORY;
1113 }
1114 LTRACEF("Growing heap by 0x%zx bytes, new ptr %p\n", size, ptr);
1115 theheap.size += size;
1116 }
1117
1118 add_to_heap(ptr, size);
1119
1120 return size;
1121 }
1122
cmpct_init(void)1123 void cmpct_init(void) {
1124 LTRACE_ENTRY;
1125
1126 // Create a mutex.
1127 mutex_init(&theheap.lock);
1128
1129 // Initialize the free list.
1130 for (int i = 0; i < NUMBER_OF_BUCKETS; i++) {
1131 theheap.free_lists[i] = NULL;
1132 }
1133 for (int i = 0; i < BUCKET_WORDS; i++) {
1134 theheap.free_list_bits[i] = 0;
1135 }
1136
1137 size_t initial_alloc = HEAP_GROW_SIZE - 2 * sizeof(header_t);
1138
1139 theheap.remaining = 0;
1140
1141 heap_grow(initial_alloc);
1142 }
1143