SnoBunny85 0 Newbie Poster

My professor has given us the fifo algorithm program and asked us to modify it to become the clock algorithm by using reverse_map to find a page table entry and then checking its reference bit. If the reference bit is set, clear it and go on. I am just completely stuck on where to go with this coding. I have included the fifo code given to us and where he defines reverse_map. I think I am adding reverse_map correctly but not sure which parameters to use or where to quite go after that. i don't want the whole code written for me, just tips to head me in the right direction because he doesn't do a very good job of explaining things. I have also attached all of the files he gave us just in case those are needed as well. thanks

/*
 * Simulate clock algorithm
 *  -p <pagesize>	Page size offset bits, default 12
 *  -m <realmem>	Number of real memory pages.  Default 10
 *  -i <tracefile>	Input trace file name.  Default, standard input.
 *  -c <clrfreq>    Clear all the used bits each <clrfreq> references.
 *                     Default 10000
 */

#include <iostream>
using std::cout;
using std::endl;

#include "argval.h"
#include "memory_sys.h"
#include "trace_reader.h"

int main(int argc, const char **argv)
{
	// Collect the arguments and open the input file.
	ArgVal args(argc, argv);
	int pagebits = args.ival("-p", 12);
	int realmem = args.ival("-m", 10);
	RefReader tracereader;
	if(args.present("-i")) tracereader.open(args.cval("-i"));

	//add c to clear all the bit references
	int clrfreq = args.ival("-c", 10000);

	// The vm represents the page table and real memory.
	PageMapping vm(realmem);

	// Next page in FIFO ordering.
	unsigned int next = 0;

	// Various statistics we wish to collect.
	int nwrb = 0;		// Number of page write-backs.

	// Read the trace and process.
	Ref r;
	while(tracereader.read(r)) {
		// See how many pages the reference covers (almost always just
		// one), and the first page.  Then loop to process each of
		// those pages.
		int npage = r.npage(pagebits);
		unsigned int page = r.pageno(pagebits);
		while(npage--) {
			// Attempt the page reference.
			if(!vm.ref_page(page, r.is_write())) {
				// Fault.  Kick out old page and establish
				// new mapping.

--->this is my coding
            //using reverse_map to find the page table entry
            vm.reverse_map(next, , page);
---->
			PTE old_pte = vm.set_mapping(page, next);
			if(old_pte.mod) ++nwrb;

			// Repeat the reference.
			vm.ref_page(page, r.is_write());

			// Rotate next through the page numbers.
			if(++next >= realmem) next = 0;
			}
			++page;
		}
	}

	cout << "Clock replacement policy" << endl;
	cout << tracereader.ref_count() << " memory references produce "
	     << vm.get_numfault() << " page faults with " << nwrb
	     << " write-backs.\n" << vm.get_faultrate(tracereader.ref_count())
	     << " faults/reference." << endl;

}
#include <utility>

#include "memory_sys.h"

// Remove the entry for the indicated page.  Returns the old entry, which
// may have already been invalid.
PTE PageMapping::invalidate_pte(unsigned int pageno) 
{
	// Find the entry and invalidate it.
	map<unsigned int, PTE>::iterator i = table.find(pageno);
	if(i == table.end()) return PTE();

	// Make the return value, then erase the original
	PTE ret(i->second);
	table.erase(i);

	// Clear the reverse map.
	if(ret.valid)
		realmem[ret.realpage] = table.end();

	return ret;
}

// Set a new mapping in the table.  If the realpage is already in use,
// its existing mapping is cleared and a _copy_ of that _old_ PTE is
// returned.  If pageno is presently mapped, its old PTE is invalidated
// also, and not returned.  Then a new mapping is established with the
// referenced and modified bits clear
PTE PageMapping::set_mapping(unsigned int pageno, unsigned int realpage) 
{
	// If there is an existing mapping to realpage, create a return PTE
	// and invalidate the exising mapping.
	PTE ret;
	if(realmem[realpage] != table.end()) {
		ret = realmem[realpage]->second;
		table.erase(realmem[realpage]);
	}

	// If there is an existing mapping, invalidate it.  Otherwise,
	// insert a new entry and map it correctly.
	map<unsigned int, PTE>::iterator i = table.find(pageno);
	if(i == table.end()) {
		// No existing mapping.  Make one.
		i = table.insert(std::make_pair(pageno,PTE())).first;
		i->second.valid = true;
	} else {
		// Existing mapping.  Clear it.
		realmem[i->second.realpage] = table.end();
		i->second.ref = i->second.mod = false;
	}

	// Make the mapping (new or old) point to the require page, and
	// the page point back for the reverse map service.
	i->second.realpage = realpage;
	realmem[realpage] = i;

	return ret;
}

