Source code of Windows XP (NT5)
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.

256 lines
4.7 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. buffer.c
  5. Abstract:
  6. This module contains code for buffer-management.
  7. Author:
  8. Abolade Gbadegesin (aboladeg) 2-Mar-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. LIST_ENTRY NhpBufferQueue;
  14. LONG NhpBufferQueueLength;
  15. CRITICAL_SECTION NhpBufferQueueLock;
  16. PNH_BUFFER
  17. NhAcquireFixedLengthBuffer(
  18. VOID
  19. )
  20. /*++
  21. Routine Description:
  22. This routine is invoked to acquire an I/O buffer.
  23. If no buffer is available on the buffer queue, a new one is obtained.
  24. Arguments:
  25. none.
  26. Return Value:
  27. PNH_BUFFER - the buffer allocated
  28. --*/
  29. {
  30. PNH_BUFFER Buffer;
  31. PLIST_ENTRY Link;
  32. EnterCriticalSection(&NhpBufferQueueLock);
  33. if (!IsListEmpty(&NhpBufferQueue)) {
  34. Link = RemoveHeadList(&NhpBufferQueue);
  35. LeaveCriticalSection(&NhpBufferQueueLock);
  36. InterlockedDecrement(&NhpBufferQueueLength);
  37. Buffer = CONTAINING_RECORD(Link, NH_BUFFER, Link);
  38. Buffer->Type = NhFixedLengthBufferType;
  39. return Buffer;
  40. }
  41. LeaveCriticalSection(&NhpBufferQueueLock);
  42. Buffer = NH_ALLOCATE_BUFFER();
  43. if (Buffer) {
  44. Buffer->Type = NhFixedLengthBufferType;
  45. }
  46. return Buffer;
  47. } // NhAcquireFixedLengthBuffer
  48. PNH_BUFFER
  49. NhAcquireVariableLengthBuffer(
  50. ULONG Length
  51. )
  52. /*++
  53. Routine Description:
  54. This routine is invoked to acquire an I/O buffer of non-standard size.
  55. If the length requested is less than or equal to 'NH_BUFFER_SIZE',
  56. a buffer from the shared buffer-queue is returned.
  57. Otherwise, a buffer is especially allocated for the caller.
  58. Arguments:
  59. Length - the length of the buffer required.
  60. Return Value:
  61. PNH_BUFFER - the buffer allocated.
  62. --*/
  63. {
  64. PNH_BUFFER Buffer;
  65. if (Length <= NH_BUFFER_SIZE) {
  66. return NhAcquireFixedLengthBuffer();
  67. }
  68. Buffer = reinterpret_cast<PNH_BUFFER>(
  69. NH_ALLOCATE(FIELD_OFFSET(NH_BUFFER, Buffer[Length]))
  70. );
  71. if (Buffer) { Buffer->Type = NhVariableLengthBufferType; }
  72. return Buffer;
  73. } // NhAcquireVariableLengthBuffer
  74. PNH_BUFFER
  75. NhDuplicateBuffer(
  76. PNH_BUFFER Bufferp
  77. )
  78. /*++
  79. Routine Description:
  80. This routine creates a duplicate of the given buffer,
  81. including both its data and its control information.
  82. N.B. Variable-length buffers cannot be duplicated by this routine.
  83. Arguments:
  84. Bufferp - the buffer to be duplicated
  85. Return Value:
  86. PNH_BUFFER - a pointer to the duplicate
  87. --*/
  88. {
  89. PNH_BUFFER Duplicatep;
  90. ASSERT(Bufferp->Type == NhFixedLengthBufferType);
  91. if (!(Duplicatep = NhAcquireBuffer())) { return NULL; }
  92. *Duplicatep = *Bufferp;
  93. return Duplicatep;
  94. } // NhDuplicateBuffer
  95. ULONG
  96. NhInitializeBufferManagement(
  97. VOID
  98. )
  99. /*++
  100. Routine Description:
  101. This routine readies the buffer-management for operation.
  102. Arguments:
  103. none.
  104. Return Value:
  105. ULONG - Win32 status code.
  106. --*/
  107. {
  108. ULONG Error = NO_ERROR;
  109. InitializeListHead(&NhpBufferQueue);
  110. NhpBufferQueueLength = 0;
  111. __try {
  112. InitializeCriticalSection(&NhpBufferQueueLock);
  113. } __except(EXCEPTION_EXECUTE_HANDLER) {
  114. NhTrace(
  115. TRACE_FLAG_BUFFER,
  116. "NhInitializeBufferManagement: exception %d creating lock",
  117. Error = GetExceptionCode()
  118. );
  119. }
  120. return Error;
  121. } // NhInitializeBufferManagement
  122. VOID
  123. NhReleaseBuffer(
  124. PNH_BUFFER Bufferp
  125. )
  126. /*++
  127. Routine Description:
  128. This routine is called to release a buffer to the buffer queue.
  129. It attempts to place the buffer on the queue for re-use, unless
  130. the queue is full in which case the buffer is immediately freed.
  131. Arguments:
  132. Bufferp - the buffer to be released
  133. Return Value:
  134. none.
  135. --*/
  136. {
  137. if (NhpBufferQueueLength > NH_MAX_BUFFER_QUEUE_LENGTH ||
  138. Bufferp->Type != NhFixedLengthBufferType) {
  139. NH_FREE_BUFFER(Bufferp);
  140. } else {
  141. EnterCriticalSection(&NhpBufferQueueLock);
  142. InsertHeadList(&NhpBufferQueue, &Bufferp->Link);
  143. LeaveCriticalSection(&NhpBufferQueueLock);
  144. InterlockedIncrement(&NhpBufferQueueLength);
  145. }
  146. } // NhReleaseBuffer
  147. VOID
  148. NhShutdownBufferManagement(
  149. VOID
  150. )
  151. /*++
  152. Routine Description:
  153. This routine cleans up resources used by the buffer-management module.
  154. It assumes the list will not be accessed while the clean up is in progress.
  155. Arguments:
  156. none.
  157. Return Value:
  158. none.
  159. --*/
  160. {
  161. PLIST_ENTRY Link;
  162. PNH_BUFFER Bufferp;
  163. while (!IsListEmpty(&NhpBufferQueue)) {
  164. Link = RemoveHeadList(&NhpBufferQueue);
  165. Bufferp = CONTAINING_RECORD(Link, NH_BUFFER, Link);
  166. NH_FREE_BUFFER(Bufferp);
  167. }
  168. DeleteCriticalSection(&NhpBufferQueueLock);
  169. NhpBufferQueueLength = 0;
  170. } // NhShutdownBufferManagement