Windows2003-3790/sdktools/mep/browser/mbrmake/vm.c
2020-09-30 16:53:55 +02:00

198 lines
4.3 KiB
C

// vm.c
//
// simple minded virtual memory implemenation
// there is no code to do the OS2 version...
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <string.h>
#if defined(OS2)
#define INCL_NOCOMMON
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#define INCL_DOSMISC
#include <os2.h>
#else
#include <windows.h>
#endif
#include "hungary.h"
#include "vm.h"
#include "sbrproto.h"
#include "errors.h"
#define CB_PAGE_SIZE 2048 // 4k pages
#define C_LOCKS_MAX 16 // up to 16 pages may be locked in ram
#define C_PAGES_MAX 8192 // up to 4k pages resident
#define C_FREE_LIST_MAX 256 // keep free lists for items up to 256 bytes
#define GRP_MAX 16 // max number of memory groups
typedef WORD VPG; // virtual page number
typedef VA far *LPVA; // far pointer to VA
// virtual address arithmetic
//
// #define VpgOfVa(va) ((WORD)((va>>12)))
// this is really the same as the above but it assumes that the high byte
// of the long is all zero's and it is optimized for our C compiler
#define VpgOfVa(va) ((((WORD)((BYTE)(va>>16)))<<4)|\
(((BYTE)(((WORD)va)>>8))>>4))
#define OfsOfVa(va) ((WORD)((va) & 0x07ff))
#define VaBaseOfVpg(vpg) (((DWORD)(vpg)) << 12)
// phsyical page header
typedef struct _pg {
BYTE fDirty; // needs to be written out
BYTE cLocks; // this page is locked
VPG vpg; // what is the virtual page number of this page
struct _pg FAR *lppgNext; // LRU ordering next
struct _pg FAR *lppgPrev; // and prev
} PG;
typedef PG FAR * LPPG;
typedef struct _mem {
VA vaFree;
WORD cbFree;
VA mpCbVa[C_FREE_LIST_MAX];
#ifdef SWAP_INFO
WORD cPages;
#endif
} MGI; // Memory Group Info
static MGI mpGrpMgi[GRP_MAX];
// translation table -- map virtual page number to physical page address
static LPPG mpVpgLppg[C_PAGES_MAX];
// head and tail pointers for LRU
//
static LPPG near lppgHead;
static LPPG near lppgTail;
// nil page pointer
//
#define lppgNil 0
// points to the start of linked lists of free blocks
//
static VA mpCbVa[C_FREE_LIST_MAX];
// these pages are locked in memory
//
static LPPG near rgLppgLocked[C_LOCKS_MAX];
// number of pages we have given out
static VPG near vpgMac;
// number of physical pages we have resident
static WORD near cPages;
// should we keep trying to allocate memory
static BOOL near fTryMemory = TRUE;
// the file handle for the backing store
static int near fhVM;
// the name of the file for the backing store
static LSZ near lszVM;
#ifdef ASSERT
#define Assert(x, sz) { if (!(x)) AssertionFailed(sz); }
VOID
AssertionFailed(LSZ lsz)
// something went wrong...
//
{
printf("assertion failure:%s\n", lsz);
Fatal();
}
#else
#define Assert(x, y)
#endif
LPV VM_API
LpvAllocCb(ULONG cb)
// allocate a block of far memory, if _fmalloc fails, the free some of
// the memory we were using for the VM cache
//
{
LPV lpv;
if (!(lpv = calloc(cb,1))) {
Error(ERR_OUT_OF_MEMORY, "");
}
return lpv;
}
VA VM_API
VaAllocGrpCb(WORD grp, ULONG cb)
// allocate cb bytes from the requested memory group
//
{
VA vaNew;
MGI FAR *lpMgi;
LPV lpv;
lpMgi = &mpGrpMgi[grp];
Assert(grp < GRP_MAX, "Memory Group out of range");
if (cb < C_FREE_LIST_MAX && (vaNew = lpMgi->mpCbVa[cb])) {
lpv = LpvFromVa(vaNew, 0);
lpMgi->mpCbVa[cb] = *(LPVA)lpv;
memset(lpv, 0, cb);
DirtyVa(vaNew);
return vaNew;
}
if (cb < mpGrpMgi[grp].cbFree) {
vaNew = mpGrpMgi[grp].vaFree;
(PBYTE)mpGrpMgi[grp].vaFree += cb;
mpGrpMgi[grp].cbFree -= cb;
}
else {
vaNew = VaAllocCb(CB_PAGE_SIZE - sizeof(PG));
mpGrpMgi[grp].vaFree = (PBYTE)vaNew + cb;
mpGrpMgi[grp].cbFree = CB_PAGE_SIZE - cb - sizeof(PG);
}
return vaNew;
}
VOID VM_API
FreeGrpVa(WORD grp, VA va, ULONG cb)
// put this block on the free list for blocks of that size
// we don't remember how big the blocks were so the caller has
// provide that info
//
{
MGI FAR *lpMgi;
lpMgi = &mpGrpMgi[grp];
if (cb < C_FREE_LIST_MAX && cb >= 4 ) {
*(LPVA)LpvFromVa(va, 0) = lpMgi->mpCbVa[cb];
DirtyVa(va);
lpMgi->mpCbVa[cb] = va;
}
}