filled in the heap bitmap functions
This commit is contained in:
parent
dc921706d6
commit
6bf632c25a
|
@ -32,9 +32,9 @@ MAKEFLAGS += -rR
|
|||
CRBASEDIR := $(abspath ../..)
|
||||
include $(CRBASEDIR)/armcompile.mk
|
||||
|
||||
LIB_OBJS = divide.o qdivrem.o heap_toplevel.o heap_arena.o heap_base.o heap_chunks.o heap_rtree.o heap_utils.o \
|
||||
intlib.o objhelp.o objhelp_enumconn.o objhelp_enumgeneric.o objhelp_fixedcp.o rbtree.o str.o \
|
||||
strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
|
||||
LIB_OBJS = divide.o qdivrem.o heap_toplevel.o heap_arena.o heap_base.o heap_bitmap.o heap_chunks.o heap_rtree.o \
|
||||
heap_utils.o intlib.o objhelp.o objhelp_enumconn.o objhelp_enumgeneric.o objhelp_fixedcp.o rbtree.o \
|
||||
str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
|
||||
|
||||
all: kernel-lib.o
|
||||
|
||||
|
|
|
@ -78,11 +78,12 @@ static void bin_info_init(PHEAPDATA phd)
|
|||
PARENABININFO pBinInfo; /* pointer to arena bin information */
|
||||
SIZE_T szPrevRun = SYS_PAGE_SIZE; /* previous run size */
|
||||
|
||||
/* Initialize all the bins. */
|
||||
#define SIZE_CLASS(bin, delta, size) \
|
||||
pBinInfo = &(phd->aArenaBinInfo[bin]); \
|
||||
pBinInfo->cbRegions = size; \
|
||||
szPrevRun = bin_info_cbRunSize_calc(phd, pBinInfo, szPrevRun); \
|
||||
/* TODO bitmap_info_init */
|
||||
_HeapBitmapInfoInit(&(pBinInfo->bitmapinfo), pBinInfo->nRegions);
|
||||
SIZE_CLASSES
|
||||
#undef SIZE_CLASS
|
||||
|
||||
|
@ -102,11 +103,8 @@ HRESULT _HeapArenaSetup(PHEAPDATA phd)
|
|||
}
|
||||
|
||||
_H_ASSERT(phd, phd->cpgMapBias > 0);
|
||||
|
||||
phd->szArenaMaxClass = phd->szChunk - (phd->cpgMapBias << SYS_PAGE_BITS);
|
||||
|
||||
bin_info_init(phd);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
317
kernel/lib/heap_bitmap.c
Normal file
317
kernel/lib/heap_bitmap.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
/*
|
||||
* This code is based on/inspired by jemalloc-3.3.1. Please see LICENSE.jemalloc for further details.
|
||||
*/
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/intlib.h>
|
||||
#include <comrogue/str.h>
|
||||
#include "heap_internals.h"
|
||||
|
||||
/*-----------------------------
|
||||
* Bitmap management functions
|
||||
*-----------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Computes a number of groups from a number of bits.
|
||||
*
|
||||
* Parameters:
|
||||
* - cBits = The number of bits to compute.
|
||||
*
|
||||
* Returns:
|
||||
* The corresponding number of groups.
|
||||
*/
|
||||
static SIZE_T bits_to_groups(SIZE_T cBits)
|
||||
{
|
||||
return (cBits >> LG_BITMAP_GROUP_NBITS) + !!(cBits & BITMAP_GROUP_NBITS_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a bitmap info structure that is intended to contain a certain number of bits.
|
||||
*
|
||||
* Parameters:
|
||||
* - pBInfo = Pointer to info structure to be initialized.
|
||||
* - cBits = Number of bits the bitmap is to contain.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void _HeapBitmapInfoInit(PBITMAPINFO pBInfo, SIZE_T cBits)
|
||||
{
|
||||
register UINT32 i; /* loop counter */
|
||||
register SIZE_T cGroups; /* number of groups */
|
||||
|
||||
/*assert(cBits > 0);*/
|
||||
/*assert(cBits <= (1U << LG_BITMAP_MAXBITS));*/
|
||||
|
||||
/*
|
||||
* Compute the number of groups necessary to store that number of bits, and work upward through the levels
|
||||
* until we reach a level that requires only one group.
|
||||
*/
|
||||
pBInfo->aLevels[0].ofsGroup = 0;
|
||||
cGroups = bits_to_groups(cBits);
|
||||
for (i = 1; cGroups > 1; i++)
|
||||
{
|
||||
/*assert(i < BITMAP_MAX_LEVELS);*/
|
||||
pBInfo->aLevels[i].ofsGroup = pBInfo->aLevels[i - 1].ofsGroup + cGroups;
|
||||
cGroups = bits_to_groups(cGroups);
|
||||
}
|
||||
pBInfo->aLevels[i].ofsGroup = pBInfo->aLevels[i - 1].ofsGroup + cGroups;
|
||||
pBInfo->nLevels = i;
|
||||
pBInfo->cBits = cBits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of bytes required for a bitmap with the specified info.
|
||||
*
|
||||
* Parameters:
|
||||
* - pcBInfo = Pointer to the bitmap info structure.
|
||||
*
|
||||
* Returns:
|
||||
* The number of bytes required for a bitmap.
|
||||
*/
|
||||
SIZE_T _HeapBitmapInfoNumGroups(PCBITMAPINFO pcBInfo)
|
||||
{
|
||||
return pcBInfo->aLevels[pcBInfo->nLevels].ofsGroup << LG_SIZEOF_BITMAP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the size of a bitmap that is to contain a specified number of bits.
|
||||
*
|
||||
* Parameters:
|
||||
* - cBits = The number of bits the bitmap is to contain.
|
||||
*
|
||||
* Returns:
|
||||
* The size of the resulting bitmap.
|
||||
*/
|
||||
SIZE_T _HeapBitmapSize(SIZE_T cBits)
|
||||
{
|
||||
BITMAPINFO binfo;
|
||||
|
||||
_HeapBitmapInfoInit(&binfo, cBits);
|
||||
return _HeapBitmapInfoNumGroups(&binfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes a bitmap to "empty".
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be initialized.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void _HeapBitmapInit(PBITMAP pBitmap, PCBITMAPINFO pcBInfo)
|
||||
{
|
||||
SIZE_T cbExtra; /* number of "extra" bits */
|
||||
register UINT32 i; /* loop counter */
|
||||
|
||||
/*
|
||||
* Note that bitmaps are stored with the bits they contain "inverted," i.e. a 1 bit represents a bit
|
||||
* that has been *cleared*, and a 0 bit represents one that has been *set*, except for trailing unused
|
||||
* bits if any. Bit 0 is always the first logical bit in the group.
|
||||
*/
|
||||
StrSetMem(pBitmap, 0xFFU, pcBInfo->aLevels[pcBInfo->nLevels].ofsGroup << LG_SIZEOF_BITMAP);
|
||||
cbExtra = (BITMAP_GROUP_NBITS - (pcBInfo->cBits & BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;
|
||||
if (cbExtra != 0)
|
||||
pBitmap[pcBInfo->aLevels[1].ofsGroup - 1] >>= cbExtra;
|
||||
for (i = 1; i < pcBInfo->nLevels; i++)
|
||||
{
|
||||
SIZE_T cGroups = pcBInfo->aLevels[i].ofsGroup - pcBInfo->aLevels[i - 1].ofsGroup;
|
||||
cbExtra = (BITMAP_GROUP_NBITS - (cGroups & BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;
|
||||
if (cbExtra != 0)
|
||||
pBitmap[pcBInfo->aLevels[i + 1].ofsGroup - 1] >>= cbExtra;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether or not the specified group is full.
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be tested.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
*
|
||||
* Returns:
|
||||
* - TRUE = If the bitmap is full.
|
||||
* - FALSE = If the bitmap is not full.
|
||||
*/
|
||||
BOOL _HeapBitmapFull(PBITMAP pBitmap, PCBITMAPINFO pcBInfo)
|
||||
{
|
||||
register UINT32 ofsRootGroup = pcBInfo->aLevels[pcBInfo->nLevels].ofsGroup - 1;
|
||||
register BITMAP bmp = pBitmap[ofsRootGroup];
|
||||
return MAKEBOOL(bmp == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a value of a bit in a bitmap.
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be tested.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
* - nBit = The index of the bit to test.
|
||||
*
|
||||
* Returns:
|
||||
* - TRUE = If the bit is set.
|
||||
* - FALSE = If the bit is not set.
|
||||
*/
|
||||
BOOL _HeapBitmapGet(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit)
|
||||
{
|
||||
register SIZE_T ofsGroup; /* offset of group to look in */
|
||||
register BITMAP g; /* current bitmap */
|
||||
|
||||
if (nBit >= pcBInfo->cBits)
|
||||
return FALSE;
|
||||
ofsGroup = nBit >> LG_BITMAP_GROUP_NBITS;
|
||||
g = pBitmap[ofsGroup];
|
||||
return MAKEBOOL(!(g & (1U << (nBit & BITMAP_GROUP_NBITS_MASK))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a bit in a bitmap to "on."
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be altered.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
* - nBit = The index of the bit to set.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void _HeapBitmapSet(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit)
|
||||
{
|
||||
register SIZE_T ofsGroup; /* offset of group to look in */
|
||||
register PBITMAP pg; /* pointer to current bitmap */
|
||||
register BITMAP g; /* current bitmap */
|
||||
|
||||
if ((nBit < pcBInfo->cBits) && !_HeapBitmapGet(pBitmap, pcBInfo, nBit))
|
||||
{
|
||||
ofsGroup = nBit >> LG_BITMAP_GROUP_NBITS;
|
||||
pg = &(pBitmap[ofsGroup]);
|
||||
g = *pg;
|
||||
g ^= 1U << (nBit & BITMAP_GROUP_NBITS_MASK);
|
||||
*pg = g;
|
||||
if (g == 0)
|
||||
{ /* Propagate state changes up the tree. */
|
||||
register UINT32 i;
|
||||
for (i = 1; i < pcBInfo->nLevels; i++)
|
||||
{
|
||||
nBit = ofsGroup;
|
||||
ofsGroup = nBit >> LG_BITMAP_GROUP_NBITS;
|
||||
pg = &(pBitmap[pcBInfo->aLevels[i].ofsGroup + ofsGroup]);
|
||||
g = *pg;
|
||||
g ^= 1U << (nBit & BITMAP_GROUP_NBITS_MASK);
|
||||
*pg = g;
|
||||
if (g != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the first bit in the bitmap that is not yet set and returns its index.
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be altered.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
*
|
||||
* Returns:
|
||||
* The index of the bit in the bitmap that was set as a result of this function.
|
||||
*/
|
||||
SIZE_T _HeapBitmapSetFirstUnset(PBITMAP pBitmap, PCBITMAPINFO pcBInfo)
|
||||
{
|
||||
register SIZE_T nBit = (SIZE_T)(-1); /* bit index; return from this function */
|
||||
register BITMAP g; /* current bitmap */
|
||||
register UINT32 i; /* index pointer */
|
||||
|
||||
if (!_HeapBitmapFull(pBitmap, pcBInfo))
|
||||
{
|
||||
i = pcBInfo->nLevels - 1;
|
||||
g = pBitmap[pcBInfo->aLevels[i].ofsGroup];
|
||||
nBit = IntFirstSet(g) - 1;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
g = pBitmap[pcBInfo->aLevels[i].ofsGroup + nBit];
|
||||
nBit = (nBit << LG_BITMAP_GROUP_NBITS) + (IntFirstSet(g) - 1);
|
||||
}
|
||||
_HeapBitmapSet(pBitmap, pcBInfo, nBit);
|
||||
}
|
||||
return nBit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a bit in a bitmap to "off."
|
||||
*
|
||||
* Parameters:
|
||||
* - pBitmap = Pointer to the bitmap to be altered.
|
||||
* - pcBInfo = Pointer to the corresponding bitmap info structure.
|
||||
* - nBit = The index of the bit to unset.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void _HeapBitmapUnset(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit)
|
||||
{
|
||||
register SIZE_T ofsGroup; /* offset of group to look in */
|
||||
register PBITMAP pg; /* pointer to current bitmap */
|
||||
register BITMAP g; /* current bitmap */
|
||||
BOOL fPropagate; /* propagate changes? */
|
||||
|
||||
if ((nBit < pcBInfo->cBits) && _HeapBitmapGet(pBitmap, pcBInfo, nBit))
|
||||
{
|
||||
ofsGroup = nBit >> LG_BITMAP_GROUP_NBITS;
|
||||
pg = &(pBitmap[ofsGroup]);
|
||||
g = *pg;
|
||||
fPropagate = MAKEBOOL(g == 0);
|
||||
g ^= 1U << (nBit & BITMAP_GROUP_NBITS_MASK);
|
||||
*pg = g;
|
||||
if (fPropagate)
|
||||
{ /* Propagate state changes up the tree. */
|
||||
register UINT32 i;
|
||||
for (i = 1; i < pcBInfo->nLevels; i++)
|
||||
{
|
||||
nBit = ofsGroup;
|
||||
ofsGroup = nBit >> LG_BITMAP_GROUP_NBITS;
|
||||
pg = &(pBitmap[pcBInfo->aLevels[i].ofsGroup + ofsGroup]);
|
||||
g = *pg;
|
||||
fPropagate = MAKEBOOL(g == 0);
|
||||
g ^= 1U << (nBit & BITMAP_GROUP_NBITS_MASK);
|
||||
*pg = g;
|
||||
if (!fPropagate)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -144,6 +144,7 @@ typedef PEXTENT_NODE *PPEXTENT_NODE;
|
|||
#define LG_BITMAP_MAXBITS LG_RUN_MAXREGS
|
||||
|
||||
typedef UINT32 BITMAP; /* bitmap type definition */
|
||||
typedef BITMAP *PBITMAP;
|
||||
#define LG_SIZEOF_BITMAP LOG_UINTSIZE
|
||||
|
||||
/* Number of bits per group */
|
||||
|
@ -168,6 +169,7 @@ typedef struct tagBITMAPINFO
|
|||
UINT32 nLevels; /* number of levels required for bits */
|
||||
BITMAPLEVEL aLevels[BITMAP_MAX_LEVELS + 1]; /* the levels - only first (nLevels + 1) used */
|
||||
} BITMAPINFO, *PBITMAPINFO;
|
||||
typedef const BITMAPINFO *PCBITMAPINFO;
|
||||
|
||||
/*---------------------------------
|
||||
* Thread-level cache declarations
|
||||
|
@ -275,7 +277,7 @@ typedef struct tagARENABININFO
|
|||
UINT32 ofsBitmap; /* offset of bitmap element in run header */
|
||||
BITMAPINFO bitmapinfo; /* manipulates bitmaps associated with this bin's runs */
|
||||
UINT32 ofsCtx0; /* offset of context in run header, or 0 */
|
||||
UINT32 ofsRegion0; /* offse of first region in a run for size class */
|
||||
UINT32 ofsRegion0; /* offset of first region in a run for size class */
|
||||
} ARENABININFO, *PARENABININFO;
|
||||
|
||||
/* The actual arena definition. */
|
||||
|
@ -411,6 +413,25 @@ extern void _HeapBaseShutdown(PHEAPDATA phd);
|
|||
|
||||
CDECL_END
|
||||
|
||||
/*------------------
|
||||
* Bitmap functions
|
||||
*------------------
|
||||
*/
|
||||
|
||||
CDECL_BEGIN
|
||||
|
||||
extern void _HeapBitmapInfoInit(PBITMAPINFO pBInfo, SIZE_T cBits);
|
||||
extern SIZE_T _HeapBitmapInfoNumGroups(PCBITMAPINFO pcBInfo);
|
||||
extern SIZE_T _HeapBitmapSize(SIZE_T cBits);
|
||||
extern void _HeapBitmapInit(PBITMAP pBitmap, PCBITMAPINFO pcBInfo);
|
||||
extern BOOL _HeapBitmapFull(PBITMAP pBitmap, PCBITMAPINFO pcBInfo);
|
||||
extern BOOL _HeapBitmapGet(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit);
|
||||
extern void _HeapBitmapSet(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit);
|
||||
extern SIZE_T _HeapBitmapSetFirstUnset(PBITMAP pBitmap, PCBITMAPINFO pcBInfo);
|
||||
extern void _HeapBitmapUnset(PBITMAP pBitmap, PCBITMAPINFO pcBInfo, SIZE_T nBit);
|
||||
|
||||
CDECL_END
|
||||
|
||||
/*----------------------------
|
||||
* Arena management functions
|
||||
*----------------------------
|
||||
|
|
Loading…
Reference in New Issue
Block a user