filled in the heap bitmap functions

This commit is contained in:
Eric J. Bowersox 2013-06-12 21:33:24 -06:00
parent dc921706d6
commit 6bf632c25a
4 changed files with 344 additions and 8 deletions

View File

@ -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

View File

@ -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
View 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;
}
}
}
}

View File

@ -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
*----------------------------