// Simulate a reference.  This returns true if the mapping is valid, or false
// if it creates a fault.  If it is not a fault, the referenced bit, and
// optionally the modified bit, are set.  If realpage is non-NULL, and the
// mapping was valid, the page number is returned through realpage.
bool PageMapping::ref_page(unsigned int pageno, unsigned int *realpage,
			   bool is_write /* = false */) {
	// Stats.
	if(is_write) ++nwrite;
	else ++nread;

	// Find the PTE.
	map<unsigned int, PTE>::iterator i = table.find(pageno);
	if(i == table.end()) {
		// No valid entry.  Count and return a fault.
		++nfault;
		return false;
	}

	// Valid.  Update flags and return required information.
	if(realpage) *realpage = i->second.realpage;
	i->second.ref = true;
	if(is_write) i->second.mod = true;
	return true;
}

// Pre-looked-up version.
bool PageMapping::ref_page(PTEptr pte, bool is_write /* = false */)
{
	// Stats.
	if(is_write) ++nwrite;
	else ++nread;

	// Find the PTE.
	if(pte == NULL) {
		// No valid entry.  Count and return a fault.
		++nfault;
		return false;
	}

	// Valid.  Update flags and return required information.
	pte.ref(true);
	if(is_write) pte.mod(true);
	return true;
}

// Reverse lookup.
bool PageMapping::reverse_map(unsigned int realpage, 
			      unsigned int *virtpage, PTEptr *pte)
{
	// Make sure the page number is in range, then find the
	// iterator recorded for the page, and see if it is valid.
	// If either test fails, return false.
	if(realpage >= nframes) return false;
	map<unsigned int, PTE>::iterator i = realmem[realpage];
	if(i == table.end()) return false;

	// Found one.  Fill in the return information.
	if(virtpage) *virtpage = i->first;
	if(pte) *pte = PTEptr(&i->second);
	return true;
}

// Following is a test program which is only compiled if the flag 
// -DMEMSYS_TEST is used.
#ifdef MEMSYS_TEST
#include <iostream>
#include <stdlib.h>

using namespace std;

bool PageMapping::conchk()
{
	bool bad = false;

	// Go through the PTEs and see if the reverse entries match.
	std::map<unsigned int, PTE>::iterator i;
	for(i = table.begin(); i != table.end(); ++i)
	{
		if(!i->second.valid) {
			cout << "Stored PTE for " << i->first << " invalid."
			     << endl;
			bad = true;
		}
		if(i->second.realpage >= nframes) {
			cout << "Page " << i->first << " maps to real page "
			     << i->second.realpage << ", whichis out of "
			     << "range." << endl;
			bad = true;
		}
		else if(realmem[i->second.realpage] != i) {
			cout << "Reverse map error: PTE " << i->first 
			     << " maps to " << i->second.realpage
			     << ", but that real page has wrong iterator." 
			     << endl;
			bad = true;
		}
	}

	// Check them the other way.
	for(unsigned int i = 0; i < nframes; ++i) {
		if(realmem[i] != table.end() && 
		   realmem[i]->second.realpage != i) {
			cout << "Real page " << i << " shows valid but "
			     << "maps back to " 
			     << realmem[i]->second.realpage << endl;
			bad = true;
		}
	}

	return !bad;
}

const unsigned int NFRAME = 200;
const unsigned int XMASK = 0x193;

// Computed target for mapping.
bool target(unsigned int page, unsigned int *_targ = NULL)
{
	unsigned int targ = page ^ XMASK;
	if(targ >= NFRAME) return false;
	if(_targ) *_targ = targ;
	return true;
}
unsigned int rtarg(unsigned int page)
{
	unsigned int targ = 0;
	target(page, &targ);
	return targ;
}

