You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
8.0 KiB
263 lines
8.0 KiB
#ifndef _CACHE_HPP_
|
|
#define _CACHE_HPP_
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'hpp' files for this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants exported from the class. */
|
|
/* 3. Data structures exported from the class. */
|
|
/* 4. Forward references to other data structures. */
|
|
/* 5. Class specifications (including inline functions). */
|
|
/* 6. Additional large inline functions. */
|
|
/* */
|
|
/* Any portion that is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "Global.hpp"
|
|
|
|
#include "Bucket.hpp"
|
|
#include "Find.hpp"
|
|
#include "NewPage.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The allocation cache. */
|
|
/* */
|
|
/* The memory allocation cache consists of two stacks. The */
|
|
/* first stack contains preallocated elements which are */
|
|
/* available for use. The second stack contains elements */
|
|
/* which have been deallocated and are about to be recycled. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
class CACHE : public BUCKET
|
|
{
|
|
//
|
|
// Private data.
|
|
//
|
|
// A cache sits on top of a bucket and shields
|
|
// it from being swamped by calls. The 'Active'
|
|
// flag is set when the cache is active. The
|
|
// 'Stealing' flag indicates that deallocated
|
|
// memory can be stolen and reallocated. The
|
|
// 'ThreadSafe' flag indicates that locking is
|
|
// required.
|
|
//
|
|
BOOLEAN Active;
|
|
BOOLEAN Stealing;
|
|
BOOLEAN ThreadSafe;
|
|
#ifdef ENABLE_HEAP_STATISTICS
|
|
|
|
//
|
|
// When we are collecting statistics we enable
|
|
// the following variables. The 'CacheFills'
|
|
// count keeps track of the number of times
|
|
// the cache was filled from the bucket. The
|
|
// 'CacheFlushes' count keeps track of the
|
|
// number of times the cache flushed deleted
|
|
// elements to the bucket. The 'HighTide' count
|
|
// keeps track the the highest number of outstanding
|
|
// allocations since the last "DeleteAll()'. The
|
|
// 'HighWater' count keeps track of the maximum
|
|
// number of allocations at any point. The
|
|
// 'InUse' counts the the current number of outstanding
|
|
// allocations.
|
|
//
|
|
SBIT32 CacheFills;
|
|
SBIT32 CacheFlushes;
|
|
SBIT32 HighTide;
|
|
SBIT32 HighWater;
|
|
SBIT32 InUse;
|
|
#endif
|
|
|
|
//
|
|
// A cache can be controlled by the user. The
|
|
// 'CacheSize' controls the number of allocations
|
|
// that can be preallocated or queued for
|
|
// deletion. The 'NumberOfChildren' is a count
|
|
// of the number of caches that allocate space
|
|
// from this cache.
|
|
//
|
|
SBIT16 CacheSize;
|
|
SBIT16 FillSize;
|
|
SBIT16 NumberOfChildren;
|
|
|
|
//
|
|
// The cache consists of two stacks. The
|
|
// 'DeleteStack' contains elements that are
|
|
// waiting to be deleted. The 'NewStack'
|
|
// contains elements waiting to be allocated.
|
|
//
|
|
ADDRESS_AND_PAGE *DeleteStack;
|
|
VOID **NewStack;
|
|
|
|
//
|
|
// The top of the deleted stack is kept in
|
|
// 'TopOfDeleteStack' and the top of the new
|
|
// stack is kept in 'TopOfNewStack'.
|
|
//
|
|
SBIT32 TopOfDeleteStack;
|
|
SBIT32 TopOfNewStack;
|
|
|
|
//
|
|
// The 'Spinlock' is a fast lock employed to
|
|
// make the cache multi-threaded if 'ThreadSafe'
|
|
// is true.
|
|
//
|
|
SPINLOCK Spinlock;
|
|
|
|
public:
|
|
//
|
|
// Public functions.
|
|
//
|
|
// The cacahe is a subset of the full haep interface
|
|
// a certain calls simply bypass it. However, there
|
|
// are a few additional functions for cases where the
|
|
// cache needs to be notified of significant heap
|
|
// events.
|
|
//
|
|
CACHE
|
|
(
|
|
SBIT32 NewAllocationSize,
|
|
SBIT32 NewCacheSize,
|
|
SBIT32 NewChunkSize,
|
|
SBIT32 NewPageSize,
|
|
BOOLEAN NewStealing,
|
|
BOOLEAN NewThreadSafe
|
|
);
|
|
|
|
VOID *CreateDataPage( VOID );
|
|
|
|
BOOLEAN Delete( VOID *Address,PAGE *Page,SBIT32 Version );
|
|
|
|
VOID DeleteAll( VOID );
|
|
|
|
BOOLEAN DeleteDataPage( VOID *Address );
|
|
|
|
BOOLEAN MultipleNew
|
|
(
|
|
SBIT32 *Actual,
|
|
VOID *Array[],
|
|
SBIT32 Requested
|
|
);
|
|
|
|
VOID *New( VOID );
|
|
|
|
VOID *New( BOOLEAN SubDivided,SBIT32 NewSize = NoSize );
|
|
|
|
VOID ReleaseSpace( SBIT32 MaxActivePages );
|
|
|
|
BOOLEAN SearchCache( VOID *Address );
|
|
|
|
BOOLEAN Truncate( VOID );
|
|
|
|
VOID UpdateCache
|
|
(
|
|
FIND *NewFind,
|
|
HEAP *NewHeap,
|
|
NEW_PAGE *NewPages,
|
|
CACHE *NewParentCache
|
|
);
|
|
|
|
~CACHE( VOID );
|
|
|
|
//
|
|
// Public inline functions.
|
|
//
|
|
// A cache just like its parent bucket is closely
|
|
// coupled to various other classes and provides
|
|
// then is vital information.
|
|
//
|
|
INLINE VOID ClaimCacheLock( VOID )
|
|
{
|
|
if ( (ThreadSafe) && (Find -> GetLockCount() == 0) )
|
|
{ Spinlock.ClaimLock(); }
|
|
}
|
|
|
|
INLINE PAGE *FindChildPage( VOID *Address )
|
|
{
|
|
return Find -> FindPage
|
|
(
|
|
((VOID*) (((BIT32) Address) & ~(GetAllocationSize()-1))),
|
|
(CACHE*) this
|
|
);
|
|
}
|
|
|
|
INLINE PAGE *FindParentPage( VOID *Address )
|
|
{
|
|
return Find -> FindPage
|
|
(
|
|
((VOID*) (((BIT32) Address) & ~(GetPageSize()-1))),
|
|
ParentCache
|
|
);
|
|
}
|
|
|
|
INLINE SBIT16 GetCacheSize( VOID )
|
|
{ return CacheSize; }
|
|
|
|
INLINE SBIT32 GetNumberOfChildren( VOID )
|
|
{ return NumberOfChildren; }
|
|
|
|
INLINE VOID ReleaseCacheLock( VOID )
|
|
{
|
|
if ( (ThreadSafe) && (Find -> GetLockCount() == 0) )
|
|
{ Spinlock.ReleaseLock(); }
|
|
}
|
|
|
|
INLINE BOOLEAN Walk( SEARCH_PAGE *Details )
|
|
{ return NewPage -> Walk( Details ); }
|
|
#ifdef ENABLE_HEAP_STATISTICS
|
|
|
|
//
|
|
// Cache statistics.
|
|
//
|
|
// A cache has a collection statistics which it
|
|
// uses to measure how it is doing. It is possible
|
|
// to get access to this data for the purpose of
|
|
// outputing various reports.
|
|
//
|
|
INLINE SBIT32 GetCacheFills( VOID )
|
|
{ return CacheFills; }
|
|
|
|
INLINE SBIT32 GetCacheFlushes( VOID )
|
|
{ return CacheFlushes; }
|
|
|
|
INLINE SBIT32 GetHighWater( VOID )
|
|
{ return HighWater; }
|
|
#endif
|
|
|
|
private:
|
|
//
|
|
// Private functions.
|
|
//
|
|
// A cache is initially inactive. If at least one
|
|
// allocation request is made it will spring into
|
|
// life, allocate any space needed and prepare itself
|
|
// for use.
|
|
//
|
|
VOID CreateCacheStacks( VOID );
|
|
#ifdef ENABLE_HEAP_STATISTICS
|
|
|
|
VOID ComputeHighWater( SBIT32 Size );
|
|
#endif
|
|
|
|
//
|
|
// Disabled operations.
|
|
//
|
|
// All copy constructors and class assignment
|
|
// operations are disabled.
|
|
//
|
|
CACHE( CONST CACHE & Copy );
|
|
|
|
VOID operator=( CONST CACHE & Copy );
|
|
};
|
|
#endif
|