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:
parent
05ba968e82
commit
88b04e81ca
59
idl/comrogue/threadlocal.idl
Normal file
59
idl/comrogue/threadlocal.idl
Normal 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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
335
kernel/lib/heap_tcache.c
Normal 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);
|
||||
}
|
|
@ -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
|
||||
*------------------------
|
||||
|
|
Loading…
Reference in New Issue
Block a user