⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vec_mallocr.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 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 + -