257 lines
4.7 KiB
C
257 lines
4.7 KiB
C
/*++
|
|
|
|
Copyright (c) 1996,1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
FRAMEBUF.CPP
|
|
|
|
Abstract:
|
|
|
|
Manages Memory for Send/Receive Frames.
|
|
BUGBUG: when you have time do an intelligent implementation,
|
|
for now this is just a frame cache.
|
|
|
|
Author:
|
|
|
|
Aaron Ogus (aarono)
|
|
|
|
Environment:
|
|
|
|
Win32/COM
|
|
|
|
Revision History:
|
|
|
|
Date Author Description
|
|
====== ====== ============================================================
|
|
12/10/96 aarono Original
|
|
6/6/98 aarono More debug checks, shrink pool.
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include "newdpf.h"
|
|
#include <dplay.h>
|
|
#include <dplaysp.h>
|
|
#include <dplaypr.h>
|
|
#include "mydebug.h"
|
|
#include "bufmgr.h"
|
|
#include "macros.h"
|
|
|
|
#define MAX_FRAMES_ON_LIST 16
|
|
#define MIN_FRAMES_ON_LIST 8
|
|
|
|
typedef struct _frame
|
|
{
|
|
BILINK Bilink;
|
|
UINT len;
|
|
UCHAR data[0];
|
|
} FRAME, *PFRAME;
|
|
|
|
BILINK FrameList;
|
|
UINT nFramesOnList=0;
|
|
UINT TotalFrameMemory=0;
|
|
CRITICAL_SECTION FrameLock;
|
|
|
|
#ifdef DEBUG
|
|
void DebugChkFrameList()
|
|
{
|
|
BILINK *pBilink;
|
|
PFRAME pFrameWalker;
|
|
|
|
DWORD count=0;
|
|
DWORD totalsize=0;
|
|
DWORD fBreak=FALSE;
|
|
|
|
Lock(&FrameLock);
|
|
|
|
pBilink=FrameList.next;
|
|
while(pBilink != &FrameList){
|
|
pFrameWalker=CONTAINING_RECORD(pBilink,FRAME,Bilink);
|
|
pBilink=pBilink->next;
|
|
count++;
|
|
totalsize+=pFrameWalker->len;
|
|
}
|
|
|
|
if(totalsize != TotalFrameMemory){
|
|
DPF(0, "Total Frame Memory says %d but I count %d\n",TotalFrameMemory, totalsize);
|
|
fBreak=TRUE;
|
|
}
|
|
|
|
if(count != nFramesOnList){
|
|
DPF(0, "nFramesOnList %d but I count %d\n",nFramesOnList, count);
|
|
fBreak=TRUE;
|
|
}
|
|
if(fBreak){
|
|
DEBUG_BREAK();
|
|
}
|
|
|
|
Unlock(&FrameLock);
|
|
}
|
|
#else
|
|
#define DebugChkFrameList()
|
|
#endif
|
|
|
|
VOID InitFrameBuffers(VOID)
|
|
{
|
|
InitBilink(&FrameList);
|
|
InitializeCriticalSection(&FrameLock);
|
|
nFramesOnList=0;
|
|
TotalFrameMemory=0;
|
|
}
|
|
|
|
VOID FiniFrameBuffers(VOID)
|
|
{
|
|
BILINK *pBilink;
|
|
PFRAME pFrame;
|
|
|
|
Lock(&FrameLock);
|
|
|
|
while(!EMPTY_BILINK(&FrameList)){
|
|
pBilink=FrameList.next;
|
|
pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
|
|
Delete(pBilink);
|
|
My_GlobalFree(pFrame);
|
|
}
|
|
|
|
nFramesOnList=0;
|
|
TotalFrameMemory=0;
|
|
|
|
Unlock(&FrameLock);
|
|
DeleteCriticalSection(&FrameLock);
|
|
}
|
|
|
|
VOID ReleaseFrameBufferMemory(PUCHAR pFrameData)
|
|
{
|
|
PFRAME pFrame;
|
|
BILINK FramesToFree;
|
|
BILINK *pBilink;
|
|
|
|
Lock(&FrameLock);
|
|
|
|
DebugChkFrameList();
|
|
|
|
InitBilink(&FramesToFree);
|
|
|
|
pFrame=CONTAINING_RECORD(pFrameData,FRAME,data);
|
|
|
|
InsertAfter(&pFrame->Bilink, &FrameList);
|
|
nFramesOnList++;
|
|
TotalFrameMemory+=pFrame->len;
|
|
|
|
if(nFramesOnList > MAX_FRAMES_ON_LIST){
|
|
while(nFramesOnList > MIN_FRAMES_ON_LIST){
|
|
pBilink=FrameList.next;
|
|
pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
|
|
nFramesOnList--;
|
|
TotalFrameMemory-=pFrame->len;
|
|
Delete(pBilink);
|
|
DebugChkFrameList();
|
|
InsertAfter(pBilink, &FramesToFree);
|
|
}
|
|
}
|
|
|
|
DebugChkFrameList();
|
|
ASSERT(nFramesOnList);
|
|
|
|
Unlock(&FrameLock);
|
|
|
|
// Drop lock before freeing, to make more effecient.
|
|
|
|
while(!EMPTY_BILINK(&FramesToFree)){
|
|
pBilink=FramesToFree.next;
|
|
pFrame=CONTAINING_RECORD(pBilink,FRAME,Bilink);
|
|
Delete(pBilink);
|
|
My_GlobalFree(pFrame);
|
|
}
|
|
|
|
DebugChkFrameList();
|
|
|
|
}
|
|
|
|
PBUFFER GetFrameBuffer(UINT FrameLen)
|
|
{
|
|
PBUFFER pBuffer;
|
|
PFRAME pFrame;
|
|
MEMDESC memdesc;
|
|
|
|
BILINK *pBilinkWalker;
|
|
PFRAME pFrameBest=NULL, pFrameWalker;
|
|
UINT difference=FrameLen;
|
|
|
|
DPF(9,"==>GetFrameBuffer Len %d\n",FrameLen);
|
|
|
|
Lock(&FrameLock);
|
|
|
|
if(!EMPTY_BILINK(&FrameList)){
|
|
ASSERT(nFramesOnList);
|
|
|
|
pBilinkWalker=FrameList.next;
|
|
|
|
while(pBilinkWalker != &FrameList){
|
|
pFrameWalker=CONTAINING_RECORD(pBilinkWalker, FRAME, Bilink);
|
|
if(pFrameWalker->len >= FrameLen){
|
|
if(FrameLen-pFrameWalker->len < difference){
|
|
difference=FrameLen-pFrameWalker->len;
|
|
pFrameBest=pFrameWalker;
|
|
if(!difference){
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pBilinkWalker=pBilinkWalker->next;
|
|
}
|
|
|
|
if(!pFrameBest){
|
|
goto alloc_new_frame;
|
|
} else {
|
|
pFrame=pFrameBest;
|
|
}
|
|
|
|
DebugChkFrameList();
|
|
|
|
Delete(&pFrame->Bilink);
|
|
nFramesOnList--;
|
|
TotalFrameMemory-=pFrame->len;
|
|
|
|
DebugChkFrameList();
|
|
|
|
Unlock(&FrameLock);
|
|
|
|
} else {
|
|
|
|
alloc_new_frame:
|
|
Unlock(&FrameLock);
|
|
pFrame=(PFRAME)My_GlobalAlloc(GMEM_FIXED,FrameLen+sizeof(FRAME));
|
|
if(!pFrame){
|
|
return NULL;
|
|
}
|
|
pFrame->len=FrameLen;
|
|
}
|
|
|
|
memdesc.pData=&pFrame->data[0];
|
|
memdesc.len=pFrame->len;
|
|
|
|
pBuffer=BuildBufferChain((&memdesc),1);
|
|
|
|
if(!pBuffer){
|
|
ReleaseFrameBufferMemory(pFrame->data);
|
|
DPF(9,"<==GetFrameBuffer FAILED returning %x\n",pBuffer);
|
|
} else {
|
|
pBuffer->dwFlags |= BFLAG_FRAME;
|
|
DPF(9,"<==GetFrameBuffer %x, len %d\n",pBuffer, pFrame->len);
|
|
}
|
|
|
|
DebugChkFrameList();
|
|
|
|
return pBuffer;
|
|
}
|
|
|
|
// Release the buffer, put the memory back on the frame buffer list.
|
|
VOID FreeFrameBuffer(PBUFFER pBuffer)
|
|
{
|
|
ASSERT(pBuffer->dwFlags & BFLAG_FRAME);
|
|
ReleaseFrameBufferMemory(pBuffer->pData);
|
|
FreeBuffer(pBuffer);
|
|
}
|