📄 sepmetaimpl.inl
字号:
#ifndef CYGONCE_MEMALLOC_SEPMETAIMPL_INL#define CYGONCE_MEMALLOC_SEPMETAIMPL_INL//==========================================================================//// sepmetaimpl.inl//// Variable block memory pool with separate metadata class declarations////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jlarmour// Contributors: hmt// Date: 2001-06-28// Purpose: Define Sepmetaimpl class interface// Description: Inline class for constructing a variable block allocator// with separate metadata.// Usage: #include <cyg/memalloc/sepmetaimpl.hxx>//////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#ifdef CYGPKG_ISOINFRA# include <pkgconf/isoinfra.h>#endif#include <pkgconf/memalloc.h>#include <cyg/memalloc/sepmetaimpl.hxx>#include <cyg/infra/cyg_ass.h> // assertion support#include <cyg/infra/cyg_trac.h> // tracing support// Simple allocator// The memory block lists are doubly linked lists. One for all alloced// blocks, one for all free blocks. There's also a list of unused// metadata from the metadata pool. The head of the// list has the same structure but its memnext/memprev fields are zero.// Always having at least one item on the list simplifies the alloc and// free code.#ifdef CYGINT_ISO_STRING_MEMFUNCS# include <string.h>#endifinline voidCyg_Mempool_Sepmeta_Implementation::copy_data( cyg_uint8 *dst, cyg_uint8 *src, cyg_int32 nbytes ){#ifdef CYGINT_ISO_STRING_MEMFUNCS memmove( dst, src, nbytes );#else if ((src < dst) && (dst < (src + nbytes))) { // Have to copy backwards src += nbytes; dst += nbytes; while (nbytes--) { *--dst = *--src; } } else { while (nbytes--) { *dst++ = *src++; } }#endif}inline cyg_uint8 *Cyg_Mempool_Sepmeta_Implementation::alignup( cyg_uint8 *addr ){ return (cyg_uint8 *)((cyg_int32)(addr + alignment-1) & -alignment);}inline cyg_uint8 *Cyg_Mempool_Sepmeta_Implementation::aligndown( cyg_uint8 *addr ){ return (cyg_uint8 *)((cyg_int32)addr & -alignment);}inline cyg_uint8 *Cyg_Mempool_Sepmeta_Implementation::alignmetaup( cyg_uint8 *addr ){ const size_t memdqalign = __alignof__ (struct memdq); return (cyg_uint8 *)((cyg_int32)(addr + memdqalign-1) & -memdqalign);}inline cyg_uint8 *Cyg_Mempool_Sepmeta_Implementation::alignmetadown( cyg_uint8 *addr ){ const size_t memdqalign = __alignof__ (struct memdq); return (cyg_uint8 *)((cyg_int32)addr & -memdqalign);}// return the alloced dq at mem inline struct Cyg_Mempool_Sepmeta_Implementation::memdq *Cyg_Mempool_Sepmeta_Implementation::find_alloced_dq( cyg_uint8 *mem ){ struct memdq *dq=allocedhead.next; while (dq->mem != mem ) { CYG_ASSERT( dq->next->prev==dq, "Bad link in dq"); CYG_ASSERT( dq->memnext->memprev==dq, "Bad link in mem dq"); if (dq->next == &memend) // address not found! return NULL; dq = dq->next; } return dq;}// returns a free dq of at least size, or NULL if noneinline struct Cyg_Mempool_Sepmeta_Implementation::memdq *Cyg_Mempool_Sepmeta_Implementation::find_free_dq( cyg_int32 size ){ struct memdq *dq = freehead.next; while ( (dq->memnext->mem - dq->mem) < size ) { CYG_ASSERT( dq->next->prev==dq, "Bad link in dq"); CYG_ASSERT( dq->memnext->memprev==dq, "Bad link in mem dq"); if (dq->next == &freehead) { // reached end of list return NULL; } dq = dq->next; // next on free list } return dq;}// returns the free dq following meminline struct Cyg_Mempool_Sepmeta_Implementation::memdq *Cyg_Mempool_Sepmeta_Implementation::find_free_dq_slot( cyg_uint8 *mem ){ struct memdq *dq; for (dq = freehead.next; dq->mem < mem; dq = dq->next) { if ( dq == &freehead ) // wrapped round break; } return dq;}inline voidCyg_Mempool_Sepmeta_Implementation::check_free_memdq( struct memdq *dq ){ if (dq == &freehead) return; CYG_ASSERT(dq->memnext->memprev == dq, "corrupted free dq #1"); CYG_ASSERT(dq->next->prev == dq, "corrupted free dq #2"); CYG_ASSERT(dq->memprev->memnext == dq, "corrupted free dq #3"); CYG_ASSERT(dq->prev->next == dq, "corrupted free dq #4"); CYG_ASSERT(dq->memnext->mem > dq->mem, "free dq mem not sorted #1"); if (dq->memprev != &memend) CYG_ASSERT(dq->memprev->mem < dq->mem, "free dq mem not sorted #2");}inline voidCyg_Mempool_Sepmeta_Implementation::check_alloced_memdq( struct memdq *dq ){ CYG_ASSERT(dq->memnext->memprev == dq, "corrupted alloced dq #1"); CYG_ASSERT(dq->next->prev == dq, "corrupted alloced dq #2"); CYG_ASSERT(dq->memprev->memnext == dq, "corrupted alloced dq #3"); CYG_ASSERT(dq->prev->next == dq, "corrupted alloced dq #4"); if (dq != &memend) CYG_ASSERT(dq->memnext->mem > dq->mem, "alloced dq mem not sorted #1"); if (dq->memprev != &memhead) CYG_ASSERT(dq->memprev->mem < dq->mem, "alloced dq mem not sorted #2");}// -------------------------------------------------------------------------inline voidCyg_Mempool_Sepmeta_Implementation::insert_free_block( struct memdq *dq ){ // scan for correct slot in the sorted free list struct memdq *fdq = find_free_dq_slot( dq->mem ); CYG_ASSERT(fdq != &freehead ? fdq->mem > dq->mem : 1, "Block address is already in freelist"); check_free_memdq(fdq); if (dq->memnext == fdq) { // we can coalesce these two together // adjust fdq's mem address backwards to include dq fdq->mem = dq->mem; // and remove dq fdq->memprev = dq->memprev; fdq->memprev->memnext = fdq; // Don't need to adjust fdq's next/prev links as it stays in the // same place in the free list // dq is now redundant so return to metadata free list dq->next = freemetahead; freemetahead = dq; // reset dq dq = fdq; } else { // insert behind fdq dq->next = fdq; dq->prev = fdq->prev; fdq->prev = dq; dq->prev->next = dq; } check_free_memdq(dq); // maybe also coalesce backwards if (dq->memprev == dq->prev) { // adjust dq's mem address backwards to include dq->prev dq->mem = dq->prev->mem; // return dq->prev to metadata free list dq->prev->next = freemetahead; freemetahead = dq->prev; // and remove dq->prev from mem list dq->memprev = dq->prev->memprev; dq->memprev->memnext = dq; // and free list dq->prev = dq->prev->prev; dq->prev->next = dq; check_free_memdq(dq); }}// -------------------------------------------------------------------------#include <cyg/infra/diag.h>inlineCyg_Mempool_Sepmeta_Implementation::Cyg_Mempool_Sepmeta_Implementation( cyg_uint8 *base, cyg_int32 size, CYG_ADDRWORD consargs){ CYG_REPORT_FUNCTION(); struct constructorargs *args = (struct constructorargs *)consargs; CYG_CHECK_DATA_PTRC( args ); alignment = args->alignment; CYG_ASSERT( alignment > 0, "Bad alignment" ); CYG_ASSERT( 0!=alignment, "alignment is zero" ); CYG_ASSERT( 0==(alignment & alignment-1), "alignment not a power of 2" ); obase=base; osize=size; metabase = args->metabase; metasize = args->metasize; // bottom is set to the lowest available address given the alignment. bottom = alignup( base ); cyg_uint8 *metabottom = alignmetaup( metabase ); // because we split free blocks by allocating memory from the end, not // the beginning, then to preserve alignment, the *top* must also be // aligned top = aligndown( base+size ); cyg_uint8 *metatop = metabottom + sizeof(struct memdq)*(metasize/sizeof(struct memdq)); CYG_ASSERT( top > bottom , "heap too small" ); CYG_ASSERT( top <= (base+size), "top too large" ); CYG_ASSERT( (((cyg_int32)(top)) & alignment-1)==0, "top badly aligned" ); CYG_ASSERT( (((cyg_int32)(bottom)) & alignment-1)==0, "bottom badly aligned" ); CYG_ASSERT( metatop > metabottom , "meta space too small" ); CYG_ASSERT( metatop <= (metabase+metasize), "metatop too large" ); // Initialize list of unused metadata blocks. Only need to do next // pointers - can ignore prev and size struct memdq *fq = freemetahead = (struct memdq *)metabottom; while ((cyg_uint8 *)fq < metatop) { fq->next = fq+1; fq++; } CYG_ASSERT((cyg_uint8 *)fq == metatop, "traversed metadata not aligned"); // set final pointer to NULL; --fq; fq->next = NULL; // initialize the free list. memhead is the initial free block occupying // all of free memory. memhead.next = memhead.prev = &freehead; // The mem list is circular for consistency. memhead.memprev = memhead.memnext = &memend; memhead.mem = bottom; // initialize block that indicates end of memory. This pretends to // be an allocated block memend.next = memend.prev = &allocedhead; memend.memnext = memend.memprev = &memhead; memend.mem = top; // initialize alloced list memdq. memend pretends to be allocated memory // at the end allocedhead.next = allocedhead.prev = &memend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -