Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1991-1999 Microsoft Corporation
  3. Module Name:
  4. cache.cxx
  5. --*/
  6. #include <pch.cxx>
  7. #define _NTAPI_ULIB_
  8. #include "ulib.hxx"
  9. #include "cache.hxx"
  10. #include "efimisc.hxx"
  11. #include <efilib.h>
  12. DEFINE_CONSTRUCTOR( CACHE, OBJECT );
  13. CACHE::~CACHE(
  14. )
  15. /*++
  16. Routine Description:
  17. Destructor for CACHE.
  18. Arguments:
  19. None.
  20. Return Value:
  21. None.
  22. --*/
  23. {
  24. Destroy();
  25. }
  26. VOID
  27. CACHE::Construct(
  28. )
  29. /*++
  30. Routine Description:
  31. This routine initializes this class to a default initial state.
  32. Arguments:
  33. None.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. _buffer = NULL;
  39. _block_number = NULL;
  40. _inuse = NULL;
  41. _num_blocks = 0;
  42. _block_size = 0;
  43. _next_add = 0;
  44. _next_add_inuse = 0;
  45. _timeout.QuadPart = 0;
  46. }
  47. VOID
  48. CACHE::Destroy(
  49. )
  50. /*++
  51. Routine Description:
  52. This routine returns this object to its initial state.
  53. Arguments:
  54. None.
  55. Return Value:
  56. None.
  57. --*/
  58. {
  59. ULONG i;
  60. for (i = 0; i < _num_blocks; i++) {
  61. FREE(_buffer[i]);
  62. }
  63. DELETE(_buffer);
  64. DELETE(_block_number);
  65. FREE(_inuse);
  66. _num_blocks = 0;
  67. _block_size = 0;
  68. _next_add = 0;
  69. _next_add_inuse = 0;
  70. _timeout.QuadPart = 0;
  71. }
  72. BOOLEAN
  73. CACHE::Initialize(
  74. IN ULONG BlockSize,
  75. IN ULONG MaximumNumberOfBlocks
  76. )
  77. /*++
  78. Routine Description:
  79. This routine initializes this object to a valid initial state.
  80. Arguments:
  81. BlockSize - Supplies the size of the cache blocks.
  82. MaximumNumberOfBlocks - Supplies the maximum number of cache blocks.
  83. Return Value:
  84. FALSE - Failure.
  85. TRUE - Success.
  86. --*/
  87. {
  88. ULONG i;
  89. Destroy();
  90. _num_blocks = MaximumNumberOfBlocks;
  91. _block_size = BlockSize;
  92. if (!(_buffer = NEW PVOID[_num_blocks]) ||
  93. !(_block_number = NEW BIG_INT[_num_blocks]) ||
  94. !(_inuse = (LONG *)MALLOC(_num_blocks*sizeof(LONG)))) {
  95. Destroy();
  96. return FALSE;
  97. }
  98. for (i = 0; i < _num_blocks; i++) {
  99. _buffer[i] = NULL;
  100. _block_number[i] = -1;
  101. _inuse[i] = 0;
  102. }
  103. for (i = 0; i < _num_blocks; i++) {
  104. if (!(_buffer[i] = MALLOC((UINT) _block_size))) {
  105. Destroy();
  106. return FALSE;
  107. }
  108. }
  109. _timeout.QuadPart = -10000;
  110. return TRUE;
  111. }
  112. BOOLEAN
  113. CACHE::Read(
  114. IN BIG_INT BlockNumber,
  115. OUT PVOID Buffer
  116. ) CONST
  117. /*++
  118. Routine Description:
  119. This routine searches the cache for the requested block and
  120. copies it to the buffer if it is available. If the block is
  121. not available then this routine will return FALSE.
  122. Arguments:
  123. BlockNumber - Supplies the number of the block requested.
  124. Buffer - Returns the buffer for the block requested.
  125. Return Value:
  126. FALSE - Failure.
  127. TRUE - Success.
  128. --*/
  129. {
  130. ULONG i;
  131. LONG final_value;
  132. for (i = 0; i < _num_blocks; i++) {
  133. while (InterlockedCompareExchange(&_inuse[i], 1, 0) != 0) {
  134. BS->Stall(_timeout.LowPart); // BUGBUG this has ramifications on IA64 right?
  135. }
  136. if (BlockNumber == _block_number[i]) {
  137. memcpy(Buffer, _buffer[i], (UINT) _block_size);
  138. final_value = InterlockedDecrement(&_inuse[i]);
  139. DebugAssert(final_value == 0);
  140. return TRUE;
  141. }
  142. final_value = InterlockedDecrement(&_inuse[i]);
  143. DebugAssert(final_value == 0);
  144. }
  145. return FALSE;
  146. }
  147. VOID
  148. CACHE::AddBlock(
  149. IN BIG_INT BlockNumber,
  150. IN PCVOID Buffer
  151. )
  152. /*++
  153. Routine Description:
  154. This routine adds a new block to the cache. This will remove the
  155. oldest existing block out of the cache.
  156. Arguments:
  157. BlockNumber - Supplies the block number of the new block.
  158. Buffer - Supplies the buffer for the new block.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. LONG final_value;
  164. while (InterlockedCompareExchange(&_next_add_inuse, 1, 0) != 0) {
  165. BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
  166. }
  167. while (InterlockedCompareExchange(&_inuse[_next_add], 1, 0) != 0) {
  168. BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
  169. }
  170. memcpy(_buffer[_next_add], Buffer, (UINT) _block_size);
  171. _block_number[_next_add] = BlockNumber;
  172. final_value = InterlockedDecrement(&_inuse[_next_add]);
  173. DebugAssert(final_value == 0);
  174. _next_add = (_next_add + 1) % _num_blocks;
  175. final_value = InterlockedDecrement(&_next_add_inuse);
  176. DebugAssert(final_value == 0);
  177. }
  178. VOID
  179. CACHE::Empty(
  180. )
  181. /*++
  182. Routine Description:
  183. This routine eliminates all of the blocks from the cache.
  184. Arguments:
  185. None.
  186. Return Value:
  187. None.
  188. --*/
  189. {
  190. ULONG i;
  191. LONG final_value;
  192. for (i = 0; i < _num_blocks; i++) {
  193. while (InterlockedCompareExchange(&_inuse[i], 1, 0) != 0) {
  194. BS->Stall(_timeout.LowPart); // BUGBUG ramifications for IA64?
  195. }
  196. _block_number[i] = -1;
  197. final_value = InterlockedDecrement(&_inuse[i]);
  198. DebugAssert(final_value == 0);
  199. }
  200. }