// Check the pattern of bits created by the test driver.  Mod (both) set
// for multiples of 5, and ref for 3.
bool bittest(unsigned int p, PTEptr pte)
{
	bool ok = true;

	if(pte->mod != (p % 5 == 0)) {
		cout << "Bad mod bit " << pte->mod << " at " << p << endl;
		ok = false;
	}
	bool ref = (p % 5 == 0) || (p % 3 == 0);
	if(pte->ref != ref) {
		cout << "Bad ref bit " << pte->ref << " at " << p << endl;
		ok = false;
	}

	return ok;
}

class PS: public PageMapping::PageScanner {
public:
	int validct;
	bool ok;

	PS(): validct(0), ok(true) { }

	virtual void visit(unsigned int pageno, PTEptr pte)
	{
		++validct;

		unsigned int t;
		if(target(pageno,&t) && t == pte->realpage) {
			if(!bittest(pageno, pte)) ok = false;
		} else if(pte->realpage == (pageno+1) % NFRAME) {
			if(pte->ref || pte->mod) {
				cout << "Bad bits on scan" << endl;
				ok = false;
			}
		}
	}	
};

class MS: public PageMapping::FrameScanner {
public:
	int tot;
	bool ok;
	MS(): tot(0), ok(true) { }
	virtual void visit(unsigned int frameno, unsigned int mapsto,
			   PTEptr mapper)
	{
		if(mapper != NULL) {
			++tot;
			if(mapper->realpage != frameno) {
				cout << "GAK! Bad ref on frame scan "
				     << mapper->realpage << " " << frameno << endl;
				ok = false;
			}
		}
	}
};

