* Removed unused vm_page::busy_{reading|writing} fields.

* Fixed vm_page_allocate_page_run(): it did not take the pageState into account,
  and would therefore return uninitialized memory (ie. B_CONTIGUOUS areas would
  contain garbage).
  Now, it stores if a page is cleared in a new vm_page::is_cleared field.
* Some cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22306 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-09-25 15:04:29 +00:00
parent 282c8843cd
commit 8c657126cd
5 changed files with 75 additions and 119 deletions
-1
View File
@@ -37,7 +37,6 @@ status_t vm_page_write_modified(vm_cache *cache, bool fsReenter);
vm_page *vm_page_allocate_page(int state); vm_page *vm_page_allocate_page(int state);
status_t vm_page_allocate_pages(int pageState, vm_page **pages, uint32 numPages); status_t vm_page_allocate_pages(int pageState, vm_page **pages, uint32 numPages);
vm_page *vm_page_allocate_page_run(int state, addr_t length); vm_page *vm_page_allocate_page_run(int state, addr_t length);
vm_page *vm_page_allocate_specific_page(addr_t page_num, int state);
vm_page *vm_page_at_index(int32 index); vm_page *vm_page_at_index(int32 index);
vm_page *vm_lookup_page(addr_t pageNumber); vm_page *vm_lookup_page(addr_t pageNumber);
+3 -2
View File
@@ -105,8 +105,9 @@ typedef struct vm_page {
uint8 type : 2; uint8 type : 2;
uint8 state : 3; uint8 state : 3;
uint8 busy_reading : 1;
uint8 busy_writing : 1; uint8 is_cleared : 1;
// is currently only used in vm_page_allocate_page_run()
uint16 wired_count; uint16 wired_count;
int8 usage_count; int8 usage_count;
-1
View File
@@ -4178,7 +4178,6 @@ vm_soft_fault(addr_t originalAddress, bool isWrite, bool isUser)
dummyPage.cache = NULL; dummyPage.cache = NULL;
dummyPage.state = PAGE_STATE_INACTIVE; dummyPage.state = PAGE_STATE_INACTIVE;
dummyPage.type = PAGE_TYPE_DUMMY; dummyPage.type = PAGE_TYPE_DUMMY;
dummyPage.busy_writing = isWrite;
dummyPage.wired_count = 0; dummyPage.wired_count = 0;
#ifdef DEBUG_PAGE_CACHE_TRANSITIONS #ifdef DEBUG_PAGE_CACHE_TRANSITIONS
dummyPage.debug_flags = 0; dummyPage.debug_flags = 0;
-2
View File
@@ -635,8 +635,6 @@ if (consumer->virtual_base == 0x11000)
page->debug_flags |= 0x1; page->debug_flags |= 0x1;
if (consumerPage->type == PAGE_TYPE_DUMMY) if (consumerPage->type == PAGE_TYPE_DUMMY)
page->debug_flags |= 0x2; page->debug_flags |= 0x2;
if (!consumerPage->busy_writing)
page->debug_flags |= 0x4;
page->collided_page = consumerPage; page->collided_page = consumerPage;
consumerPage->collided_page = page; consumerPage->collided_page = page;
#endif // DEBUG_PAGE_CACHE_TRANSITIONS #endif // DEBUG_PAGE_CACHE_TRANSITIONS
+72 -113
View File
@@ -916,29 +916,27 @@ vm_mark_page_inuse(addr_t page)
status_t status_t
vm_mark_page_range_inuse(addr_t start_page, addr_t length) vm_mark_page_range_inuse(addr_t startPage, addr_t length)
{ {
cpu_status state; TRACE(("vm_mark_page_range_inuse: start 0x%lx, len 0x%lx\n",
vm_page *page; startPage, length));
addr_t i;
TRACE(("vm_mark_page_range_inuse: start 0x%lx, len 0x%lx\n", start_page, length)); if (sPhysicalPageOffset > startPage) {
TRACE(("vm_mark_page_range_inuse: start page %ld is before free list\n",
if (sPhysicalPageOffset > start_page) { startPage));
dprintf("vm_mark_page_range_inuse: start page %ld is before free list\n", start_page);
return B_BAD_VALUE; return B_BAD_VALUE;
} }
start_page -= sPhysicalPageOffset; startPage -= sPhysicalPageOffset;
if (start_page + length > sNumPages) { if (startPage + length > sNumPages) {
dprintf("vm_mark_page_range_inuse: range would extend past free list\n"); TRACE(("vm_mark_page_range_inuse: range would extend past free list\n"));
return B_BAD_VALUE; return B_BAD_VALUE;
} }
state = disable_interrupts(); cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock); acquire_spinlock(&sPageLock);
for (i = 0; i < length; i++) { for (addr_t i = 0; i < length; i++) {
page = &sPages[start_page + i]; vm_page *page = &sPages[startPage + i];
switch (page->state) { switch (page->state) {
case PAGE_STATE_FREE: case PAGE_STATE_FREE:
case PAGE_STATE_CLEAR: case PAGE_STATE_CLEAR:
@@ -953,7 +951,9 @@ vm_mark_page_range_inuse(addr_t start_page, addr_t length)
case PAGE_STATE_UNUSED: case PAGE_STATE_UNUSED:
default: default:
// uh // uh
dprintf("vm_mark_page_range_inuse: page 0x%lx in non-free state %d!\n", start_page + i, page->state); dprintf("vm_mark_page_range_inuse: page 0x%lx in non-free state %d!\n",
startPage + i, page->state);
break;
} }
} }
@@ -965,114 +965,67 @@ vm_mark_page_range_inuse(addr_t start_page, addr_t length)
vm_page * vm_page *
vm_page_allocate_specific_page(addr_t page_num, int page_state) vm_page_allocate_page(int pageState)
{ {
vm_page *p; page_queue *queue;
int old_page_state = PAGE_STATE_BUSY; page_queue *otherQueue;
int state;
state = disable_interrupts(); switch (pageState) {
acquire_spinlock(&sPageLock);
p = vm_lookup_page(page_num);
if (p == NULL)
goto out;
switch (p->state) {
case PAGE_STATE_FREE: case PAGE_STATE_FREE:
remove_page_from_queue(&sFreePageQueue, p); queue = &sFreePageQueue;
otherQueue = &sClearPageQueue;
break; break;
case PAGE_STATE_CLEAR: case PAGE_STATE_CLEAR:
remove_page_from_queue(&sClearPageQueue, p); queue = &sClearPageQueue;
break; otherQueue = &sFreePageQueue;
case PAGE_STATE_UNUSED:
break;
default:
// we can't allocate this page
p = NULL;
}
if (p == NULL)
goto out;
old_page_state = p->state;
p->state = PAGE_STATE_BUSY;
if (old_page_state != PAGE_STATE_UNUSED)
enqueue_page(&sActivePageQueue, p);
out:
release_spinlock(&sPageLock);
restore_interrupts(state);
if (p != NULL && page_state == PAGE_STATE_CLEAR
&& (old_page_state == PAGE_STATE_FREE || old_page_state == PAGE_STATE_UNUSED))
clear_page(p->physical_page_number * B_PAGE_SIZE);
return p;
}
vm_page *
vm_page_allocate_page(int page_state)
{
vm_page *p;
page_queue *q;
page_queue *q_other;
int state;
int old_page_state;
switch (page_state) {
case PAGE_STATE_FREE:
q = &sFreePageQueue;
q_other = &sClearPageQueue;
break;
case PAGE_STATE_CLEAR:
q = &sClearPageQueue;
q_other = &sFreePageQueue;
break; break;
default: default:
return NULL; // invalid return NULL; // invalid
} }
state = disable_interrupts(); cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock); acquire_spinlock(&sPageLock);
p = dequeue_page(q); vm_page *page = dequeue_page(queue);
if (p == NULL) { if (page == NULL) {
#ifdef DEBUG #ifdef DEBUG
if (q->count != 0) if (queue->count != 0)
panic("queue %p corrupted, count = %d\n", q, q->count); panic("queue %p corrupted, count = %d\n", queue, queue->count);
#endif #endif
// if the primary queue was empty, grap the page from the // if the primary queue was empty, grap the page from the
// secondary queue // secondary queue
p = dequeue_page(q_other); page = dequeue_page(otherQueue);
if (p == NULL) { if (page == NULL) {
#ifdef DEBUG #ifdef DEBUG
if (q_other->count != 0) if (otherQueue->count != 0) {
panic("other queue %p corrupted, count = %d\n", q_other, q_other->count); panic("other queue %p corrupted, count = %d\n", otherQueue,
otherQueue->count);
}
#endif #endif
// ToDo: issue "someone" to free up some pages for us, and go into wait state until that's done // ToDo: issue "someone" to free up some pages for us, and go into
panic("vm_allocate_page: out of memory! page state = %d\n", page_state); // wait state until that's done
panic("vm_allocate_page: out of memory! page state = %d\n",
pageState);
} }
} }
if (p->cache != NULL) if (page->cache != NULL)
panic("supposed to be free page %p has cache\n", p); panic("supposed to be free page %p has cache\n", page);
old_page_state = p->state; int oldPageState = page->state;
p->state = PAGE_STATE_BUSY; page->state = PAGE_STATE_BUSY;
enqueue_page(&sActivePageQueue, p); enqueue_page(&sActivePageQueue, page);
release_spinlock(&sPageLock); release_spinlock(&sPageLock);
restore_interrupts(state); restore_interrupts(state);
// if needed take the page from the free queue and zero it out // if needed take the page from the free queue and zero it out
if (page_state == PAGE_STATE_CLEAR && old_page_state == PAGE_STATE_FREE) if (pageState == PAGE_STATE_CLEAR && oldPageState != PAGE_STATE_CLEAR)
clear_page(p->physical_page_number * B_PAGE_SIZE); clear_page(page->physical_page_number * B_PAGE_SIZE);
return p; return page;
} }
@@ -1103,37 +1056,36 @@ vm_page_allocate_pages(int pageState, vm_page **pages, uint32 numPages)
vm_page * vm_page *
vm_page_allocate_page_run(int page_state, addr_t len) vm_page_allocate_page_run(int pageState, addr_t length)
{ {
unsigned int start; vm_page *firstPage = NULL;
unsigned int i; uint32 start = 0;
vm_page *first_page = NULL;
int state;
start = 0; cpu_status state = disable_interrupts();
state = disable_interrupts();
acquire_spinlock(&sPageLock); acquire_spinlock(&sPageLock);
for (;;) { for (;;) {
bool foundit = true; bool foundRun = true;
if (start + len > sNumPages) if (start + length > sNumPages)
break; break;
for (i = 0; i < len; i++) { uint32 i;
for (i = 0; i < length; i++) {
if (sPages[start + i].state != PAGE_STATE_FREE if (sPages[start + i].state != PAGE_STATE_FREE
&& sPages[start + i].state != PAGE_STATE_CLEAR) { && sPages[start + i].state != PAGE_STATE_CLEAR) {
foundit = false; foundRun = false;
i++; i++;
break; break;
} }
} }
if (foundit) { if (foundRun) {
// pull the pages out of the appropriate queues // pull the pages out of the appropriate queues
for (i = 0; i < len; i++) { for (i = 0; i < length; i++) {
sPages[start + i].is_cleared
= sPages[start + i].state == PAGE_STATE_CLEAR;
set_page_state_nolock(&sPages[start + i], PAGE_STATE_BUSY); set_page_state_nolock(&sPages[start + i], PAGE_STATE_BUSY);
} }
first_page = &sPages[start]; firstPage = &sPages[start];
break; break;
} else { } else {
start += i; start += i;
@@ -1142,7 +1094,16 @@ vm_page_allocate_page_run(int page_state, addr_t len)
release_spinlock(&sPageLock); release_spinlock(&sPageLock);
restore_interrupts(state); restore_interrupts(state);
return first_page; if (firstPage != NULL && pageState == PAGE_STATE_CLEAR) {
for (uint32 i = 0; i < length; i++) {
if (!sPages[start + i].is_cleared) {
clear_page(sPages[start + i].physical_page_number
* B_PAGE_SIZE);
}
}
}
return firstPage;
} }
@@ -1168,14 +1129,12 @@ vm_lookup_page(addr_t pageNumber)
status_t status_t
vm_page_set_state(vm_page *page, int page_state) vm_page_set_state(vm_page *page, int pageState)
{ {
status_t status;
cpu_status state = disable_interrupts(); cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock); acquire_spinlock(&sPageLock);
status = set_page_state_nolock(page, page_state); status_t status = set_page_state_nolock(page, pageState);
release_spinlock(&sPageLock); release_spinlock(&sPageLock);
restore_interrupts(state); restore_interrupts(state);