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.
301 lines
5.2 KiB
301 lines
5.2 KiB
/*++
|
|
|
|
Copyright (c) 1991-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cache.cxx
|
|
|
|
--*/
|
|
#include <pch.cxx>
|
|
#define _NTAPI_ULIB_
|
|
|
|
#include "ulib.hxx"
|
|
#include "cache.hxx"
|
|
|
|
#include "efimisc.hxx"
|
|
#include <efilib.h>
|
|
|
|
DEFINE_CONSTRUCTOR( CACHE, OBJECT );
|
|
|
|
|
|
CACHE::~CACHE(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CACHE.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
|
|
VOID
|
|
CACHE::Construct(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes this class to a default initial state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
_buffer = NULL;
|
|
_block_number = NULL;
|
|
_inuse = NULL;
|
|
_num_blocks = 0;
|
|
_block_size = 0;
|
|
_next_add = 0;
|
|
_next_add_inuse = 0;
|
|
_timeout.QuadPart = 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
CACHE::Destroy(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns this object to its initial state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < _num_blocks; i++) {
|
|
FREE(_buffer[i]);
|
|
}
|
|
DELETE(_buffer);
|
|
DELETE(_block_number);
|
|
FREE(_inuse);
|
|
|
|
_num_blocks = 0;
|
|
_block_size = 0;
|
|
_next_add = 0;
|
|
_next_add_inuse = 0;
|
|
_timeout.QuadPart = 0;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
CACHE::Initialize(
|
|
IN ULONG BlockSize,
|
|
IN ULONG MaximumNumberOfBlocks
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes this object to a valid initial state.
|
|
|
|
Arguments:
|
|
|
|
BlockSize - Supplies the size of the cache blocks.
|
|
MaximumNumberOfBlocks - Supplies the maximum number of cache blocks.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
|
|
Destroy();
|
|
|
|
_num_blocks = MaximumNumberOfBlocks;
|
|
_block_size = BlockSize;
|
|
|
|
if (!(_buffer = NEW PVOID[_num_blocks]) ||
|
|
!(_block_number = NEW BIG_INT[_num_blocks]) ||
|
|
!(_inuse = (LONG *)MALLOC(_num_blocks*sizeof(LONG)))) {
|
|
|
|
Destroy();
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < _num_blocks; i++) {
|
|
|
|
_buffer[i] = NULL;
|
|
_block_number[i] = -1;
|
|
_inuse[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < _num_blocks; i++) {
|
|
|
|
if (!(_buffer[i] = MALLOC((UINT) _block_size))) {
|
|
|
|
Destroy();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
_timeout.QuadPart = -10000;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
CACHE::Read(
|
|
IN BIG_INT BlockNumber,
|
|
OUT PVOID Buffer
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine searches the cache for the requested block and
|
|
copies it to the buffer if it is available. If the block is
|
|
not available then this routine will return FALSE.
|
|
|
|
Arguments:
|
|
|
|
BlockNumber - Supplies the number of the block requested.
|
|
Buffer - Returns the buffer for the block requested.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
LONG final_value;
|
|
|
|
for (i = 0; i < _num_blocks; i++) {
|
|
|
|
while (InterlockedCompareExchange(&_inuse[i], 1, 0) != 0) {
|
|
BS->Stall(_timeout.LowPart); // BUGBUG this has ramifications on IA64 right?
|
|
}
|
|
|
|
if (BlockNumber == _block_number[i]) {
|
|
|
|
memcpy(Buffer, _buffer[i], (UINT) _block_size);
|
|
final_value = InterlockedDecrement(&_inuse[i]);
|
|
DebugAssert(final_value == 0);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
final_value = InterlockedDecrement(&_inuse[i]);
|
|
DebugAssert(final_value == 0);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
VOID
|
|
CACHE::AddBlock(
|
|
IN BIG_INT BlockNumber,
|
|
IN PCVOID Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds a new block to the cache. This will remove the
|
|
oldest existing block out of the cache.
|
|
|
|
Arguments:
|
|
|
|
BlockNumber - Supplies the block number of the new block.
|
|
Buffer - Supplies the buffer for the new block.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
LONG final_value;
|
|
|
|
while (InterlockedCompareExchange(&_next_add_inuse, 1, 0) != 0) {
|
|
BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
|
|
}
|
|
|
|
while (InterlockedCompareExchange(&_inuse[_next_add], 1, 0) != 0) {
|
|
BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
|
|
}
|
|
|
|
memcpy(_buffer[_next_add], Buffer, (UINT) _block_size);
|
|
_block_number[_next_add] = BlockNumber;
|
|
|
|
final_value = InterlockedDecrement(&_inuse[_next_add]);
|
|
DebugAssert(final_value == 0);
|
|
|
|
_next_add = (_next_add + 1) % _num_blocks;
|
|
|
|
final_value = InterlockedDecrement(&_next_add_inuse);
|
|
DebugAssert(final_value == 0);
|
|
}
|
|
|
|
|
|
VOID
|
|
CACHE::Empty(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine eliminates all of the blocks from the cache.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
LONG final_value;
|
|
|
|
for (i = 0; i < _num_blocks; i++) {
|
|
|
|
while (InterlockedCompareExchange(&_inuse[i], 1, 0) != 0) {
|
|
BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
|
|
}
|
|
|
|
_block_number[i] = -1;
|
|
|
|
final_value = InterlockedDecrement(&_inuse[i]);
|
|
DebugAssert(final_value == 0);
|
|
}
|
|
}
|