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:
@@ -53,7 +53,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,void * req,int page
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the really interesting part of creating an area
|
// 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",
|
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);
|
inName,pageCount,address,type,inState,protect,inFinalWrite,fd,offset,originalArea);
|
||||||
vpage *newPage;
|
vpage *newPage;
|
||||||
@@ -78,7 +78,7 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr
|
|||||||
newVnode.fd=fd;
|
newVnode.fd=fd;
|
||||||
newVnode.offset=offset;
|
newVnode.offset=offset;
|
||||||
// vmBlock->vnodeManager->addVNode(newVnode,newPage);
|
// 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
|
else
|
||||||
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t 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);
|
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) {
|
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect) {
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class area : public node
|
|||||||
area(void);
|
area(void);
|
||||||
void setup(areaManager *myManager);
|
void setup(areaManager *myManager);
|
||||||
void freeArea(void);
|
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 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);
|
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 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);
|
status_t cloneArea(area *area, char *inName, void **address, addressSpec type,pageState inState,protectType protect);
|
||||||
unsigned long mapAddressSpecToAddress(addressSpec type,void *requested,int pageCount);
|
unsigned long mapAddressSpecToAddress(addressSpec type,void *requested,int pageCount);
|
||||||
|
|||||||
@@ -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");
|
strcpy( name,"mmap - need to include fileName");
|
||||||
|
|
||||||
addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY);
|
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);
|
//error ("flags = %x, anon = %x\n",flags,MAP_ANON);
|
||||||
lock();
|
lock();
|
||||||
if (flags & MAP_ANON) {
|
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;
|
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;
|
area *newArea = new (vmBlock->areaPool->get()) area;
|
||||||
newArea->setup(this);
|
newArea->setup(this);
|
||||||
//error ("area = %x, start = %x\n",newArea, newArea->getStartAddress());
|
//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);
|
atomic_add(&nextAreaID,1);
|
||||||
newArea->setAreaID(nextAreaID);
|
newArea->setAreaID(nextAreaID);
|
||||||
addArea(newArea);
|
addArea(newArea);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM};
|
|||||||
#define B_DMA_IO 0x00000001
|
#define B_DMA_IO 0x00000001
|
||||||
#define B_READ_DEVICE 0x00000002
|
#define B_READ_DEVICE 0x00000002
|
||||||
|
|
||||||
|
enum mmapSharing {CLONEAREA,SHARED,PRIVATE,COPY};
|
||||||
|
|
||||||
struct physical_entry {void *address;
|
struct physical_entry {void *address;
|
||||||
ulong size;
|
ulong size;
|
||||||
};
|
};
|
||||||
|
|||||||
+25
-10
@@ -40,7 +40,7 @@ vpage::vpage(void) : physPage(NULL),backingNode(NULL),protection(none),dirty(fal
|
|||||||
|
|
||||||
// Does the real setup work for making a vpage.
|
// Does the real setup work for making a vpage.
|
||||||
// backing and/or physMem can be NULL/0.
|
// 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
|
// Basic setup from parameters
|
||||||
vpage *clonedPage; // This is the page that this page is to be the clone of...
|
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));
|
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;
|
end_address=start+PAGE_SIZE-1;
|
||||||
|
|
||||||
// Set up the backing store. If one is specified, use it; if not, get a swap file page.
|
// Set up the backing store. If one is specified, use it; if not, get a swap file page.
|
||||||
if (backingNode) {
|
if (backingNode) { // This is an mmapped file (or a cloned area)
|
||||||
clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found
|
switch (share) {
|
||||||
if (clonedPage) {
|
case CLONE: // This is a cloned area
|
||||||
physPage=clonedPage->physPage;
|
case SHARED: // This is a shared mmap
|
||||||
protection=(protection<=readable)?protection: copyOnWrite;
|
clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found
|
||||||
if (clonedPage->getProtection()<=readable)
|
if (clonedPage) physPage=clonedPage->physPage;
|
||||||
clonedPage->setProtection(copyOnWrite);
|
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.
|
else { // Going to swap file.
|
||||||
backingNode=&(vmBlock->swapMan->findNode());
|
backingNode=&(vmBlock->swapMan->findNode());
|
||||||
clonedPage=vmBlock->vnodeMan->addVnode(backingNode,*this); // Use the pointer version which will use this one. Should always return NULL
|
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)) {
|
if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) {
|
||||||
physPage=vmBlock->pageMan->getPage();
|
physPage=vmBlock->pageMan->getPage();
|
||||||
error ("vpage::setup, state = %d, allocated page %x\n",state,physPage);
|
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)
|
if (physPage)
|
||||||
atomic_add(&(physPage->count),1);
|
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));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class vpage : public node
|
|||||||
vpage(void);
|
vpage(void);
|
||||||
vpage(unsigned long address) {start_address=address-address%PAGE_SIZE;end_address=start_address+PAGE_SIZE-1;} // Only for lookups
|
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...
|
// 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);
|
void cleanup(void);
|
||||||
|
|
||||||
// Mutators
|
// Mutators
|
||||||
|
|||||||
Reference in New Issue
Block a user