main()
{
	PageMapping pm(NFRAME);

	bool ok = pm.conchk();
	if(pm.get_nframes() != NFRAME) {
		cout << "Bad frame count " << pm.get_nframes() << " != "
		     << NFRAME << endl;
		ok = false;
	}

	// All pages should be invalid.
	for(unsigned int p = 0; p < 2*NFRAME; p += 13) {
		if(pm.valid(p) || pm.get_pte(p) != NULL) {
			cout << "Valid at empty " << p << endl;
			ok = false;
		}
	}

	// Set a bunch of mappings and check internal consistancy.
	int nvalid = 0;
	for(unsigned int p = 0; p < 2*NFRAME; ++p) {
		unsigned int t;
		if(!target(p,&t)) continue;
		PTE old = pm.set_mapping(p, t);
		if(old.valid) {
			cout << "Valid at first setting " << p << endl;
			ok = false;
		}
		++nvalid;
	}
	ok = pm.conchk() && ok;

	// Check the back references.
	int rev = 0;
	for(unsigned int r = 0; r < NFRAME; ++r) {
		unsigned int page;
		PTEptr pte;
		if(pm.reverse_map(r, &page, &pte)) {
			if(!pte->valid || pte->mod || pte->ref) {
				cout << "Bad flags on reverse PTE A" << endl;
				ok = false;
			}
			if(pte->realpage != r) {
				cout << "Bad reverse map failure A." << endl;
				ok = false;
			}
			++rev;
		}
	}
	if(rev != nvalid) {
		cout << "Forward and reverse map counts don't match." << endl;
		ok = false;
	}

	// Shadow counts to test the ones in the object.
	int nread = 0, nwrite = 0, nfault = 0;

	// Do some references.
	for(unsigned int p = 0; p < 2*NFRAME; p += 3) {
		++nread;
		bool valid = pm.ref_page(p);
		if(!valid) ++nfault;
		if(valid != target(p)) {
			cout << "Bad validity at ref_page(" << p << ")" << endl;
			ok = false;
		}
	}

	// Do some modification refs.
	for(unsigned int p = 0; p < 2*NFRAME; p += 5) {
		++nwrite;
		bool valid = pm.ref_page(p, true);
		if(!valid) ++nfault;
		if(valid != target(p)) {
			cout << "Bad validity at mod ref_page(" << p << ")" 
			     << endl;
			ok = false;
		}
	}

	// See if it's all ok.
	ok = pm.conchk() && ok;
	for(unsigned int p = 0; p < 2*NFRAME; ++p) {
		unsigned int t;
		bool v = target(p,&t);
		PTEptr pte = pm.get_pte(p);

		if(v != (pte != NULL)) {
			cout << "Bad validity at get_pte(" << p << ")" << endl;
			ok = false;
			continue;
		}

		if(pte == NULL) continue;

		if(pte->realpage != t) {
			cout << "Bad target for " << p << ": should be "
			     << v << " instead of " << pte->realpage << endl;
			ok = false;
		}
		
		ok = bittest(p, pte) && ok;

		// Check the reverse mapping.
		unsigned int vp;
		PTEptr revpte;
		if(!pm.reverse_map(pte->realpage,&vp,&revpte) || vp != p ||
		   revpte != pte) {
			cout << "Reverse map failure B." << endl;
			ok = false;
		}
	}

	// Some random tests
	int origvalid = nvalid;
	int changed = 0;
	for(int n = 1; n <= 500; ++n)
	{
		unsigned int p = rand() % (2*NFRAME);
		unsigned int t;
		bool v = target(p,&t);

		PTE old;
		PTEptr oldptr = pm.get_pte(p);
		if(oldptr != NULL) old = *oldptr;
		PTE pte = pm.set_mapping(p,(p+1)%NFRAME);

		// Account for destroyed entries, and for one created.
		if(oldptr != NULL && old.realpage != (p+1)%NFRAME) --nvalid;
		if(pte.valid) --nvalid;
		++nvalid;

		if(oldptr == NULL) {
			// There was not a previous mapping from p.
			if(!v) {
				// There was no old mapping, so there
				// reason for suspicion.
			} else {
				// If this happens, it should have been
				// a replacement by a new one.  See if there
				// is a new-style mapping to t.  It can also be
				// knocked out by a forward mapping from the same
				// virtual page, which then gets replaced by
				// a different multiple of NFRAME.
				unsigned int oldfrom = 
					t == 0 ? NFRAME - 1 : t - 1;
				unsigned int altfrom = p % NFRAME;
				bool found = false;
				while(!found && oldfrom < 2*NFRAME) {
					PTEptr altmap = pm.get_pte(oldfrom);
					found = (altmap != NULL && 
						 altmap->realpage == t);
					if(found) break;
					oldfrom += NFRAME;

					altmap = pm.get_pte(altfrom);
					found = (altmap != NULL && 
						 altmap->realpage == (altfrom+1)%NFRAME);
					altfrom += NFRAME;
				}
				if(!found) {
					cout << "Missing old mapping from "
					     << p << " t = " << t 
					     << " oldfrom = " << oldfrom
					     << endl;
					ok = false;
				}
			}
		} else {
			// Might have replaced an old one or a new one.
			if(v && old.realpage == t) {
				// Bits must be unchanged from earlier test
				ok = bittest(p, &old) && ok;
			} else if(old.realpage == (p+1)%NFRAME) {
				// New entry.  Must be zero.
				if(old.mod || old.ref) {
					cout << "Bad bits on new entry at "
					     << p << endl;
					ok = false;
				}
				++changed;
			} else {
				cout << "Bad target maps " << p << " to "
				     << old.realpage << endl;
				ok = false;
			}
		}

		// Check the reverse mapping.
		unsigned int vp;
		PTEptr revpte;
		if(!pm.reverse_map((p+1)%NFRAME,&vp,&revpte) || vp != p ||
		   revpte == NULL || revpte->realpage != (p+1)%NFRAME) {
			cout << "Reverse map failure C." << endl;
			ok = false;
		}

		if(n % 10 == 0)
			ok = pm.conchk() && ok;
	}

	cout << origvalid << " original valid entries; "
	     << nvalid << " final valid entries." << endl;
	cout << changed << " observed redirects" << endl;

	PS pscanner;
	pscanner.scan(pm);
	if(pscanner.validct != nvalid) {
		cout << "Scan valid count mismatch " << pscanner.validct
		     << " != " << nvalid << endl;
		ok = false;
	}

	MS mscanner;
	mscanner.scan(pm);
	if(mscanner.tot != nvalid) {
		cout << "Tot use count incorrect " << mscanner.tot 
		     << " != " << nvalid << endl;
		ok = false;
	}

	ok = pm.conchk() && pscanner.ok && mscanner.ok && ok;

	if(pm.get_numread() != nread || pm.get_numwrite() != nwrite || 
	   pm.get_numfault() != nfault) {
		cout << "Count error: " 
		     << pm.get_numread() << " " << nread  << " "
		     << pm.get_numwrite() << " " << nwrite << " " 
		     << pm.get_numfault() << " " << nfault << endl;
		ok = false;
	}

	if(ok) {
		cout << "All tests okay." << endl;
		exit(0);
	} else
		exit(1);
}
#endif