Changes to mmap to make COPY and SHARED work correctly (I hope)

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2358 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps 2003-01-06 04:49:58 +00:00
parent de613a80e7
commit 954674ddf8
6 changed files with 45 additions and 20 deletions

View File

@ -53,7 +53,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,void * req,int page
}
// This is the really interesting part of creating an area
status_t area::createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/) {
status_t area::createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea /* For clone only*/, mmapSharing share) {
error ("area::createAreaGuts : name = %s, pageCount = %d, address = %lx, addressSpec = %d, pageState = %d, protection = %d, inFinalWrite = %d, fd = %d, offset = %d,originalArea=%ld\n",
inName,pageCount,address,type,inState,protect,inFinalWrite,fd,offset,originalArea);
vpage *newPage;
@ -78,7 +78,7 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr
newVnode.fd=fd;
newVnode.offset=offset;
// vmBlock->vnodeManager->addVNode(newVnode,newPage);
newPage->setup(base+PAGE_SIZE*i,&newVnode,NULL,protect,inState);
newPage->setup(base+PAGE_SIZE*i,&newVnode,NULL,protect,inState,share);
}
else
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
@ -99,8 +99,8 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr
return B_OK;
}
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset) {
return createAreaGuts(inName,pageCount,address,type,inState,protect,true,fd,offset);
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset, mmapSharing share) {
return createAreaGuts(inName,pageCount,address,type,inState,protect,true,fd,offset,NULL,share);
}
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect) {

View File

@ -29,8 +29,8 @@ class area : public node
area(void);
void setup(areaManager *myManager);
void freeArea(void);
status_t createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/);
status_t createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect,int fd,size_t offset);
status_t createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL,mmapSharing share=CLONEAREA /* For clone only*/);
status_t createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect,int fd,size_t offset, mmapSharing share=CLONEAREA);
status_t createArea (char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect);
status_t cloneArea(area *area, char *inName, void **address, addressSpec type,pageState inState,protectType protect);
unsigned long mapAddressSpecToAddress(addressSpec type,void *requested,int pageCount);

View File

@ -285,8 +285,9 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
strcpy( name,"mmap - need to include fileName");
addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY);
protectType protType=(prot&PROT_WRITE)?writable:(prot&PROT_READ)?readable:none;
// Not doing anything with MAP_SHARED and MAP_COPY - needs to be done
protectType protType;
protType=(flags&PROT_WRITE)?writable:(flags&(PROT_READ|PROT_EXEC))?readable:none;
//error ("flags = %x, anon = %x\n",flags,MAP_ANON);
lock();
if (flags & MAP_ANON) {
@ -294,10 +295,17 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
return addr;
}
int shareCount=0;
mmapSharing share;
if (flags & MAP_SHARED) { share=SHARED;shareCount++;}
if (flags & MAP_PRIVATE) { share=PRIVATE;shareCount++;}
if (flags & MAP_COPY){ share=COPY;shareCount++;}
if (shareCount!=1)
return NULL;
area *newArea = new (vmBlock->areaPool->get()) area;
newArea->setup(this);
//error ("area = %x, start = %x\n",newArea, newArea->getStartAddress());
newArea->createAreaMappingFile(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr,addType,LAZY,protType,fd,offset);
newArea->createAreaMappingFile(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr,addType,LAZY,protType,fd,offset,share);
atomic_add(&nextAreaID,1);
newArea->setAreaID(nextAreaID);
addArea(newArea);

View File

@ -47,6 +47,8 @@ enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM};
#define B_DMA_IO 0x00000001
#define B_READ_DEVICE 0x00000002
enum mmapSharing {CLONEAREA,SHARED,PRIVATE,COPY};
struct physical_entry {void *address;
ulong size;
};

View File

@ -40,7 +40,7 @@ vpage::vpage(void) : physPage(NULL),backingNode(NULL),protection(none),dirty(fal
// Does the real setup work for making a vpage.
// backing and/or physMem can be NULL/0.
void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state) {
void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state, mmapSharing share) {
// Basic setup from parameters
vpage *clonedPage; // This is the page that this page is to be the clone of...
error ("vpage::setup: start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0));
@ -53,21 +53,35 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
end_address=start+PAGE_SIZE-1;
// Set up the backing store. If one is specified, use it; if not, get a swap file page.
if (backingNode) {
clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found
if (clonedPage) {
physPage=clonedPage->physPage;
protection=(protection<=readable)?protection: copyOnWrite;
if (clonedPage->getProtection()<=readable)
clonedPage->setProtection(copyOnWrite);
if (backingNode) { // This is an mmapped file (or a cloned area)
switch (share) {
case CLONE: // This is a cloned area
case SHARED: // This is a shared mmap
clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found
if (clonedPage) physPage=clonedPage->physPage;
break;
case PRIVATE: // This is a one way share - we get others changes (until we make a change) but no one gets our changes
clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found
if (clonedPage) physPage=clonedPage->physPage;
protection=(protection<=readable)?protection: copyOnWrite;
break;
case COPY: // This is not shared - get a fresh page and fresh swap file space and copy the original page
physPage=vmBlock->pageMan->getPage();
clonedPage=vmBlock->vnodeMan->findVnode(*backing); // Find out if the page we are copying is in memory already...
if (clonedPage && clonedPage->physPage) // If it is in memory, copy its values
memcpy((void *)(physPage->getAddress()),(void *)(clonedPage->physPage->getAddress()),PAGE_SIZE);
else
refresh(); // otherwise, get a copy from disk...
backingNode=&(vmBlock->swapMan->findNode()); // Now get swap space (since we don't want to be backed by the file...
clonedPage=vmBlock->vnodeMan->addVnode(backingNode,*this); // Add this vnode to the vnode keeper
break;
}
}
else { // Going to swap file.
backingNode=&(vmBlock->swapMan->findNode());
clonedPage=vmBlock->vnodeMan->addVnode(backingNode,*this); // Use the pointer version which will use this one. Should always return NULL
}
// If there is no physical page already and we can't wait to get one, then get one now
// If there is no physical page already and we can't wait to get one, then get one now
if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) {
physPage=vmBlock->pageMan->getPage();
error ("vpage::setup, state = %d, allocated page %x\n",state,physPage);
@ -76,6 +90,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
if (physPage)
atomic_add(&(physPage->count),1);
}
error ("vpage::setup: ended : start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0));
}

View File

@ -21,7 +21,7 @@ class vpage : public node
vpage(void);
vpage(unsigned long address) {start_address=address-address%PAGE_SIZE;end_address=start_address+PAGE_SIZE-1;} // Only for lookups
// Setup should now only be called by the vpage manager...
void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0.
void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state, mmapSharing share=CLONEAREA); // backing and/or physMem can be NULL/0.
void cleanup(void);
// Mutators