home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
APPS
/
hl10osrc.zoo
/
Lib
/
vm.cc
< prev
Wrap
Text File
|
2009-11-06
|
10KB
|
343 lines
/* -*- Mode: C -*- */
/* vm.cc - PageFile implementation (virtual memory management)
* Created by Robert Heller on Sat Dec 7 00:19:52 1991
*
* ------------------------------------------------------------------
* Home Libarian by Deepwoods Software
* Common Class library implementation code
* ------------------------------------------------------------------
* Modification History:
* ------------------------------------------------------------------
* Contents:
* ------------------------------------------------------------------
*
*
* Copyright (c) 1991,1992 by Robert heller (D/B/A Deepwoods Software)
* All Rights Reserved
*
*/
#include <stream.h>
#include <vm.h>
// File open function.
// Open or create the page file
OpenStatus PageFile::open(char *filename,Direction direction,int flags,int mode,
Boolean create_if)
{
OpenStatus result = failure; // assume failure
fd = ::open(filename,flags); // try to open the file
// failure?
if (fd < 0) {
// yes. create a new file if posible
if (create_if && (direction == out || direction == inout)) {
#ifdef OSK
fd = create(filename,flags,mode); // OSK specific
#else
fd = ::open(filename,flags|O_CREAT,mode); // vanila UNIX
#endif
// still a problem? give up
if (fd < 0) return(failure);
// else note that it is a new file
result = opennew;
} else return(failure);
} else result = openold; // old file open
PageFile::direction = direction; // remember direction
numpagesincore = 0; // empty WS
isopen = true; // yes, it is open
return(result);
}
// close a PageFile
void PageFile::close()
{
// if the file is open...
if (isopen) {
for (int i = 0; i < numpagesincore; i++) {
// write out any dirty pages
if (pagetable[i].isdirty) {
if (!PageWrite(pagetable[i])) {
int error = errno;
cerr << "%%% PageWrite error. Page no. = " <<
pagetable[i].diskpage.record_address <<
"\n";
exit(error);
}
pagetable[i].isdirty = false;
}
// free up and used core memory
if (pagetable[i].corepage != 0) {
delete pagetable[i].corepage;
pagetable[i].corepage = 0;
}
}
// really close the file
::close(fd);
// nope, not open anymore
isopen = false;
// no pages core resident
numpagesincore = 0;
}
}
// Read in a page. ptentry says which page.
Boolean PageFile::PageRead(PTEntry& ptentry)
{
//cerr << "*** PageFile::PageRead(): page's disk address is " <<
// ptentry.diskpage.record_address << "\n";
// try to seek to page
long pos = lseek(fd,ptentry.diskpage.record_address,SEEK_SET);
// can't seek? fail
if (pos == -1L) return(false);
// do we have memory available?
if (ptentry.corepage == 0) {
ptentry.corepage = new Page; // allocate memory if needed
}
//cerr << "*** -: page's core address is 0x" <<
// form("%08x",ptentry.corepage) << "\n";
// read in page
if (read(fd,(char *)(ptentry.corepage),sizeof(Page)) <
sizeof(Page)) return(false);
// page is ready and clean
ptentry.isdirty = false;
return(true);
}
// Write out a page
Boolean PageFile::PageWrite(PTEntry& ptentry)
{
//cerr << "*** PageFile::PageWrite(): page's disk address is " <<
// ptentry.diskpage.record_address <<
// ", and its core address is 0x" <<
// form("%08x",ptentry.corepage) << "\n";
// seek to disk space
long pos = lseek(fd,ptentry.diskpage.record_address,SEEK_SET);
// if seek failure, return failure
if (pos == -1L) return(false);
// write the page
if (write(fd,(char *)(ptentry.corepage),sizeof(Page)) <
sizeof(Page)) return(false);
// no longer dirty...
ptentry.isdirty = false;
return(true);
}
// Locate a page. Read the page in if necessary, dumping the least recently
// referenced page to make room
PTEntry & PageFile::FindPage(DiskPage diskpage)
{
//cerr << "*** in PageFile::FindPage - looking for page " <<
// diskpage.record_address << "\n";
// is page already resident?
for (int i = 0; i < numpagesincore; i++) {
if (pagetable[i].diskpage == diskpage) {
// yes. promote page to end of table, if it is not
// already there
//cerr << "*** -: Page is resident.\n";
if (i < (numpagesincore-1)) {
temp = pagetable[i];
for (int j = i+1; j < numpagesincore; j++) {
pagetable[j-1] = pagetable[j];
}
pagetable[numpagesincore-1] = temp;
}
//cerr << "*** -: core address is 0x" <<
// form("%08x",pagetable[numpagesincore-1].corepage) <<
// "\n";
// return page table entry
return(pagetable[numpagesincore-1]);
}
}
//cerr << "*** -: Page is non-resident.\n";
// page not in core. Is WS (page table) full?
if (numpagesincore < NumPTEntries) {
//cerr << "*** -: WS grown.\n";
// if not, use new entry at the end and increase WS
pagetable[numpagesincore].diskpage = diskpage;
if (!PageRead(pagetable[numpagesincore])) {
int error = errno;
cerr << "%%% PageRead error: page no. = " <<
diskpage.record_address << "\n";
exit(error);
}
numpagesincore++;
//cerr << "*** -: core address is 0x" <<
// form("%08x",pagetable[numpagesincore-1].corepage) <<
// "\n";
return(pagetable[numpagesincore-1]);
} else { // otherwise, bump a page
// if old page is dirty, write it out
if (pagetable[0].isdirty == true) {
//cerr << "*** -: Page out " <<
// pagetable[0].diskpage.record_address <<
// "\n";
if (!PageWrite(pagetable[0])) {
int error = errno;
cerr << "%%% PageWrite error: page no. = " <<
pagetable[0].diskpage.record_address <<
"\n";
exit(error);
}
}
// shift pages down
temp = pagetable[0];
for (int j = 1; j < numpagesincore; j++) {
pagetable[j-1] = pagetable[j];
}
pagetable[numpagesincore-1] = temp;
// setup page
pagetable[numpagesincore-1].diskpage = diskpage;
if(!PageRead(pagetable[numpagesincore-1])) {
int error = errno;
cerr << "%%% PageRead error: page no. = " <<
diskpage.record_address << "\n";
exit(error);
}
//cerr << "*** -: core address is 0x" <<
// form("%08x",pagetable[numpagesincore-1].corepage) <<
// "\n";
return(pagetable[numpagesincore-1]);
}
}
// allocate a new, fresh page
DiskPage PageFile::NewPage()
{
DiskPage temppage; // new page
long int fill; // filler to make page address fall
// on a sector boundry
static char buffer[SectorSize]; // filler
static Boolean init = false; // init flag
if (init == false) { // filler initialization
memset(buffer,'\0',SectorSize);
init = true;
}
//cerr << "*** in PageFile::NewPage()\n";
// find eof
temppage = lseek(fd,0,SEEK_END);
if (temppage == -1L) return temppage; // failure??
// compute filler size
fill = SectorSize - (temppage.record_address & (SectorSize-1));
// is filler even needed?
if (fill == SectorSize) fill = 0;
if (fill != 0) {
// yep. write filler and re-compute page address.
write(fd,buffer,fill);
temppage = lseek(fd,0,SEEK_END);
}
//cerr << "*** -: new page at " << temppage.record_address << "\n";
// find a home for this page (code copied from FindPage, with
// minor mode)
if (numpagesincore < NumPTEntries) {
//cerr << "*** -: WS grown.\n";
pagetable[numpagesincore].diskpage = temppage;
if (pagetable[numpagesincore].corepage == 0) {
pagetable[numpagesincore].corepage = new Page;
}
//cerr << "*** -: core address is 0x" <<
// form("%08x",pagetable[numpagesincore].corepage) <<
// "\n";
memset((char *) pagetable[numpagesincore].corepage,
'\0',SectorSize);
if (!PageWrite(pagetable[numpagesincore])) {
int error = errno;
cerr << "%%% PageWrite error: page no. = " <<
pagetable[numpagesincore].diskpage.record_address <<
"\n";
exit(error);
}
pagetable[numpagesincore].isdirty = false;
numpagesincore++;
return(pagetable[numpagesincore-1].diskpage);
} else {
if (pagetable[0].isdirty == true) {
//cerr << "*** -: Page out " <<
// pagetable[0].diskpage.record_address <<
// "\n";
if (!PageWrite(pagetable[0])) {
int error = errno;
cerr << "%%% PageWrite error: page no. = " <<
pagetable[0].diskpage.record_address <<
"\n";
exit(error);
}
}
temp = pagetable[0];
for (int j = 1; j < numpagesincore; j++) {
pagetable[j-1] = pagetable[j];
}
pagetable[numpagesincore-1] = temp;
pagetable[numpagesincore-1].diskpage = temppage;
memset((char *) pagetable[numpagesincore-1].corepage,
'\0',SectorSize);
//cerr << "*** -: core address is 0x" <<
// form("%08x",pagetable[numpagesincore-1].corepage) <<
// "\n";
if (!PageWrite(pagetable[numpagesincore-1])) {
int error = errno;
cerr << "%%% PageWrite error: page no. = " <<
pagetable[numpagesincore-1].diskpage.record_address <<
"\n";
exit(error);
}
pagetable[numpagesincore-1].isdirty = false;
return(pagetable[numpagesincore-1].diskpage);
}
}
// Read in a data record
int PageFile::ReadRecord(DiskRecord& record, char *buffer, int buffsize)
{
// seek to data offset
long pos = lseek(fd,record.record_address,SEEK_SET);
// seek failure?
if (pos == -1) return(-1);
// read in data (or at as much as will fit in record
if (buffsize >= record.record_size) {
return(read(fd,buffer,record.record_size));
} else {
return(read(fd,buffer,buffsize));
}
}
// Write a redord out
DiskRecord PageFile::WriteRecord(char *buffer, int buffsize)
{
DiskRecord newrec; // new disk record
// seek to EOF
newrec.record_address = lseek(fd,0,SEEK_END);
// seek failure??
if (newrec.record_address == -1L) {
return 0;
}
//cerr.form("*** in WriteRecord(): newrec.record_address = 0x%08x\n",
// newrec.record_address);
// write out record
newrec.record_size = write(fd,buffer,buffsize);
//cerr.form("*** in WriteRecord(): buffsize = %d, newrec.record_size = %d\n",
// buffsize,newrec.record_size);
return(newrec);
}
// update old record or write new one
DiskRecord PageFile::ReWriteRecord(DiskRecord& record, char *buffer, int buffsize)
{
long pos;
//cerr << "*** PageFile::ReWriteRecord(): record = (:SIZE " <<
// record.record_size << " :ADDR " << record.record_address <<
// "), buffsize = " << buffsize << "\n";
// will new record fill in old place?
if (buffsize > record.record_size) {
// no, create new record
return(PageFile::WriteRecord(buffer,buffsize));
} else {
// yes, rewrite old record
pos = lseek(fd,record.record_address,SEEK_SET);
if (pos == -1) return(0);
record.record_size = write(fd,buffer,buffsize);
return(record);
}
}