adding more to arena and thread cache in heap, including defining interfaces for thread-local data (will be dummy objects in kernel)

This commit is contained in:
Eric J. Bowersox 2013-06-19 00:39:29 -06:00
parent 05ba968e82
commit 88b04e81ca
6 changed files with 541 additions and 4 deletions

View File

@ -0,0 +1,59 @@
/*
* 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.
*/
import "comrogue/objectbase.idl";
/*------------------------
* IThreadLocal interface
*------------------------
*/
[object, uuid(514c86e9-314d-444a-8741-8eb263e0e52d), pointer_default(unique)]
interface IThreadLocal : IUnknown
{
[unique] typedef IThreadLocal *PTHREADLOCAL;
cpp_quote("typedef void (*PFNTHREADLOCALCLEANUP)(PVOID, PVOID);")
HRESULT SetCleanupFunc(PFNTHREADLOCALCLEANUP pfnCleanup, PVOID pvParam);
HRESULT Get(PPVOID ppv);
HRESULT Set(PVOID pv);
}
/*-------------------------------
* IThreadLocalFactory interface
*-------------------------------
*/
[object, uuid(74f88e79-ae9b-4e43-8c9b-7c3160182d7a), pointer_default(unique)]
interface IThreadLocalFactory : IUnknown
{
[unique] typedef IThreadLocalFactory *PTHREADLOCALFACTORY;
HRESULT CreateThreadLocal(PVOID pvInitial, IThreadLocal **ppthrl);
}

View File

@ -33,8 +33,8 @@ CRBASEDIR := $(abspath ../..)
include $(CRBASEDIR)/armcompile.mk
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
heap_tcache.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

@ -546,14 +546,61 @@ SIZE_T _HeapArenaPtrSmallBinIndGet(PHEAPDATA phd, PCVOID pv, SIZE_T szMapBits)
*/
SIZE_T _HeapArenaBinIndex(PHEAPDATA phd, PARENA pArena, PARENABIN pBin)
{
SIZE_T ndxBin = pBin - pArena->aBins;
SIZE_T ndxBin = pBin - pArena->aBins; /* return from this function */
_H_ASSERT(phd, ndxBin < NBINS);
return ndxBin;
}
UINT32 _HeapArenaRunRegInd(PHEAPDATA phd, PARENARUN pRun, PARENABININFO pBinInfo, PCVOID pv)
{
return 0; /* TODO */
UINT32 ofsDiff; /* offset between pointer and start of run */
SIZE_T cbInterval; /* interval between regions */
UINT32 nShift; /* shift for bit scaling */
UINT32 nRegionIndex; /* region index - return from this function */
/* Don't free a pointer lower than Region 0. */
_H_ASSERT(phd, (UINT_PTR)pv >= ((UINT_PTR)pRun + (UINT_PTR)(pBinInfo->ofsRegion0)));
ofsDiff = (UINT32)((UINT_PTR)pv - (UINT_PTR)pRun - pBinInfo->ofsRegion0);
/* rescale diff and interval by powers of two */
cbInterval = pBinInfo->cbInterval;
nShift = IntFirstSet(cbInterval) - 1;
ofsDiff >>= nShift;
cbInterval >>= nShift;
if (cbInterval == 1)
{
nRegionIndex = ofsDiff; /* divisor was a power of 2 */
}
else
{ /* compute ofsDiff / cbInterval by using multiply and right-shift with a lookup table */
#define SIZE_INV_SHIFT ((sizeof(UINT32) << 3) - LG_RUN_MAXREGS)
#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1)
static const UINT32 SEG_RODATA acbIntervalInvs[] =
{
SIZE_INV(3),
SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
};
if (cbInterval <= ((sizeof(acbIntervalInvs) / sizeof(UINT32)) + 2))
nRegionIndex = (ofsDiff * acbIntervalInvs[cbInterval - 3]) >> SIZE_INV_SHIFT;
else
nRegionIndex = ofsDiff / cbInterval;
#undef SIZE_INV
#undef SIZE_INV_SHIFT
}
_H_ASSERT(phd, ofsDiff == nRegionIndex * cbInterval);
_H_ASSERT(phd, nRegionIndex < pBinInfo->nRegions);
return nRegionIndex;
}
PVOID _HeapArenaMalloc(PHEAPDATA phd, PARENA pArena, SIZE_T sz, BOOL fZero, BOOL fTryTCache)

View File

@ -48,6 +48,7 @@
#include <comrogue/stream.h>
#include <comrogue/mutex.h>
#include <comrogue/heap.h>
#include <comrogue/threadlocal.h>
#include <comrogue/objhelp.h>
#include <comrogue/internals/dlist.h>
#include <comrogue/internals/rbtree.h>
@ -182,12 +183,33 @@ typedef const BITMAPINFO *PCBITMAPINFO;
*---------------------------------
*/
#define TCACHE_NSLOTS_SMALL_MAX 200 /* max cache slots per small bin */
#define TCACHE_NSLOTS_LARGE 20 /* cache slots for large classes */
#define LG_TCACHE_MAXCLASS_DEFAULT 15 /* log2 of max class */
#define TCACHE_GC_SWEEP 8192 /* number of allocations between full GC sweeps */
/* number of allocations between incremental GC sweeps */
#define TCACHE_GC_INCR ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))
/* enable status */
typedef enum tagTCACHE_ENABLE
{
TCACHE_DISABLED = FALSE,
TCACHE_ENABLED = TRUE,
TCACHE_ENABLE_DEFAULT = 2
} TCACHE_ENABLE;
/* statistics per cache bin */
typedef struct tagTCACHEBINSTATS
{
UINT64 nRequests; /* number of requests in this particular bin */
} TCACHEBINSTATS, *PTCACHEBINSTATS;
/* read-only info stored with each element of bins array */
typedef struct tagTCACHEBININFO
{
UINT32 nCachedMax; /* upper limit on bin.nCached */
} TCACHEBININFO, *PTCACHEBININFO;
/* single bin of the cache */
typedef struct tagTCACHEBIN
{
@ -211,6 +233,12 @@ typedef struct tagTCACHE
TCACHEBIN aBins[0]; /* cache bins (dynamically sized) */
} TCACHE, *PTCACHE;
/* state values encoded as small non-NULL pointers */
#define TCACHE_STATE_DISABLED ((PTCACHE)(UINT_PTR)1)
#define TCACHE_STATE_REINCARNATED ((PTCACHE)(UINT_PTR)2)
#define TCACHE_STATE_PURGATORY ((PTCACHE)(UINT_PTR)3)
#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY
/*------------------------
* Arena data definitions
*------------------------
@ -373,6 +401,13 @@ typedef struct tagHEAPDATA {
PEXTENT_NODE pexnBaseNodes; /* pointer to base nodes */
SIZE_T cpgMapBias; /* number of header pages for arena chunks */
SIZE_T szArenaMaxClass; /* maximum size class for arenas */
SSIZE_T nTCacheMaxClassBits; /* bits in thread cache max class size */
PTCACHEBININFO ptcbi; /* pointer to thread cache bin info */
SIZE_T nHBins; /* number of thread cache bins */
SIZE_T cbTCacheMaxClass; /* max cached size class */
UINT32 nStackElems; /* number of stack elements per tcache */
IThreadLocal *pthrlTCache; /* thread-local tcache value */
IThreadLocal *pthrlTCacheEnable; /* thread-local tcache enable value */
ARENABININFO aArenaBinInfo[NBINS]; /* array of arena bin information */
} HEAPDATA, *PHEAPDATA;
@ -544,6 +579,50 @@ CDECL_END
#define SMALL_SIZE2BIN(s) (abSmallSize2Bin[(s - 1) >> LG_TINY_MIN])
/*------------------------------
* Thread-level cache functions
*------------------------------
*/
CDECL_BEGIN
extern void _HeapTCacheEvent(PHEAPDATA phd, PTCACHE ptcache);
extern void _HeapTCacheFlush(PHEAPDATA phd);
extern BOOL _HeapTCacheIsEnabled(PHEAPDATA phd);
extern PTCACHE _HeapTCacheGet(PHEAPDATA phd, BOOL fCreate);
extern void _HeapTCacheSetEnabled(PHEAPDATA phd, BOOL fEnabled);
extern PVOID _HeapTCacheAllocEasy(PHEAPDATA phd, PTCACHEBIN ptbin);
extern PVOID _HeapTCacheAllocSmall(PHEAPDATA phd, PTCACHE ptcache, SIZE_T sz, BOOL fZero);
extern PVOID _HeapTCacheAllocLarge(PHEAPDATA phd, PTCACHE ptcache, SIZE_T sz, BOOL fZero);
extern void _HeapTCacheDAllocSmall(PHEAPDATA phd, PTCACHE ptcache, PVOID pv, SIZE_T ndxBin);
extern void _HeapTCacheDAllocLarge(PHEAPDATA phd, PTCACHE ptcache, PVOID pv, SIZE_T sz);
extern SIZE_T _HeapTCacheSAlloc(PHEAPDATA phd, PCVOID pv);
extern void _HeapTCacheEventHard(PHEAPDATA phd, PTCACHE ptcache);
extern PVOID _HeapTCacheAllocSmallHard(PHEAPDATA phd, PTCACHE ptcache, PTCACHEBIN ptbin, SIZE_T ndxBin);
extern void _HeapTCacheBinFlushSmall(PHEAPDATA phd, PTCACHEBIN ptbin, SIZE_T ndxBin, UINT32 nRem, PTCACHE ptcache);
extern void _HeapTCacheBinFlushLarge(PHEAPDATA phd, PTCACHEBIN ptbin, SIZE_T ndxBin, UINT32 nRem, PTCACHE ptcache);
extern void _HeapTCacheArenaAssociate(PHEAPDATA phd, PTCACHE ptcache, PARENA pArena);
extern void _HeapTCacheArenaDisassociate(PHEAPDATA phd, PTCACHE ptcache);
extern PTCACHE _HeapTCacheCreate(PHEAPDATA phd, PARENA pArena);
extern void _HeapTCacheDestroy(PHEAPDATA phd, PTCACHE ptcache);
extern void _HeapTCacheStatsMerge(PHEAPDATA phd, PTCACHE ptcache, PARENA pArena);
extern HRESULT _HeapTCacheSetup(PHEAPDATA phd, IThreadLocalFactory *pthrlf);
extern void _HeapTCacheShutdown(PHEAPDATA phd);
CDECL_END
/*------------------------------
* Top-level internal functions
*------------------------------
*/
CDECL_BEGIN
extern PARENA _HeapChooseArenaHard(PHEAPDATA phd);
extern PARENA _HeapChooseArena(PHEAPDATA phd, PARENA parena);
CDECL_END
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */

335
kernel/lib/heap_tcache.c Normal file
View File

@ -0,0 +1,335 @@
/*
* 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/compiler_macros.h>
#include <comrogue/types.h>
#include <comrogue/scode.h>
#include <comrogue/intlib.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/seg.h>
#include "heap_internals.h"
#ifdef _H_THIS_FILE
#undef _H_THIS_FILE
_DECLARE_H_THIS_FILE
#endif
/*------------------------------
* Thread-level cache functions
*------------------------------
*/
/*
* Record a thread cache event, which may cause a garbage collection.
*
* Parameters:
* - phd = Pointer to the HEAPDATA block.
* - ptcache = Pointer to thread cache to record an event for.
*
* Returns:
* Nothing.
*/
void _HeapTCacheEvent(PHEAPDATA phd, PTCACHE ptcache)
{
if (TCACHE_GC_INCR == 0)
return;
ptcache->cEvents++;
_H_ASSERT(phd, ptcache->cEvents <= TCACHE_GC_INCR);
if (ptcache->cEvents == TCACHE_GC_INCR)
_HeapTCacheEventHard(phd, ptcache);
}
/*
* Destroys the current thread's cache if it exists.
*
* Parameters:
* - phd = Pointer to the HEAPDATA block.
*
* Returns:
* Nothing.
*/
void _HeapTCacheFlush(PHEAPDATA phd)
{
PTCACHE ptcache = NULL; /* pointer to thread cache */
IThreadLocal_Get(phd->pthrlTCache, (PPVOID)(&ptcache));
if (ptcache)
IThreadLocal_Set(phd->pthrlTCache, NULL);
if (ptcache > TCACHE_STATE_MAX)
_HeapTCacheDestroy(phd, ptcache);
}
/*
* Returns whether the thread cache is enabled for this thread.
*
* Parameters:
* - phd = Pointer to the HEAPDATA block.
*
* Returns:
* - TRUE = If the thread cache is enabled for this thread.
* - FALSE = If the thread cache is disabled for this thread.
*/
BOOL _HeapTCacheIsEnabled(PHEAPDATA phd)
{
TCACHE_ENABLE te; /* enable state */
IThreadLocal_Get(phd->pthrlTCacheEnable, (PPVOID)(&te));
if (te == TCACHE_ENABLE_DEFAULT)
{
te = (phd->uiFlags & PHDFLAGS_NOTCACHE) ? TCACHE_DISABLED : TCACHE_ENABLED;
IThreadLocal_Set(phd->pthrlTCacheEnable, (PVOID)te);
}
return MAKEBOOL(te);
}
/*
* Retrieve the thread cache for this thread, creating it if necessary and desired.
*
* Parameters:
* - phd = Pointer to the HEAPDATA block.
* - fCreate = TRUE to create the thread cache if it does not exist, FALSE to skip that step.
*
* Returns:
* - NULL = The cache was disabled or not created.
* - Other = Pointer to the thread cache.
*/
PTCACHE _HeapTCacheGet(PHEAPDATA phd, BOOL fCreate)
{
PTCACHE ptcache = NULL; /* pointer to thread cache */
IThreadLocal_Get(phd->pthrlTCache, (PPVOID)(&ptcache));
if ((UINT_PTR)ptcache <= (UINT_PTR)TCACHE_STATE_MAX)
{
if (ptcache == TCACHE_STATE_DISABLED)
return NULL; /* cache disabled */
if (ptcache == NULL)
{
if (!fCreate)
return NULL;
if (!_HeapTCacheIsEnabled(phd))
{ /* disabled, record that fact */
_HeapTCacheSetEnabled(phd, FALSE);
return NULL;
}
return _HeapTCacheCreate(phd, _HeapChooseArena(phd, NULL));
}
if (ptcache == TCACHE_STATE_PURGATORY)
{
IThreadLocal_Set(phd->pthrlTCache, (PVOID)TCACHE_STATE_REINCARNATED);
return NULL;
}
if (ptcache == TCACHE_STATE_REINCARNATED)
return NULL;
/* NOT REACHED */
}
return ptcache;
}
/*
* Set the enable state of the thread cache for this thread.
*
* Parameters:
* - phd = Pointer to the HEAPDATA block.
* - fEnabled = TRUE to enable the cache, FALSE to disable it.
*
* Returns:
* Nothing.
*/
void _HeapTCacheSetEnabled(PHEAPDATA phd, BOOL fEnabled)
{
TCACHE_ENABLE te; /* enable state */
PTCACHE ptcache = NULL; /* pointer to thread cache */
te = fEnabled ? TCACHE_ENABLED : TCACHE_DISABLED;
IThreadLocal_Set(phd->pthrlTCacheEnable, (PVOID)te);
IThreadLocal_Get(phd->pthrlTCache, (PPVOID)(&ptcache));
if (fEnabled)
{
if (ptcache == TCACHE_STATE_DISABLED)
IThreadLocal_Set(phd->pthrlTCache, NULL);
}
else
{
if (ptcache > TCACHE_STATE_MAX)
{
_HeapTCacheDestroy(phd, ptcache);
ptcache = NULL;
}
if (ptcache == NULL)
IThreadLocal_Set(phd->pthrlTCache, (PVOID)TCACHE_STATE_DISABLED);
}
}
PVOID _HeapTCacheAllocEasy(PHEAPDATA phd, PTCACHEBIN ptbin)
{
return NULL; /* TODO */
}
PVOID _HeapTCacheAllocSmall(PHEAPDATA phd, PTCACHE ptcache, SIZE_T sz, BOOL fZero)
{
return NULL; /* TODO */
}
PVOID _HeapTCacheAllocLarge(PHEAPDATA phd, PTCACHE ptcache, SIZE_T sz, BOOL fZero)
{
return NULL; /* TODO */
}
void _HeapTCacheDAllocSmall(PHEAPDATA phd, PTCACHE ptcache, PVOID pv, SIZE_T ndxBin)
{
/* TODO */
}
void _HeapTCacheDAllocLarge(PHEAPDATA phd, PTCACHE ptcache, PVOID pv, SIZE_T sz)
{
/* TODO */
}
SIZE_T _HeapTCacheSAlloc(PHEAPDATA phd, PCVOID pv)
{
return 0; /* TODO */
}
void _HeapTCacheEventHard(PHEAPDATA phd, PTCACHE ptcache)
{
/* TODO */
}
PVOID _HeapTCacheAllocSmallHard(PHEAPDATA phd, PTCACHE ptcache, PTCACHEBIN ptbin, SIZE_T ndxBin)
{
return NULL; /* TODO */
}
void _HeapTCacheBinFlushSmall(PHEAPDATA phd, PTCACHEBIN ptbin, SIZE_T ndxBin, UINT32 nRem, PTCACHE ptcache)
{
/* TODO */
}
void _HeapTCacheBinFlushLarge(PHEAPDATA phd, PTCACHEBIN ptbin, SIZE_T ndxBin, UINT32 nRem, PTCACHE ptcache)
{
/* TODO */
}
void _HeapTCacheArenaAssociate(PHEAPDATA phd, PTCACHE ptcache, PARENA pArena)
{
/* TODO */
}
void _HeapTCacheArenaDisassociate(PHEAPDATA phd, PTCACHE ptcache)
{
/* TODO */
}
PTCACHE _HeapTCacheCreate(PHEAPDATA phd, PARENA pArena)
{
return NULL; /* TODO */
}
void _HeapTCacheDestroy(PHEAPDATA phd, PTCACHE ptcache)
{
/* TODO */
}
void _HeapTCacheStatsMerge(PHEAPDATA phd, PTCACHE ptcache, PARENA pArena)
{
/* TODO */
}
static void tcacheCleanup(PVOID pvContents, PVOID pvArg)
{
/*
PHEAPDATA phd = (PHEAPDATA)pvArg;
PTCACHE ptcache = (PTCACHE)pvContents;
*/
/* TODO */
}
HRESULT _HeapTCacheSetup(PHEAPDATA phd, IThreadLocalFactory *pthrlf)
{
register UINT32 i; /* loop counter */
HRESULT hr;
/* figure out the size of the largest max class */
if (phd->nTCacheMaxClassBits < 0 || (1U << phd->nTCacheMaxClassBits) < SMALL_MAXCLASS)
phd->cbTCacheMaxClass = SMALL_MAXCLASS;
else if ((1U << phd->nTCacheMaxClassBits) > phd->szArenaMaxClass)
phd->cbTCacheMaxClass = phd->szArenaMaxClass;
else
phd->cbTCacheMaxClass = (1U << phd->nTCacheMaxClassBits);
/* figure out bins count */
phd->nHBins = NBINS + (phd->cbTCacheMaxClass >> SYS_PAGE_BITS);
/* initialize the info block */
phd->ptcbi = (PTCACHEBININFO)_HeapBaseAlloc(phd, phd->nHBins * sizeof(TCACHEBININFO));
if (!(phd->ptcbi))
return E_OUTOFMEMORY;
phd->nStackElems = 0;
for (i = 0; i < NBINS; i++)
{
if ((phd->aArenaBinInfo[i].nRegions << 1) <= TCACHE_NSLOTS_SMALL_MAX)
phd->ptcbi[i].nCachedMax = (phd->aArenaBinInfo[i].nRegions << 1);
else
phd->ptcbi[i].nCachedMax = TCACHE_NSLOTS_SMALL_MAX;
phd->nStackElems += phd->ptcbi[i].nCachedMax;
}
for (; i < phd->nHBins; i++)
{
phd->ptcbi[i].nCachedMax = TCACHE_NSLOTS_LARGE;
phd->nStackElems += phd->ptcbi[i].nCachedMax;
}
/* Create the thread-local values */
hr = IThreadLocalFactory_CreateThreadLocal(pthrlf, NULL, &(phd->pthrlTCache));
if (FAILED(hr))
goto error0;
IThreadLocal_SetCleanupFunc(phd->pthrlTCache, tcacheCleanup, phd);
hr = IThreadLocalFactory_CreateThreadLocal(pthrlf, (PVOID)TCACHE_ENABLE_DEFAULT, &(phd->pthrlTCacheEnable));
if (FAILED(hr))
goto error1;
return S_OK;
error1:
IUnknown_Release(phd->pthrlTCache);
error0:
return hr;
}
void _HeapTCacheShutdown(PHEAPDATA phd)
{
IUnknown_Release(phd->pthrlTCacheEnable);
IUnknown_Release(phd->pthrlTCache);
}

View File

@ -50,6 +50,23 @@
#define PHDFLAGS_INIT (PHDFLAGS_REDZONE|PHDFLAGS_JUNKFILL|PHDFLAGS_ZEROFILL|PHDFLAGS_NOTCACHE|PHDFLAGS_PROFILE)
/*------------------------------
* Top-level internal functions
*------------------------------
*/
PARENA _HeapChooseArenaHard(PHEAPDATA phd)
{
return NULL; /* TODO */
}
PARENA _HeapChooseArena(PHEAPDATA phd, PARENA parena)
{
if (parena)
return parena;
return NULL; /* TODO */
}
/*------------------------
* IMalloc implementation
*------------------------