From 6bf632c25a18b1c17358cc82e162747f4db0855f Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Wed, 12 Jun 2013 21:33:24 -0600 Subject: [PATCH] filled in the heap bitmap functions --- kernel/lib/Makefile | 6 +- kernel/lib/heap_arena.c | 6 +- kernel/lib/heap_bitmap.c | 317 ++++++++++++++++++++++++++++++++++++ kernel/lib/heap_internals.h | 23 ++- 4 files changed, 344 insertions(+), 8 deletions(-) create mode 100644 kernel/lib/heap_bitmap.c diff --git a/kernel/lib/Makefile b/kernel/lib/Makefile index 867718b..a00ccf5 100644 --- a/kernel/lib/Makefile +++ b/kernel/lib/Makefile @@ -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 diff --git a/kernel/lib/heap_arena.c b/kernel/lib/heap_arena.c index 39b442e..b1b97c0 100644 --- a/kernel/lib/heap_arena.c +++ b/kernel/lib/heap_arena.c @@ -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; } diff --git a/kernel/lib/heap_bitmap.c b/kernel/lib/heap_bitmap.c new file mode 100644 index 0000000..a660748 --- /dev/null +++ b/kernel/lib/heap_bitmap.c @@ -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 +#include +#include +#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; + } + } + } +} diff --git a/kernel/lib/heap_internals.h b/kernel/lib/heap_internals.h index 865c90a..5869966 100644 --- a/kernel/lib/heap_internals.h +++ b/kernel/lib/heap_internals.h @@ -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 *----------------------------