| 4370 | #if !ONLY_MSPACES |
| 4371 | |
| 4372 | void* dlmalloc(size_t bytes) { |
| 4373 | /* |
| 4374 | Basic algorithm: |
| 4375 | If a small request (< 256 bytes minus per-chunk overhead): |
| 4376 | 1. If one exists, use a remainderless chunk in associated smallbin. |
| 4377 | (Remainderless means that there are too few excess bytes to |
| 4378 | represent as a chunk.) |
| 4379 | 2. If it is big enough, use the dv chunk, which is normally the |
| 4380 | chunk adjacent to the one used for the most recent small request. |
| 4381 | 3. If one exists, split the smallest available chunk in a bin, |
| 4382 | saving remainder in dv. |
| 4383 | 4. If it is big enough, use the top chunk. |
| 4384 | 5. If available, get memory from system and use it |
| 4385 | Otherwise, for a large request: |
| 4386 | 1. Find the smallest available binned chunk that fits, and use it |
| 4387 | if it is better fitting than dv chunk, splitting if necessary. |
| 4388 | 2. If better fitting than any binned chunk, use the dv chunk. |
| 4389 | 3. If it is big enough, use the top chunk. |
| 4390 | 4. If request size >= mmap threshold, try to directly mmap this chunk. |
| 4391 | 5. If available, get memory from system and use it |
| 4392 | |
| 4393 | The ugly goto's here ensure that postaction occurs along all paths. |
| 4394 | */ |
| 4395 | |
| 4396 | if (!PREACTION(gm)) { |
| 4397 | void* mem; |
| 4398 | size_t nb; |
| 4399 | if (bytes <= MAX_SMALL_REQUEST) { |
| 4400 | bindex_t idx; |
| 4401 | binmap_t smallbits; |
| 4402 | nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); |
| 4403 | idx = small_index(nb); |
| 4404 | smallbits = gm->smallmap >> idx; |
| 4405 | |
| 4406 | if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ |
| 4407 | mchunkptr b, p; |
| 4408 | idx += ~smallbits & 1; /* Uses next bin if idx empty */ |
| 4409 | b = smallbin_at(gm, idx); |
| 4410 | p = b->fd; |
| 4411 | assert(chunksize(p) == small_index2size(idx)); |
| 4412 | unlink_first_small_chunk(gm, b, p, idx); |
| 4413 | set_inuse_and_pinuse(gm, p, small_index2size(idx)); |
| 4414 | mem = chunk2mem(p); |
| 4415 | check_malloced_chunk(gm, mem, nb); |
| 4416 | goto postaction; |
| 4417 | } |
| 4418 | |
| 4419 | else if (nb > gm->dvsize) { |
| 4420 | if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ |
| 4421 | mchunkptr b, p, r; |
| 4422 | size_t rsize; |
| 4423 | bindex_t i; |
| 4424 | binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); |
| 4425 | binmap_t leastbit = least_bit(leftbits); |
| 4426 | compute_bit2idx(leastbit, i); |
| 4427 | b = smallbin_at(gm, i); |
| 4428 | p = b->fd; |
| 4429 | assert(chunksize(p) == small_index2size(i)); |
no test coverage detected