| 4883 | } |
| 4884 | |
| 4885 | static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { |
| 4886 | void* mem = 0; |
| 4887 | if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ |
| 4888 | alignment = MIN_CHUNK_SIZE; |
| 4889 | if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ |
| 4890 | size_t a = MALLOC_ALIGNMENT << 1; |
| 4891 | while (a < alignment) a <<= 1; |
| 4892 | alignment = a; |
| 4893 | } |
| 4894 | if (bytes >= MAX_REQUEST - alignment) { |
| 4895 | if (m != 0) { /* Test isn't needed but avoids compiler warning */ |
| 4896 | MALLOC_FAILURE_ACTION; |
| 4897 | } |
| 4898 | } |
| 4899 | else { |
| 4900 | size_t nb = request2size(bytes); |
| 4901 | size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; |
| 4902 | mem = internal_malloc(m, req); |
| 4903 | if (mem != 0) { |
| 4904 | mchunkptr p = mem2chunk(mem); |
| 4905 | if (PREACTION(m)) |
| 4906 | return 0; |
| 4907 | if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ |
| 4908 | /* |
| 4909 | Find an aligned spot inside chunk. Since we need to give |
| 4910 | back leading space in a chunk of at least MIN_CHUNK_SIZE, if |
| 4911 | the first calculation places us at a spot with less than |
| 4912 | MIN_CHUNK_SIZE leader, we can move to the next aligned spot. |
| 4913 | We've allocated enough total room so that this is always |
| 4914 | possible. |
| 4915 | */ |
| 4916 | char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - |
| 4917 | SIZE_T_ONE)) & |
| 4918 | -alignment)); |
| 4919 | char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? |
| 4920 | br : br+alignment; |
| 4921 | mchunkptr newp = (mchunkptr)pos; |
| 4922 | size_t leadsize = pos - (char*)(p); |
| 4923 | size_t newsize = chunksize(p) - leadsize; |
| 4924 | |
| 4925 | if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ |
| 4926 | newp->prev_foot = p->prev_foot + leadsize; |
| 4927 | newp->head = newsize; |
| 4928 | } |
| 4929 | else { /* Otherwise, give back leader, use the rest */ |
| 4930 | set_inuse(m, newp, newsize); |
| 4931 | set_inuse(m, p, leadsize); |
| 4932 | dispose_chunk(m, p, leadsize); |
| 4933 | } |
| 4934 | p = newp; |
| 4935 | } |
| 4936 | |
| 4937 | /* Give back spare room at the end */ |
| 4938 | if (!is_mmapped(p)) { |
| 4939 | size_t size = chunksize(p); |
| 4940 | if (size > nb + MIN_CHUNK_SIZE) { |
| 4941 | size_t remainder_size = size - nb; |
| 4942 | mchunkptr remainder = chunk_plus_offset(p, nb); |
no test coverage detected