2002-08-28 01:34:19 +00:00
|
|
|
#include <new.h>
|
2002-07-19 03:55:07 +00:00
|
|
|
#include <cacheManager.h>
|
2002-09-05 03:26:02 +00:00
|
|
|
#include "vmHeaderBlock.h"
|
2002-07-19 03:55:07 +00:00
|
|
|
|
2002-12-15 07:05:38 +00:00
|
|
|
// functions for hash and isEqual. No surprises
|
2002-11-19 04:05:16 +00:00
|
|
|
ulong vnodeHash (node &vp) {vnode &vn=reinterpret_cast <vnode &>(vp); return vn.offset+vn.fd;}
|
|
|
|
|
bool vnodeisEqual (node &vp,node &vp2) {
|
|
|
|
|
vnode &vn=reinterpret_cast <vnode &>(vp);
|
|
|
|
|
vnode &vn2=reinterpret_cast <vnode &>(vp2);
|
|
|
|
|
return vn.fd==vn2.fd && vn.offset==vn2.offset;
|
|
|
|
|
}
|
2002-09-14 17:03:16 +00:00
|
|
|
|
2002-09-05 03:26:02 +00:00
|
|
|
extern vmHeaderBlock *vmBlock;
|
2003-03-26 04:00:38 +00:00
|
|
|
|
2002-11-19 04:05:16 +00:00
|
|
|
cacheManager::cacheManager(void) : area (),cacheMembers(30) {
|
2002-08-28 03:26:23 +00:00
|
|
|
myLock=create_sem(1,"Cache Manager Semaphore");
|
2002-11-19 04:05:16 +00:00
|
|
|
cacheMembers.setHash(vnodeHash);
|
|
|
|
|
cacheMembers.setIsEqual(vnodeisEqual);
|
2002-07-19 03:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
2002-12-15 07:05:38 +00:00
|
|
|
// Given a vnode and protection level, see if we have it in cache already
|
2002-11-19 04:05:16 +00:00
|
|
|
void *cacheManager::findBlock(vnode *target,bool readOnly) {
|
|
|
|
|
cacheMember *candidate=reinterpret_cast<cacheMember *>(cacheMembers.find(target));
|
|
|
|
|
|
|
|
|
|
if (!candidate || readOnly || candidate->vp->getProtection()>=writable)
|
|
|
|
|
return candidate;
|
|
|
|
|
|
2002-12-15 07:05:38 +00:00
|
|
|
// At this point, we have the first one in the hash bucket. Loop over the hash bucket from now on,
|
2002-11-19 04:05:16 +00:00
|
|
|
// looking for an equality and writability match...
|
|
|
|
|
for (struct cacheMember *cur=candidate;cur;cur=reinterpret_cast<cacheMember *>(cur->next)) {
|
2002-07-19 03:55:07 +00:00
|
|
|
if ((target==cur->vn) && (readOnly || (cur->vp->getProtection()>=writable)))
|
|
|
|
|
return (cur->vp->getStartAddress());
|
|
|
|
|
}
|
2002-11-19 04:05:16 +00:00
|
|
|
// We didn't find one, but to get here, there has to be one that is READ ONLY. So let's make a copy
|
|
|
|
|
// of that one, but readable...
|
|
|
|
|
return createBlock(target,false);
|
2002-07-19 03:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
2002-12-15 07:05:38 +00:00
|
|
|
// No cache hit found; have to make a new one. Find a virtual page, create a vnode, and map.
|
2002-11-19 04:05:16 +00:00
|
|
|
void *cacheManager::createBlock(vnode *target,bool readOnly, cacheMember *candidate) {
|
2002-07-19 03:55:07 +00:00
|
|
|
bool foundSpot=false;
|
2003-03-26 04:00:38 +00:00
|
|
|
vpage *cur=NULL;
|
2002-07-19 03:55:07 +00:00
|
|
|
unsigned long begin=CACHE_BEGIN;
|
2003-03-26 04:00:38 +00:00
|
|
|
|
2002-07-25 01:27:00 +00:00
|
|
|
lock();
|
2003-03-26 04:00:38 +00:00
|
|
|
// Find a place in the cache's virtual space to put this vnode...
|
|
|
|
|
// This *HAS* to succeed, because the address space should be larger than physical memory...
|
|
|
|
|
for (int i=0;!foundSpot && i<pageCount;i++) {
|
|
|
|
|
cur=getNthVpage(i);
|
|
|
|
|
foundSpot=!cur->getPhysPage();
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 03:55:07 +00:00
|
|
|
// Create a vnode here
|
2003-03-26 04:00:38 +00:00
|
|
|
cur->setup((unsigned long)(cur->getStartAddress()),target,NULL,((readOnly)?readable:writable),NO_LOCK);
|
|
|
|
|
cacheMembers.add(cur);
|
2002-11-19 04:05:16 +00:00
|
|
|
// While this may not seem like a good idea (since this only happens on a write),
|
|
|
|
|
// it is because someone may only write to part of the file/page...
|
|
|
|
|
if (candidate)
|
2003-03-26 04:00:38 +00:00
|
|
|
memcpy(cur->getStartAddress(),candidate->vp->getStartAddress(),PAGE_SIZE);
|
2002-07-25 01:27:00 +00:00
|
|
|
unlock();
|
2002-07-19 03:55:07 +00:00
|
|
|
// return address from this vnode
|
2003-03-26 04:00:38 +00:00
|
|
|
return cur->getStartAddress();
|
2002-07-19 03:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-19 04:05:16 +00:00
|
|
|
void *cacheManager::readBlock(vnode *target) {
|
2002-07-19 03:55:07 +00:00
|
|
|
void *destination=findBlock(target,true);
|
|
|
|
|
if (destination) return destination;
|
|
|
|
|
return createBlock(target,true);
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-19 04:05:16 +00:00
|
|
|
void *cacheManager::writeBlock(vnode *target) {
|
2002-07-19 03:55:07 +00:00
|
|
|
void *destination=findBlock(target,false);
|
|
|
|
|
if (destination) return destination;
|
|
|
|
|
return createBlock(target,false);
|
|
|
|
|
}
|