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
|
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 \
|
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 \
|
heap_tcache.o heap_utils.o intlib.o objhelp.o objhelp_enumconn.o objhelp_enumgeneric.o objhelp_fixedcp.o \
|
||||||
str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
|
rbtree.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
|
||||||
|
|
||||||
all: kernel-lib.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 _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);
|
_H_ASSERT(phd, ndxBin < NBINS);
|
||||||
return ndxBin;
|
return ndxBin;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 _HeapArenaRunRegInd(PHEAPDATA phd, PARENARUN pRun, PARENABININFO pBinInfo, PCVOID pv)
|
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)
|
PVOID _HeapArenaMalloc(PHEAPDATA phd, PARENA pArena, SIZE_T sz, BOOL fZero, BOOL fTryTCache)
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <comrogue/stream.h>
|
#include <comrogue/stream.h>
|
||||||
#include <comrogue/mutex.h>
|
#include <comrogue/mutex.h>
|
||||||
#include <comrogue/heap.h>
|
#include <comrogue/heap.h>
|
||||||
|
#include <comrogue/threadlocal.h>
|
||||||
#include <comrogue/objhelp.h>
|
#include <comrogue/objhelp.h>
|
||||||
#include <comrogue/internals/dlist.h>
|
#include <comrogue/internals/dlist.h>
|
||||||
#include <comrogue/internals/rbtree.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 */
|
/* statistics per cache bin */
|
||||||
typedef struct tagTCACHEBINSTATS
|
typedef struct tagTCACHEBINSTATS
|
||||||
{
|
{
|
||||||
UINT64 nRequests; /* number of requests in this particular bin */
|
UINT64 nRequests; /* number of requests in this particular bin */
|
||||||
} TCACHEBINSTATS, *PTCACHEBINSTATS;
|
} 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 */
|
/* single bin of the cache */
|
||||||
typedef struct tagTCACHEBIN
|
typedef struct tagTCACHEBIN
|
||||||
{
|
{
|
||||||
|
@ -211,6 +233,12 @@ typedef struct tagTCACHE
|
||||||
TCACHEBIN aBins[0]; /* cache bins (dynamically sized) */
|
TCACHEBIN aBins[0]; /* cache bins (dynamically sized) */
|
||||||
} TCACHE, *PTCACHE;
|
} 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
|
* Arena data definitions
|
||||||
*------------------------
|
*------------------------
|
||||||
|
@ -373,6 +401,13 @@ typedef struct tagHEAPDATA {
|
||||||
PEXTENT_NODE pexnBaseNodes; /* pointer to base nodes */
|
PEXTENT_NODE pexnBaseNodes; /* pointer to base nodes */
|
||||||
SIZE_T cpgMapBias; /* number of header pages for arena chunks */
|
SIZE_T cpgMapBias; /* number of header pages for arena chunks */
|
||||||
SIZE_T szArenaMaxClass; /* maximum size class for arenas */
|
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 */
|
ARENABININFO aArenaBinInfo[NBINS]; /* array of arena bin information */
|
||||||
} HEAPDATA, *PHEAPDATA;
|
} HEAPDATA, *PHEAPDATA;
|
||||||
|
|
||||||
|
@ -544,6 +579,50 @@ CDECL_END
|
||||||
|
|
||||||
#define SMALL_SIZE2BIN(s) (abSmallSize2Bin[(s - 1) >> LG_TINY_MIN])
|
#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 /* __ASM__ */
|
||||||
|
|
||||||
#endif /* __COMROGUE_INTERNALS__ */
|
#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)
|
#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
|
* IMalloc implementation
|
||||||
*------------------------
|
*------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user