| 4537 | #if !ONLY_MSPACES |
| 4538 | |
| 4539 | void* dlmalloc(size_t bytes) { |
| 4540 | /* |
| 4541 | Basic algorithm: |
| 4542 | If a small request (< 256 bytes minus per-chunk overhead): |
| 4543 | 1. If one exists, use a remainderless chunk in associated smallbin. |
| 4544 | (Remainderless means that there are too few excess bytes to |
| 4545 | represent as a chunk.) |
| 4546 | 2. If it is big enough, use the dv chunk, which is normally the |
| 4547 | chunk adjacent to the one used for the most recent small request. |
| 4548 | 3. If one exists, split the smallest available chunk in a bin, |
| 4549 | saving remainder in dv. |
| 4550 | 4. If it is big enough, use the top chunk. |
| 4551 | 5. If available, get memory from system and use it |
| 4552 | Otherwise, for a large request: |
| 4553 | 1. Find the smallest available binned chunk that fits, and use it |
| 4554 | if it is better fitting than dv chunk, splitting if necessary. |
| 4555 | 2. If better fitting than any binned chunk, use the dv chunk. |
| 4556 | 3. If it is big enough, use the top chunk. |
| 4557 | 4. If request size >= mmap threshold, try to directly mmap this chunk. |
| 4558 | 5. If available, get memory from system and use it |
| 4559 | |
| 4560 | The ugly goto's here ensure that postaction occurs along all paths. |
| 4561 | */ |
| 4562 | |
| 4563 | #if USE_LOCKS |
| 4564 | ensure_initialization(); /* initialize in sys_alloc if not using locks */ |
| 4565 | #endif |
| 4566 | |
| 4567 | if (!PREACTION(gm)) { |
| 4568 | void* mem; |
| 4569 | size_t nb; |
| 4570 | if (bytes <= MAX_SMALL_REQUEST) { |
| 4571 | bindex_t idx; |
| 4572 | binmap_t smallbits; |
| 4573 | nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); |
| 4574 | idx = small_index(nb); |
| 4575 | smallbits = gm->smallmap >> idx; |
| 4576 | |
| 4577 | if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ |
| 4578 | mchunkptr b, p; |
| 4579 | idx += ~smallbits & 1; /* Uses next bin if idx empty */ |
| 4580 | b = smallbin_at(gm, idx); |
| 4581 | p = b->fd; |
| 4582 | assert(chunksize(p) == small_index2size(idx)); |
| 4583 | unlink_first_small_chunk(gm, b, p, idx); |
| 4584 | set_inuse_and_pinuse(gm, p, small_index2size(idx)); |
| 4585 | mem = chunk2mem(p); |
| 4586 | check_malloced_chunk(gm, mem, nb); |
| 4587 | goto postaction; |
| 4588 | } |
| 4589 | |
| 4590 | else if (nb > gm->dvsize) { |
| 4591 | if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ |
| 4592 | mchunkptr b, p, r; |
| 4593 | size_t rsize; |
| 4594 | bindex_t i; |
| 4595 | binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); |
| 4596 | binmap_t leastbit = least_bit(leftbits); |
no test coverage detected