1:     2:     3:     4:     5:     6:     7:     8:     9:    10:    11:    12:    13:    14: 
   15: 
   16:    17:    18:    19:    20:    21:    22:    23: 
   24: 
   25: #include "mem.h"
   26: 
   27:    28:    29:    30: 
   31: EXPORT size_t _mem_minfragment = sizeof(QUEUE) * 2;
   32: 
   33:    34:    35: 
   36: EXPORT BOOL (*_mem_chkalloc)( void *ptr, int mode, MACB *macb );
   37: 
   38: #define chkalloc        (*_mem_chkalloc)
   39: 
   40:    41:    42: 
   43: Inline size_t toPageCount( size_t size, MACB *macb )
   44: {
   45:         return (size + (macb->pagesz-1)) / macb->pagesz;
   46: }
   47: 
   48:    49:    50:    51:    52:    53: 
   54: LOCAL QUEUE* searchFreeArea( size_t size, MACB *macb )
   55: {
   56:         QUEUE  *q = &macb->freeque;
   57: 
   58:            59:    60:    61:    62: 
   63:         if ( size > macb->pagesz / 4 ) {
   64:                 
   65:                 size_t fsz = 0;
   66:                 while ( (q = q->prev) != &macb->freeque ) {
   67:                         fsz = (size_t)FreeSize(q);
   68:                         if ( fsz <= size ) {
   69:                                 return ( fsz < size )? q->next: q;
   70:                         }
   71:                 }
   72:                 return ( fsz >= size )? q->next: q;
   73:         } else {
   74:                 
   75:                 while ( (q = q->next) != &macb->freeque ) {
   76:                         if ( (size_t)FreeSize(q) >= size ) {
   77:                                 break;
   78:                         }
   79:                 }
   80:                 return q;
   81:         }
   82: }
   83: 
   84:    85:    86:    87:    88:    89:    90:    91:    92:    93:    94:    95:    96:    97:    98:    99:   100:   101:   102: 
  103: LOCAL void appendFreeArea( QUEUE *aq, MACB *macb )
  104: {
  105:         QUEUE  *fq;
  106:         size_t size = (size_t)AreaSize(aq);
  107: 
  108:         
  109:           110:   111:   112: 
  113:         fq = searchFreeArea(size, macb);
  114: 
  115:         
  116:         clrAreaFlag(aq, AREA_USE);
  117:         if ( fq != &macb->freeque && (size_t)FreeSize(fq) == size ) {
  118:                 QueInsert(aq + 1, fq + 1);
  119:         } else {
  120:                 QueInsert(aq + 1, fq);
  121:         }
  122:         QueInit(aq + 2);
  123: }
  124: 
  125:   126:   127: 
  128: LOCAL void removeFreeQue( QUEUE *fq )
  129: {
  130:         if ( !isQueEmpty(fq + 1) ) {
  131:                 QUEUE *nq = (fq + 1)->next;
  132: 
  133:                 QueRemove(fq + 1);
  134:                 QueInsert(nq + 1, nq);
  135:                 QueRemove(nq);
  136:                 QueInsert(nq, fq);
  137:         }
  138: 
  139:         QueRemove(fq);
  140: }
  141: 
  142:   143:   144:   145: 
  146: LOCAL void insertAreaQue( QUEUE *que, QUEUE *ent )
  147: {
  148:         ent->prev = que;
  149:         ent->next = que->next;
  150:         Assign(que->next->prev, ent);
  151:         que->next = ent;
  152: }
  153: 
  154:   155:   156: 
  157: LOCAL void removeAreaQue( QUEUE *aq )
  158: {
  159:         Mask(aq->prev)->next = aq->next;
  160:         Assign(aq->next->prev, Mask(aq->prev));
  161: }
  162: 
  163:   164:   165:   166: 
  167: Inline QUEUE* newPage( size_t size, MACB *macb )
  168: {
  169:         QUEUE  *top, *end;
  170:         size_t nblk;
  171: 
  172:         if ( macb->pagesz == 0 ) {
  173:                 return NULL;
  174:         }
  175: 
  176:         
  177:         nblk = toPageCount(size + sizeof(QUEUE)*2, macb);
  178:         top = (QUEUE*)(*macb->getblk)(nblk, macb->mematr);
  179:         if ( top == NULL ) {
  180:                 return NULL;
  181:         }
  182: 
  183:         
  184:         end = (QUEUE*)((VB*)top + nblk * macb->pagesz) - 1;
  185:         insertAreaQue(&macb->areaque, end);
  186:         insertAreaQue(&macb->areaque, top);
  187:         setAreaFlag(top, AREA_TOP);
  188:         setAreaFlag(end, AREA_END);
  189: 
  190:         return top;
  191: }
  192: 
  193:   194:   195: 
  196: Inline void* allocate( QUEUE *aq, size_t size, MACB *macb )
  197: {
  198:         QUEUE  *q;
  199: 
  200:           201: 
  202:         if ( (size_t)AreaSize(aq) - size >= MIN_FRAGMENT + sizeof(QUEUE) ) {
  203: 
  204:                 
  205:                 q = (QUEUE*)((VB*)(aq + 1) + size);
  206:                 insertAreaQue(aq, q);
  207: 
  208:                 
  209:                 appendFreeArea(q, macb);
  210:         }
  211:         setAreaFlag(aq, AREA_USE);
  212: 
  213:         return (void*)(aq + 1);
  214: }
  215: 
  216: 
  217: 
  218:   219:   220: 
  221: EXPORT void* _mem_malloc( size_t size, MACB *_macb )
  222: {
  223:         MACB   *macb = AlignMACB(_macb);
  224:         QUEUE  *q;
  225: 
  226:         if ( macb->testmode > 0 ) {
  227:                 chkalloc(NULL, 0, macb);
  228:         }
  229: 
  230:           231: 
  232:         if ( size > 0 && size < MIN_FRAGMENT ) {
  233:                 size = MIN_FRAGMENT;
  234:         }
  235: 
  236:         size = ROUND(size);
  237:         if ( size <= 0 ) {
  238:                 return NULL;
  239:         }
  240: 
  241:         
  242:         q = searchFreeArea(size, macb);
  243:         if ( q != &macb->freeque ) {
  244:                 
  245:                 removeFreeQue(q);
  246: 
  247:                 q = q - 1;
  248:         } else {
  249:                 
  250:                 q = newPage(size, macb);
  251:                 if ( q == NULL ) {
  252:                         return NULL;  
  253:                 }
  254:         }
  255: 
  256:         
  257:         return allocate(q, size, macb);
  258: }
  259: 
  260:   261:   262: 
  263: EXPORT void* _mem_calloc( size_t nmemb, size_t size, MACB *macb )
  264: {
  265:         size_t sz = nmemb * size;
  266:         void   *p;
  267: 
  268:         
  269:         p = _mem_malloc(sz, macb);
  270:         if ( p == NULL ) {
  271:                 return NULL;
  272:         }
  273: 
  274:         
  275:         return MEMSET(p, 0, sz);
  276: }
  277: 
  278:   279:   280: 
  281: EXPORT void* _mem_realloc( void *ptr, size_t size, MACB *_macb )
  282: {
  283:         MACB   *macb = AlignMACB(_macb);
  284:         QUEUE  *aq;
  285:         size_t oldsz, sz;
  286: 
  287:         if ( macb->testmode > 0 ) {
  288:                 if ( !chkalloc(ptr, 0, macb) ) {
  289:                         return NULL;
  290:                 }
  291:         }
  292: 
  293:           294: 
  295:         if ( size > 0 && size < MIN_FRAGMENT ) {
  296:                 size = MIN_FRAGMENT;
  297:         }
  298: 
  299:         size = ROUND(size);
  300: 
  301:         aq = (QUEUE*)ptr - 1;
  302: 
  303:         if ( ptr != NULL ) {
  304:                 
  305:                 oldsz = (size_t)AreaSize(aq);
  306: 
  307:                 
  308:                 if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
  309:                         removeFreeQue(aq->next + 1);
  310:                         removeAreaQue(aq->next);
  311:                 }
  312: 
  313:                 sz = (size_t)AreaSize(aq);
  314:         } else {
  315:                 sz = oldsz = 0;
  316:         }
  317: 
  318:         if ( size <= sz ) {
  319:                 if ( size > 0 ) {
  320:                         
  321:                         allocate(aq, size, macb);
  322:                 } else {
  323:                         
  324:                         _mem_free(ptr, macb);
  325:                         ptr = NULL;
  326:                 }
  327:         } else {
  328:                 
  329:                 void *newptr = _mem_malloc(size, macb);
  330:                 if ( newptr == NULL ) {
  331:                         
  332:                         if ( ptr != NULL ) {
  333:                                 allocate(aq, oldsz, macb);
  334:                         }
  335:                         return NULL;
  336:                 }
  337: 
  338:                 if ( ptr != NULL ) {
  339:                         
  340:                         MEMCPY(newptr, ptr, oldsz);
  341: 
  342:                         
  343:                         _mem_free(ptr, macb);
  344:                 }
  345:                 ptr = newptr;
  346:         }
  347: 
  348:         return ptr;
  349: }
  350: 
  351:   352:   353: 
  354: EXPORT void  _mem_free( void *ptr, MACB *_macb )
  355: {
  356:         MACB   *macb = AlignMACB(_macb);
  357:         QUEUE  *aq;
  358: 
  359:         if ( ptr == NULL ) {
  360:                 return;
  361:         }
  362: 
  363:         if ( macb->testmode > 0 ) {
  364:                 if ( !chkalloc(ptr, 0, macb) ) {
  365:                         return;
  366:                 }
  367:         }
  368: 
  369:         aq = (QUEUE*)ptr - 1;
  370:         clrAreaFlag(aq, AREA_USE);
  371: 
  372:         if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
  373:                 
  374:                 removeFreeQue(aq->next + 1);
  375:                 removeAreaQue(aq->next);
  376:         }
  377: 
  378:         if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->prev, AREA_USE) ) {
  379:                 
  380:                 aq = aq->prev;
  381:                 removeFreeQue(aq + 1);
  382:                 removeAreaQue(aq->next);
  383:         }
  384: 
  385:         
  386:         if ( chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) {
  387:                 
  388:                 removeAreaQue(aq->next);
  389:                 removeAreaQue(aq);
  390:                 (*macb->relblk)(aq);
  391:         } else {
  392:                 
  393:                 appendFreeArea(aq, macb);
  394:         }
  395: }