123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- /*
- This is a version (aka dlmalloc) of malloc/free/realloc written by
- Doug Lea and released to the public domain. Use, modify, and
- redistribute this code without permission or acknowledgement in any
- way you wish. Send questions, comments, complaints, performance
- data, etc to dl@cs.oswego.edu
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
- Note: There may be an updated version of this malloc obtainable at
- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
- */
- #include <features.h>
- #include <stddef.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include "malloc.h"
- /* ------------------------------ memalign ------------------------------ */
- void* memalign(size_t alignment, size_t bytes)
- {
- size_t nb; /* padded request size */
- char* m; /* memory returned by malloc call */
- mchunkptr p; /* corresponding chunk */
- char* _brk; /* alignment point within p */
- mchunkptr newp; /* chunk to return */
- size_t newsize; /* its size */
- size_t leadsize; /* leading space before alignment point */
- mchunkptr remainder; /* spare room at end to split off */
- unsigned long remainder_size; /* its size */
- size_t size;
- /* If need less alignment than we give anyway, just relay to malloc */
- if (alignment <= MALLOC_ALIGNMENT) return malloc(bytes);
- /* Otherwise, ensure that it is at least a minimum chunk size */
- if (alignment < MINSIZE) alignment = MINSIZE;
- /* Make sure alignment is power of 2 (in case MINSIZE is not). */
- if ((alignment & (alignment - 1)) != 0) {
- size_t a = MALLOC_ALIGNMENT * 2;
- while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
- alignment = a;
- }
- LOCK;
- checked_request2size(bytes, nb);
- /* Strategy: find a spot within that chunk that meets the alignment
- * request, and then possibly free the leading and trailing space. */
- /* Call malloc with worst case padding to hit alignment. */
- m = (char*)(malloc(nb + alignment + MINSIZE));
- if (m == 0) {
- UNLOCK;
- return 0; /* propagate failure */
- }
- p = mem2chunk(m);
- if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
- /*
- Find an aligned spot inside chunk. Since we need to give back
- leading space in a chunk of at least MINSIZE, if the first
- calculation places us at a spot with less than MINSIZE leader,
- we can move to the next aligned spot -- we've allocated enough
- total room so that this is always possible.
- */
- _brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
- -((signed long) alignment)));
- if ((unsigned long)(_brk - (char*)(p)) < MINSIZE)
- _brk += alignment;
- newp = (mchunkptr)_brk;
- leadsize = _brk - (char*)(p);
- newsize = chunksize(p) - leadsize;
- /* For mmapped chunks, just adjust offset */
- if (chunk_is_mmapped(p)) {
- newp->prev_size = p->prev_size + leadsize;
- set_head(newp, newsize|IS_MMAPPED);
- UNLOCK;
- return chunk2mem(newp);
- }
- /* Otherwise, give back leader, use the rest */
- set_head(newp, newsize | PREV_INUSE);
- set_inuse_bit_at_offset(newp, newsize);
- set_head_size(p, leadsize);
- free(chunk2mem(p));
- p = newp;
- assert (newsize >= nb &&
- (((unsigned long)(chunk2mem(p))) % alignment) == 0);
- }
- /* Also give back spare room at the end */
- if (!chunk_is_mmapped(p)) {
- size = chunksize(p);
- if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
- remainder_size = size - nb;
- remainder = chunk_at_offset(p, nb);
- set_head(remainder, remainder_size | PREV_INUSE);
- set_head_size(p, nb);
- free(chunk2mem(remainder));
- }
- }
- check_inuse_chunk(p);
- UNLOCK;
- return chunk2mem(p);
- }
|