windows-nt/Source/XPSP1/NT/base/efiutil/efilib/efisrc/cache.cxx

302 lines
4.9 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}
}