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) 1996,1997 Microsoft Corporation
  3. Module Name:
  4. FRAMEBUF.CPP
  5. Abstract:
  6. Manages Memory for Send/Receive Frames.
  7. BUGBUG: when you have time do an intelligent implementation,
  8. for now this is just a frame cache.
  9. Author:
  10. Aaron Ogus (aarono)
  11. Environment:
  12. Win32/COM
  13. Revision History:
  14. Date Author Description
  15. ====== ====== ============================================================
  16. 12/10/96 aarono Original
  17. 6/6/98 aarono More debug checks, shrink pool.
  18. --*/
  19. #include <windows.h>
  20. #include "newdpf.h"
  21. #include <dplay.h>
  22. #include <dplaysp.h>
  23. #include <dplaypr.h>
  24. #include "mydebug.h"
  25. #include "bufmgr.h"
  26. #include "macros.h"
  27. #define MAX_FRAMES_ON_LIST 16
  28. #define MIN_FRAMES_ON_LIST 8
  29. typedef struct _frame
  30. {
  31. BILINK Bilink;
  32. UINT len;
  33. UCHAR data[0];
  34. } FRAME, *PFRAME;
  35. BILINK FrameList;
  36. UINT nFramesOnList=0;
  37. UINT TotalFrameMemory=0;
  38. CRITICAL_SECTION FrameLock;
  39. #ifdef DEBUG
  40. void DebugChkFrameList()
  41. {
  42. BILINK *pBilink;
  43. PFRAME pFrameWalker;
  44. DWORD count=0;
  45. DWORD totalsize=0;
  46. DWORD fBreak=FALSE;
  47. Lock(&FrameLock);
  48. pBilink=FrameList.next;
  49. while(pBilink != &FrameList){
  50. pFrameWalker=CONTAINING_RECORD(pBilink,FRAME,Bilink);
  51. pBilink=pBilink->next;
  52. count++;
  53. totalsize+=pFrameWalker->len;
  54. }
  55. if(totalsize != TotalFrameMemory){
  56. DPF(0, "Total Frame Memory says %d but I count %d\n",TotalFrameMemory, totalsize);
  57. fBreak=TRUE;
  58. }
  59. if(count != nFramesOnList){
  60. DPF(0, "nFramesOnList %d but I count %d\n",nFramesOnList, count);
  61. fBreak=TRUE;
  62. }
  63. if(fBreak){
  64. DEBUG_BREAK();
  65. }
  66. Unlock(&FrameLock);
  67. }
  68. #else
  69. #define DebugChkFrameList()
  70. #endif
  71. VOID InitFrameBuffers(VOID)
  72. {
  73. InitBilink(&FrameList);
  74. InitializeCriticalSection(&FrameLock);
  75. nFramesOnList=0;
  76. TotalFrameMemory=0;
  77. }
  78. VOID FiniFrameBuffers(VOID)
  79. {
  80. BILINK *pBilink;
  81. PFRAME pFrame;
  82. Lock(&FrameLock);
  83. while(!EMPTY_BILINK(&FrameList)){
  84. pBilink=FrameList.next;
  85. pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
  86. Delete(pBilink);
  87. My_GlobalFree(pFrame);
  88. }
  89. nFramesOnList=0;
  90. TotalFrameMemory=0;
  91. Unlock(&FrameLock);
  92. DeleteCriticalSection(&FrameLock);
  93. }
  94. VOID ReleaseFrameBufferMemory(PUCHAR pFrameData)
  95. {
  96. PFRAME pFrame;
  97. BILINK FramesToFree;
  98. BILINK *pBilink;
  99. Lock(&FrameLock);
  100. DebugChkFrameList();
  101. InitBilink(&FramesToFree);
  102. pFrame=CONTAINING_RECORD(pFrameData,FRAME,data);
  103. InsertAfter(&pFrame->Bilink, &FrameList);
  104. nFramesOnList++;
  105. TotalFrameMemory+=pFrame->len;
  106. if(nFramesOnList > MAX_FRAMES_ON_LIST){
  107. while(nFramesOnList > MIN_FRAMES_ON_LIST){
  108. pBilink=FrameList.next;
  109. pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
  110. nFramesOnList--;
  111. TotalFrameMemory-=pFrame->len;
  112. Delete(pBilink);
  113. DebugChkFrameList();
  114. InsertAfter(pBilink, &FramesToFree);
  115. }
  116. }
  117. DebugChkFrameList();
  118. ASSERT(nFramesOnList);
  119. Unlock(&FrameLock);
  120. // Drop lock before freeing, to make more effecient.
  121. while(!EMPTY_BILINK(&FramesToFree)){
  122. pBilink=FramesToFree.next;
  123. pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
  124. Delete(pBilink);
  125. My_GlobalFree(pFrame);
  126. }
  127. DebugChkFrameList();
  128. }
  129. PBUFFER GetFrameBuffer(UINT FrameLen)
  130. {
  131. PBUFFER pBuffer;
  132. PFRAME pFrame;
  133. MEMDESC memdesc;
  134. BILINK *pBilinkWalker;
  135. PFRAME pFrameBest=NULL, pFrameWalker;
  136. UINT difference=FrameLen;
  137. DPF(9,"==>GetFrameBuffer Len %d\n",FrameLen);
  138. Lock(&FrameLock);
  139. if(!EMPTY_BILINK(&FrameList)){
  140. ASSERT(nFramesOnList);
  141. pBilinkWalker=FrameList.next;
  142. while(pBilinkWalker != &FrameList){
  143. pFrameWalker=CONTAINING_RECORD(pBilinkWalker, FRAME, Bilink);
  144. if(pFrameWalker->len >= FrameLen){
  145. if(FrameLen-pFrameWalker->len < difference){
  146. difference=FrameLen-pFrameWalker->len;
  147. pFrameBest=pFrameWalker;
  148. if(!difference){
  149. break;
  150. }
  151. }
  152. }
  153. pBilinkWalker=pBilinkWalker->next;
  154. }
  155. if(!pFrameBest){
  156. goto alloc_new_frame;
  157. } else {
  158. pFrame=pFrameBest;
  159. }
  160. DebugChkFrameList();
  161. Delete(&pFrame->Bilink);
  162. nFramesOnList--;
  163. TotalFrameMemory-=pFrame->len;
  164. DebugChkFrameList();
  165. Unlock(&FrameLock);
  166. } else {
  167. alloc_new_frame:
  168. Unlock(&FrameLock);
  169. pFrame=(PFRAME)My_GlobalAlloc(GMEM_FIXED,FrameLen+sizeof(FRAME));
  170. if(!pFrame){
  171. return NULL;
  172. }
  173. pFrame->len=FrameLen;
  174. }
  175. memdesc.pData=&pFrame->data[0];
  176. memdesc.len=pFrame->len;
  177. pBuffer=BuildBufferChain((&memdesc),1);
  178. if(!pBuffer){
  179. ReleaseFrameBufferMemory(pFrame->data);
  180. DPF(9,"<==GetFrameBuffer FAILED returning %x\n",pBuffer);
  181. } else {
  182. pBuffer->dwFlags |= BFLAG_FRAME;
  183. DPF(9,"<==GetFrameBuffer %x, len %d\n",pBuffer, pFrame->len);
  184. }
  185. DebugChkFrameList();
  186. return pBuffer;
  187. }
  188. // Release the buffer, put the memory back on the frame buffer list.
  189. VOID FreeFrameBuffer(PBUFFER pBuffer)
  190. {
  191. ASSERT(pBuffer->dwFlags & BFLAG_FRAME);
  192. ReleaseFrameBufferMemory(pBuffer->pData);
  193. FreeBuffer(pBuffer);
  194. }