/* * FreeQue search * Search the free area whose size is equal to 'blksz', * or larger than * 'blksz' but closest. * If it does not exist, return '&imacb->freeque'. */ EXPORT QUEUE* knl_searchFreeArea( IMACB *imacb, W blksz ) { QUEUE *q = &imacb->freeque; /* For area whose memory pool size is less than 1/4, search from smaller size. Otherwise, search from larger size. */ if ( blksz > imacb->memsz / 4 ) { /* Search from larger size. */ W fsz = 0; while ( (q = q->prev) != &imacb->freeque ) { fsz = FreeSize(q); if ( fsz <= blksz ) { return ( fsz < blksz )? q->next: q; } } return ( fsz >= blksz )? q->next: q; } else { /* Search from smaller size. */ while ( (q = q->next) != &imacb->freeque ) { if ( FreeSize(q) >= blksz ) { break; } } return q; } }
/* * FreeQue search * Search the free area whose size is equal to 'blksz', * or larger than * 'blksz' but closest. * If it does not exist, return '&mplcb->freeque'. */ LOCAL QUEUE* searchFreeArea( MPLCB *mplcb, INT blksz ) { QUEUE *q = &mplcb->freeque; /* For area whose memory pool size is less than 1/4, search from smaller size. Otherwise, search from larger size. */ if ( blksz > mplcb->mplsz / 4 ) { /* Search from larger size. */ INT fsz = 0; while ( (q = q->prev) != &mplcb->freeque ) { fsz = FreeSize(q); if ( fsz <= blksz ) { return ( fsz < blksz )? q->next: q; } } return ( fsz >= blksz )? q->next: q; } else { /* Search from smaller size. */ while ( (q = q->next) != &mplcb->freeque ) { if ( FreeSize(q) >= blksz ) { break; } } return q; } }
/* * Free queue search * Searches for a free space with the same size as 'size' or * the next largest. * If none is found, returns &freeque. */ LIST *searchFreeArea( RAW_U32 size, MACB *macb ) { LIST *q = &macb->freeque; /* * Areas up to 1/4 of page size are searched starting * from the smallest; * others are searched starting from the largest. */ if ( size > macb->pagesz / 4 ) { /* Searches in order of increasing size */ RAW_U32 fsz = 0; while ( (q = q->previous) != &macb->freeque ) { fsz = (RAW_U32)FreeSize(q); if ( fsz <= size ) { return ( fsz < size )? q->next: q; } } return ( fsz >= size )? q->next: q; } else { /* Searches in order of decreasing size */ while ( (q = q->next) != &macb->freeque ) { if ( (RAW_U32)FreeSize(q) >= size ) { break; } } return q; } }
/* * FreeQue search * Search free area whose size is equal to 'blksz', or closest and * larger than 'blksz'. * If it can not be found, return '&imacb->freeque'. */ LOCAL QUEUE* searchFreeArea( size_t blksz, IMACB *imacb ) { QUEUE *q = &imacb->freeque; /* For area that is less than 1/4 of the page size, search from smaller size. Otherwise, search from larger size. */ if ( blksz > (pagesz / 4) ) { /* Search from larger size */ size_t fsz = 0; while ( (q = q->prev) != &imacb->freeque ) { fsz = FreeSize(q); if ( fsz <= blksz ) { return ( fsz < blksz )? q->next: q; } } return ( fsz >= blksz )? q->next: q; } else { /* Search from smaller size */ while ( (q = q->next) != &imacb->freeque ) { if ( FreeSize(q) >= blksz ) { break; } } return q; } }
/* * Registration of free area on FreeQue * FreeQue is composed of 2 types: Queue that links the * different size of areas by size and queue that links the * same size of areas. * * freeque * | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * | +-----------------------+ +-----------------------+ * *---> FreeQue Size order | | EmptyQue | * | | FreeQue Same size --------->| FreeQue Same size -----> * | | | | | * | | | | | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * v +-----------------------+ +-----------------------+ */ EXPORT void knl_appendFreeArea( IMACB *imacb, QUEUE *aq ) { QUEUE *fq; W size = AreaSize(aq); /* Registration position search */ /* Search the free area whose size is equal to 'blksz', * or larger than 'blksz' but closest. * If it does not exist, return '&imacb->freeque'. */ fq = knl_searchFreeArea(imacb, size); /* Register */ clrAreaFlag(aq, AREA_USE); if ( fq != &imacb->freeque && FreeSize(fq) == size ) { /* FreeQue Same size */ (aq + 2)->next = (fq + 1)->next; (fq + 1)->next = aq + 2; (aq + 2)->prev = fq + 1; if( (aq + 2)->next != NULL ) { (aq + 2)->next->prev = aq + 2; } (aq + 1)->next = NULL; } else { /* FreeQue Size order */ QueInsert(aq + 1, fq); (aq + 2)->next = NULL; (aq + 2)->prev = (QUEUE*)size; } }
/* * Refer variable size memory pool state */ SYSCALL ER _td_ref_mpl( ID mplid, TD_RMPL *pk_rmpl ) { MPLCB *mplcb; QUEUE *fq, *q; INT frsz, blksz; ER ercd = E_OK; CHECK_MPLID(mplid); mplcb = get_mplcb(mplid); BEGIN_DISABLE_INTERRUPT; if ( mplcb->mplid == 0 ) { ercd = E_NOEXS; } else { pk_rmpl->exinf = mplcb->exinf; pk_rmpl->wtsk = wait_tskid(&mplcb->wait_queue); frsz = 0; for ( fq = mplcb->freeque.next; fq != &mplcb->freeque; fq = fq->next ) { blksz = FreeSize(fq); frsz += blksz; for ( q = (fq+1)->next; q != (fq+1); q = q->next ) { frsz += blksz; } } pk_rmpl->frsz = frsz; pk_rmpl->maxsz = MaxFreeSize(mplcb); } END_DISABLE_INTERRUPT; return ercd; }
/* * Maximum free area size */ Inline INT MaxFreeSize( MPLCB *mplcb ) { if ( isQueEmpty(&mplcb->freeque) ) { return 0; } return FreeSize(mplcb->freeque.prev); }
/* * Get memory */ EXPORT void* knl_Imalloc( size_t size ) { QUEUE *q, *aq, *aq2; UINT imask; /* If it is smaller than the minimum fragment size, allocate the minimum size to it. */ if ( size < MIN_FRAGMENT ) { size = MIN_FRAGMENT; } else { size = ROUND(size); } DI(imask); /* Exclusive control by interrupt disable */ /* Search FreeQue */ q = knl_searchFreeArea(knl_imacb, size); if ( q == &(knl_imacb->freeque) ) { q = NULL; /* Insufficient memory */ goto err_ret; } /* There is free area: Split from FreeQue once */ knl_removeFreeQue(q); aq = q - 1; /* If there are fragments smaller than the minimum fragment size, allocate them also */ if ( FreeSize(q) - size >= MIN_FRAGMENT + sizeof(QUEUE) ) { /* Divide area into 2 */ aq2 = (QUEUE*)((VB*)(aq + 1) + size); knl_insertAreaQue(aq, aq2); /* Register remaining area to FreeQue */ knl_appendFreeArea(knl_imacb, aq2); } setAreaFlag(aq, AREA_USE); err_ret: EI(imask); return (VP)q; }
/* * Registration in free space free queue * Free queue comprises a two-tier structure: a queue linking * areas of differing size in order of size, and a queue * linking areas that are the same size. * * macb->freeque * | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * | +-----------------------+ +-----------------------+ * +----> FreeQue size order | +--------> FreeQue same size -----> * | | FreeQue same size --------+ | EmptyQue | * | | | | | * | | | | | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * | +-----------------------+ +-----------------------+ */ void appendFreeArea( LIST *aq, MACB *macb ) { LIST *fq; RAW_U32 size = (RAW_U32)AreaSize(aq); /* Search registration position */ /* Searches for a free space with the same size as 'size' or * the next largest. * If none is found, returns &freeque. */ fq = searchFreeArea(size, macb); /* Registration */ clrAreaFlag(aq, AREA_USE); if ( fq != &macb->freeque && (RAW_U32)FreeSize(fq) == size ) { list_insert(fq + 1, aq + 1); } else { list_insert(fq, aq + 1); } list_init(aq + 2); }
/* * Registration of free area on FreeQue * FreeQue is composed of 2 types: Queue that links the * different size of areas by size and queue that links the * same size of areas. * * freeque * | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * | +-----------------------+ +-----------------------+ * *---> FreeQue Size order | *----> FreeQue Same size -----> * | | FreeQue Same size -----* | EmptyQue | * | | | | | * | | | | | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * v +-----------------------+ +-----------------------+ */ LOCAL void appendFreeArea( MPLCB *mplcb, QUEUE *aq ) { QUEUE *fq; INT size = AreaSize(aq); /* Registration position search */ /* Search the free area whose size is equal to 'blksz', * or larger than 'blksz' but closest. * If it does not exist, return '&mplcb->freeque'. */ fq = searchFreeArea(mplcb, size); /* Register */ clrAreaFlag(aq, AREA_USE); if ( fq != &mplcb->freeque && FreeSize(fq) == size ) { QueInsert(aq + 1, fq + 1); } else { QueInsert(aq + 1, fq); } QueInit(aq + 2); }
/* * Registration of free area on FreeQue * FreeQue is composed of 2 types: Queue that links the different * size of areas by size * and queue that links the same size areas. * * imacb->freeque * | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * | +-----------------------+ +-----------------------+ * *---> FreeQue by size | *----> FreeQue same size ----> * | | FreeQue same size ----* | EmptyQue | * | | | | | * | | | | | * | +-----------------------+ +-----------------------+ * | | AreaQue | | AreaQue | * v +-----------------------+ +-----------------------+ */ LOCAL void appendFreeArea( QUEUE *aq, IMACB *imacb ) { QUEUE *fq; size_t size = AreaSize(aq); /* Registration position search */ /* Search free area whose size is equal to 'blksz', * or closest and larger than 'blksz'. * If it can not be found, return '&imacb->freeque'. */ fq = searchFreeArea(size, imacb); /* Registration */ clrAreaFlag(aq, AREA_USE); if ( (fq != &imacb->freeque) && (FreeSize(fq) == size) ) { QueInsert(aq + 1, fq + 1); } else { QueInsert(aq + 1, fq); } QueInit(aq + 2); }
void BufferFormatPrintTarget::WriteChar(char c) { if (FreeSize() > 0) m_buffer[m_pos++] = c; }
inline int BufferFormatPrintTarget::WritableSize(int expected) const { return std::min(FreeSize(), expected); }