📄 vec_mallocr.c
字号:
/* This code is based on mallocr.c written by Doug Lea which is released to the public domain. Any changes to libc/stdlib/mallocr.c should be reflected here as well. *//* Preliminaries */#ifndef __STD_C#ifdef __STDC__#define __STD_C 1#else#if __cplusplus#define __STD_C 1#else#define __STD_C 0#endif /*__cplusplus*/#endif /*__STDC__*/#endif /*__STD_C*/#ifndef Void_t#if __STD_C#define Void_t void#else#define Void_t char#endif#endif /*Void_t*/#if __STD_C#include <stddef.h> /* for size_t */#else#include <sys/types.h>#endif#ifdef __cplusplusextern "C" {#endif#include <sys/config.h>/* In newlib, all the publically visible routines take a reentrancy pointer. We don't currently do anything much with it, but we do pass it to the lock routine. */#include <reent.h>#include <string.h>#include <malloc.h>#define MALLOC_LOCK __malloc_lock(reent_ptr)#define MALLOC_UNLOCK __malloc_unlock(reent_ptr)#ifdef SMALL_MEMORY#define malloc_getpagesize (128)#else#define malloc_getpagesize (4096)#endif#if __STD_Cextern void __malloc_lock(struct _reent *);extern void __malloc_unlock(struct _reent *);#elseextern void __malloc_lock();extern void __malloc_unlock();#endif#if __STD_C#define RARG struct _reent *reent_ptr,#define RONEARG struct _reent *reent_ptr#else#define RARG reent_ptr#define RONEARG reent_ptr#define RDECL struct _reent *reent_ptr;#endif#define RCALL reent_ptr,#define RONECALL reent_ptr/* Define MALLOC_LOCK and MALLOC_UNLOCK to C expressions to run to lock and unlock the malloc data structures. MALLOC_LOCK may be called recursively. */#ifndef MALLOC_LOCK#define MALLOC_LOCK#endif#ifndef MALLOC_UNLOCK#define MALLOC_UNLOCK#endif/* INTERNAL_SIZE_T is the word-size used for internal bookkeeping of chunk sizes. On a 64-bit machine, you can reduce malloc overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the expense of not being able to handle requests greater than 2^31. This limitation is hardly ever a concern; you are encouraged to set this. However, the default version is the same as size_t.*/#ifndef INTERNAL_SIZE_T#define INTERNAL_SIZE_T size_t#endif/* Following is needed on implementations whereby long > size_t. The problem is caused because the code performs subtractions of size_t values and stores the result in long values. In the case where long > size_t and the first value is actually less than the second value, the resultant value is positive. For example, (long)(x - y) where x = 0 and y is 1 ends up being 0x00000000FFFFFFFF which is 2*31 - 1 instead of 0xFFFFFFFFFFFFFFFF. This is due to the fact that assignment from unsigned to signed won't sign extend.*/#ifdef SIZE_T_SMALLER_THAN_LONG#define long_sub_size_t(x, y) ( (x < y) ? -((long)(y - x)) : (x - y) );#else#define long_sub_size_t(x, y) ( (long)(x - y) )#endif/* REALLOC_ZERO_BYTES_FREES should be set if a call to realloc with zero bytes should be the same as a call to free. Some people think it should. Otherwise, since this malloc returns a unique pointer for malloc(0), so does realloc(p, 0). *//* The following macros are only invoked with (2n+1)-multiples of INTERNAL_SIZE_T units, with a positive integer n. This is exploited for fast inline execution when n is small. */#define MALLOC_ZERO(charp, nbytes) \do { \ INTERNAL_SIZE_T mzsz = (nbytes); \ if(mzsz <= 9*sizeof(mzsz)) { \ INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \ if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; \ if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; \ if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; }}} \ *mz++ = 0; \ *mz++ = 0; \ *mz = 0; \ } else memset((charp), 0, mzsz); \} while(0)#define MALLOC_COPY(dest,src,nbytes) \do { \ INTERNAL_SIZE_T mcsz = (nbytes); \ if(mcsz <= 9*sizeof(mcsz)) { \ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \ if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; \ if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; \ if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; }}} \ *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; \ *mcdst = *mcsrc ; \ } else memcpy(dest, src, mcsz); \} while(0)#define vECCALLOc _vec_calloc_r#define fREe _free_r#define mEMALIGn _memalign_r#define vECREALLOc _vec_realloc_r##if __STD_CVoid_t* vECREALLOc(RARG Void_t*, size_t);Void_t* vECCALLOc(RARG size_t, size_t);#elseVoid_t* vECREALLOc();Void_t* vECCALLOc();#endif#ifdef __cplusplus}; /* end of extern "C" */#endif/* Type declarations*/struct malloc_chunk{ INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ struct malloc_chunk* fd; /* double links -- used only if free. */ struct malloc_chunk* bk;};typedef struct malloc_chunk* mchunkptr;/* sizes, alignments */#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))#define MALLOC_ALIGN 16#define MALLOC_ALIGNMENT 16#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)#define MINSIZE (sizeof(struct malloc_chunk))/* conversion from malloc headers to user pointers, and back */#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))/* pad request bytes into a usable size */#define request2size(req) \ (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \ (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? ((MINSIZE + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)) : \ (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))/* Check if m has acceptable alignment */#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)/* Physical chunk operations *//* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */#define PREV_INUSE 0x1 /* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */#define IS_MMAPPED 0x2/* Bits to mask off when extracting size */#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)/* Ptr to next physical malloc_chunk. */#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))/* Ptr to previous physical malloc_chunk */#define prev_chunk(p)\ ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))/* Treat space at ptr + offset as a chunk */#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))/* Dealing with use bits *//* extract p's inuse bit */#define inuse(p)\((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)/* extract inuse bit of previous chunk */#define prev_inuse(p) ((p)->size & PREV_INUSE)/* check for mmap()'ed chunk */#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)/* set/clear chunk as in use without otherwise disturbing */#define set_inuse(p)\((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE#define clear_inuse(p)\((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)/* check/set/clear inuse bits in known places */#define inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)#define set_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)#define clear_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))/* Dealing with size fields *//* Get size, ignoring use bits */#define chunksize(p) ((p)->size & ~(SIZE_BITS))/* Set size at head, without disturbing its use bit */#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))/* Set size/use ignoring previous bits in header */#define set_head(p, s) ((p)->size = (s))#ifdef DEFINE_VECREALLOC#if __STD_CVoid_t* vECREALLOc(RARG Void_t* oldmem, size_t bytes)#elseVoid_t* vECREALLOc(RARG oldmem, bytes) RDECL Void_t* oldmem; size_t bytes;#endif{ INTERNAL_SIZE_T nb; /* padded request size */ mchunkptr oldp; /* chunk corresponding to oldmem */ INTERNAL_SIZE_T oldsize; /* its size */ mchunkptr newp; /* chunk to return */ INTERNAL_SIZE_T newsize; /* its size */ Void_t* newmem; /* corresponding user mem */ mchunkptr remainder; /* holds split off extra space from newp */ INTERNAL_SIZE_T remainder_size; /* its size */#ifdef REALLOC_ZERO_BYTES_FREES if (bytes == 0) { fREe(RCALL oldmem); return 0; }#endif /* realloc of null is supposed to be same as malloc */ if (oldmem == 0) return mEMALIGn(RCALL 16, bytes); MALLOC_LOCK; newp = oldp = mem2chunk(oldmem); newsize = oldsize = chunksize(oldp); nb = request2size(bytes); if ((long)(oldsize) < (long)(nb)) { /* Must allocate */ newmem = mEMALIGn (RCALL 16, bytes); if (newmem == 0) /* propagate failure */ { MALLOC_UNLOCK; return 0; } /* copy, free, and exit */ MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); fREe(RCALL oldmem); MALLOC_UNLOCK; return newmem; } remainder_size = long_sub_size_t(newsize, nb); if (remainder_size >= (long)MINSIZE) /* split off remainder */ { remainder = chunk_at_offset(newp, nb); set_head_size(newp, nb); set_head(remainder, remainder_size | PREV_INUSE); set_inuse_bit_at_offset(remainder, remainder_size); fREe(RCALL chunk2mem(remainder)); /* let free() deal with it */ } else { set_head_size(newp, newsize); set_inuse_bit_at_offset(newp, newsize); } MALLOC_UNLOCK; return chunk2mem(newp);}#endif /* DEFINE_VECREALLOC */#ifdef DEFINE_VECCALLOC/* calloc calls malloc, then zeroes out the allocated chunk.*/#if __STD_CVoid_t* vECCALLOc(RARG size_t n, size_t elem_size)#elseVoid_t* vECCALLOc(RARG n, elem_size) RDECL size_t n; size_t elem_size;#endif{ INTERNAL_SIZE_T sz = n * elem_size; Void_t* mem; mem = mEMALIGn (RCALL 16, sz); if (mem == 0) { return 0; } MALLOC_ZERO(mem, sz); return mem;}#endif /* DEFINE_VECCALLOC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -