diff --git a/idl/comrogue/threadlocal.idl b/idl/comrogue/threadlocal.idl new file mode 100644 index 0000000..aa0cf4b --- /dev/null +++ b/idl/comrogue/threadlocal.idl @@ -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); +} diff --git a/kernel/lib/Makefile b/kernel/lib/Makefile index a00ccf5..65c6826 100644 --- a/kernel/lib/Makefile +++ b/kernel/lib/Makefile @@ -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 diff --git a/kernel/lib/heap_arena.c b/kernel/lib/heap_arena.c index d39f3a7..64e4592 100644 --- a/kernel/lib/heap_arena.c +++ b/kernel/lib/heap_arena.c @@ -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) diff --git a/kernel/lib/heap_internals.h b/kernel/lib/heap_internals.h index d698c56..6464b67 100644 --- a/kernel/lib/heap_internals.h +++ b/kernel/lib/heap_internals.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -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__ */ diff --git a/kernel/lib/heap_tcache.c b/kernel/lib/heap_tcache.c new file mode 100644 index 0000000..f6c0c09 --- /dev/null +++ b/kernel/lib/heap_tcache.c @@ -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 +#include +#include +#include +#include +#include +#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); +} diff --git a/kernel/lib/heap_toplevel.c b/kernel/lib/heap_toplevel.c index 42fdbab..c66212c 100644 --- a/kernel/lib/heap_toplevel.c +++ b/kernel/lib/heap_toplevel.c @@ -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 *------------------------