gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/memory.cbare sourcepermlink (0.07 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.02
    4:  *
    5:  *    Copyright (C) 2006-2020 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2020/10/21 .
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: /*
   15:  *      memory.c
   16:  *      In-kernel dynamic memory management
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "memory.h"
   21: 
   22: /*
   23:  * FreeQue search
   24:  *      Search the free area whose size is equal to 'blksz',
   25:  *      or larger than
   26:  *      'blksz' but closest.
   27:  *      If it does not exist, return '&imacb->freeque'.
   28:  */
   29: EXPORT QUEUE* knl_searchFreeArea( IMACB *imacb, W blksz )
   30: {
   31:         QUEUE  *q = &imacb->freeque;
   32: 
   33:         /* For area whose memory pool size is less than 1/4,
   34:            search from smaller size.
   35:            Otherwise, search from larger size. */
   36:         if ( blksz > imacb->memsz / 4 ) {
   37:                 /* Search from larger size. */
   38:                 W fsz = 0;
   39:                 while ( (q = q->prev) != &imacb->freeque ) {
   40:                         fsz = FreeSize(q);
   41:                         if ( fsz <= blksz ) {
   42:                                 return ( fsz < blksz )? q->next: q;
   43:                         }
   44:                 }
   45:                 return ( fsz >= blksz )? q->next: q;
   46:         } else {
   47:                 /* Search from smaller size. */
   48:                 while ( (q = q->next) != &imacb->freeque ) {
   49:                         if ( FreeSize(q) >= blksz ) {
   50:                                 break;
   51:                         }
   52:                 }
   53:                 return q;
   54:         }
   55: }
   56: 
   57: 
   58: /*
   59:  * Registration of free area on FreeQue
   60:  *      FreeQue is composed of 2 types: Queue that links the
   61:  *      different size of areas by size and queue that links the
   62:  *      same size of areas.
   63:  *
   64:  *      freeque
   65:  *      |
   66:  *      |   +-----------------------+            +-----------------------+
   67:  *      |   | AreaQue                    |     | AreaQue               |
   68:  *      |   +-----------------------+            +-----------------------+
   69:  *      *---> FreeQue Size order    |            | EmptyQue             |
   70:  *      |   | FreeQue Same size   --------->| FreeQue Same size   ----->
   71:  *      |   |                            |            |                      |
   72:  *      |   |                            |            |                      |
   73:  *      |   +-----------------------+            +-----------------------+
   74:  *      |   | AreaQue                    |     | AreaQue               |
   75:  *      v   +-----------------------+            +-----------------------+
   76:  */
   77: EXPORT void knl_appendFreeArea( IMACB *imacb, QUEUE *aq )
   78: {
   79:         QUEUE  *fq;
   80:         W      size = AreaSize(aq);
   81: 
   82:         /* Registration position search */
   83:         /*  Search the free area whose size is equal to 'blksz',
   84:          *  or larger than 'blksz' but closest.
   85:          *  If it does not exist, return '&imacb->freeque'.
   86:          */
   87:         fq = knl_searchFreeArea(imacb, size);
   88: 
   89:         /* Register */
   90:         clrAreaFlag(aq, AREA_USE);
   91:         if ( fq != &imacb->freeque && FreeSize(fq) == size ) {
   92:                 /* FreeQue Same size */
   93:                 (aq + 2)->next = (fq + 1)->next;
   94:                 (fq + 1)->next = aq + 2;
   95:                 (aq + 2)->prev = fq + 1;
   96:                 if( (aq + 2)->next != NULL ) {
   97:                         (aq + 2)->next->prev = aq + 2;
   98:                 }
   99:                 (aq + 1)->next = NULL;
  100:         } else {
  101:                 /* FreeQue Size order */
  102:                 QueInsert(aq + 1, fq);
  103:                 (aq + 2)->next = NULL;
  104:                 (aq + 2)->prev = (QUEUE*)size;
  105:         }
  106: }
  107: 
  108: /*
  109:  * Delete from FreeQue
  110:  */
  111: EXPORT void knl_removeFreeQue( QUEUE *fq )
  112: {
  113:         if ( fq->next == NULL ) {      /* FreeQue Same size */
  114:                 (fq + 1)->prev->next = (fq + 1)->next;
  115:                 if ( (fq + 1)->next != NULL ) {
  116:                         (fq + 1)->next->prev = (fq + 1)->prev;
  117:                 }
  118:         } else {                       /* FreeQue Size order */
  119:                 if ( (fq + 1)->next != NULL ) {               /* having FreeQue Same size */
  120:                         QueInsert((fq + 1)->next - 1, fq);
  121:                         (fq + 1)->next->prev = (fq + 1)->prev;
  122:                 }
  123:                 QueRemove(fq);
  124:         }
  125: }
  126: 
  127: /*
  128:  * Register area
  129:  *      Insert 'ent' just after 'que.'
  130:  */
  131: EXPORT void knl_insertAreaQue( QUEUE *que, QUEUE *ent )
  132: {
  133:         ent->prev = que;
  134:         ent->next = que->next;
  135:         Assign(que->next->prev, ent);
  136:         que->next = ent;
  137: }
  138: 
  139: /*
  140:  * Delete area
  141:  */
  142: EXPORT void knl_removeAreaQue( QUEUE *aq )
  143: {
  144:         Mask(aq->prev)->next = aq->next;
  145:         Assign(aq->next->prev, Mask(aq->prev));
  146: }
  147: 
  148: /* ------------------------------------------------------------------------ */
  149: 
  150: #if USE_IMALLOC
  151: /* ------------------------------------------------------------------------ */
  152: 
  153: Noinit(EXPORT IMACB *knl_imacb);
  154: 
  155: /* ------------------------------------------------------------------------ */
  156: 
  157: /*
  158:  * Memory allocate
  159:  */
  160: EXPORT void* knl_Imalloc( SZ size )
  161: {
  162:         QUEUE  *q, *aq, *aq2;
  163:         UINT   imask;
  164: 
  165:         /* If it is smaller than the minimum fragment size,
  166:            allocate the minimum size to it. */
  167:         if( size <= 0 ) {
  168:                 return (void *)NULL;
  169:         } else         if ( size < MIN_FRAGMENT ) {
  170:                 size = MIN_FRAGMENT;
  171:         } else {
  172:                 size = ROUND(size);
  173:         }
  174: 
  175:         DI(imask);  /* Exclusive control by interrupt disable */
  176: 
  177:         /* Search FreeQue */
  178:         q = knl_searchFreeArea(knl_imacb, size);
  179:         if ( q == &(knl_imacb->freeque) ) {
  180:                 q = NULL; /* Insufficient memory */
  181:                 goto err_ret;
  182:         }
  183: 
  184:         /* There is free area: Split from FreeQue once */
  185:         knl_removeFreeQue(q);
  186: 
  187:         aq = q - 1;
  188: 
  189:         /* If there are fragments smaller than the minimum fragment size,
  190:            allocate them also */
  191:         if ( FreeSize(q) - size >= MIN_FRAGMENT + sizeof(QUEUE) ) {
  192: 
  193:                 /* Divide area into 2 */
  194:                 aq2 = (QUEUE*)((VB*)(aq + 1) + size);
  195:                 knl_insertAreaQue(aq, aq2);
  196: 
  197:                 /* Register remaining area to FreeQue */
  198:                 knl_appendFreeArea(knl_imacb, aq2);
  199:         }
  200:         setAreaFlag(aq, AREA_USE);
  201: 
  202: err_ret:
  203:         EI(imask);
  204: 
  205:         return (void *)q;
  206: }
  207: 
  208: /*
  209:  * Memory allocate  and clear
  210:  */
  211: EXPORT void* knl_Icalloc( SZ nmemb, SZ size )
  212: {
  213:         SZ     sz = nmemb * size;
  214:         void   *mem;
  215: 
  216:         mem = knl_Imalloc(sz);
  217:         if ( mem == NULL ) {
  218:                 return NULL;
  219:         }
  220: 
  221:         knl_memset(mem, 0, sz);
  222: 
  223:         return mem;
  224: }
  225: 
  226: 
  227: /*
  228:  * Memory allocation size change
  229:  */
  230: EXPORT void* knl_Irealloc( void *ptr, SZ size )
  231: {
  232:         void   *newptr;
  233:         QUEUE  *aq;
  234:         SZ     oldsz;
  235: 
  236:         if(size != 0) {
  237:                 newptr = knl_Imalloc(size);
  238:                 if(newptr == NULL) {
  239:                         return NULL;
  240:                 }
  241:         } else {
  242:                 newptr = NULL;
  243:         }
  244: 
  245:         if(ptr != NULL) {
  246:                 if(newptr != NULL) {
  247:                         aq = (QUEUE*)ptr - 1;
  248:                         oldsz = (SZ)AreaSize(aq);
  249:                         knl_memcpy(newptr, ptr, (size > oldsz)?oldsz:size);
  250:                 }
  251:                 knl_Ifree(ptr);
  252:         }
  253: 
  254:         return newptr;
  255: }
  256: 
  257: 
  258: /*
  259:  * Free memory
  260:  */
  261: EXPORT void  knl_Ifree( void *ptr )
  262: {
  263:         QUEUE  *aq;
  264:         UINT   imask;
  265: 
  266:         DI(imask);  /* Exclusive control by interrupt disable */
  267: 
  268:         aq = (QUEUE*)ptr - 1;
  269:         clrAreaFlag(aq, AREA_USE);
  270: 
  271:         if ( !chkAreaFlag(aq->next, AREA_USE) ) {
  272:                 /* Merge with free area in after location */
  273:                 knl_removeFreeQue(aq->next + 1);
  274:                 knl_removeAreaQue(aq->next);
  275:         }
  276: 
  277:         if ( !chkAreaFlag(aq->prev, AREA_USE) ) {
  278:                 /* Merge with free area in front location */
  279:                 aq = aq->prev;
  280:                 knl_removeFreeQue(aq + 1);
  281:                 knl_removeAreaQue(aq->next);
  282:         }
  283: 
  284:         knl_appendFreeArea(knl_imacb, aq);
  285: 
  286:         EI(imask);
  287: }
  288: 
  289: 
  290: /* ------------------------------------------------------------------------ */
  291: 
  292: /*
  293:  * IMACB Initialization 
  294:  */
  295: LOCAL void initIMACB( void )
  296: {
  297:         QueInit(&(knl_imacb->areaque));
  298:         QueInit(&(knl_imacb->freeque));
  299: }
  300: 
  301: /*
  302:  * Imalloc initial setting 
  303:  */
  304: EXPORT ER knl_init_Imalloc( void )
  305: {
  306:         QUEUE  *top, *end;
  307: 
  308:         /* Align top with 4 byte unit alignment for IMACB */
  309:         knl_lowmem_top = (void *)(((UW)knl_lowmem_top + 3) & ~0x00000003UL);
  310:         knl_imacb = (IMACB*)knl_lowmem_top;
  311:         knl_lowmem_top = (void *)((UW)knl_lowmem_top + sizeof(IMACB));
  312: 
  313:         /* Align top with 8 byte unit alignment */
  314:         knl_lowmem_top = (void *)(((UW)knl_lowmem_top + 7) & ~0x00000007UL);
  315:         top = (QUEUE*)knl_lowmem_top;
  316:         knl_imacb->memsz = (W)((UW)knl_lowmem_limit - (UW)knl_lowmem_top - sizeof(QUEUE)*2);
  317: 
  318:         knl_lowmem_top = knl_lowmem_limit;  /* Update memory free space */
  319: 
  320:         initIMACB();
  321: 
  322:         /* Register on AreaQue */
  323:         end = (QUEUE*)((VB*)top + knl_imacb->memsz) + 1;
  324:         knl_insertAreaQue(&knl_imacb->areaque, end);
  325:         knl_insertAreaQue(&knl_imacb->areaque, top);
  326:         setAreaFlag(end, AREA_USE);
  327:         setAreaFlag(&knl_imacb->areaque, AREA_USE);
  328: 
  329:         knl_appendFreeArea(knl_imacb, top);
  330: 
  331:         return E_OK;
  332: }
  333: 
  334: #endif /* USE_IMALLOC */