* 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);
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_specific_page(addr_t page_num, int state);
vm_page *vm_page_at_index(int32 index);
vm_page *vm_lookup_page(addr_t pageNumber);
+3 -2
View File
@@ -105,8 +105,9 @@ typedef struct vm_page {
uint8 type : 2;
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;
int8 usage_count;
-1
View File
@@ -4178,7 +4178,6 @@ vm_soft_fault(addr_t originalAddress, bool isWrite, bool isUser)
dummyPage.cache = NULL;
dummyPage.state = PAGE_STATE_INACTIVE;
dummyPage.type = PAGE_TYPE_DUMMY;
dummyPage.busy_writing = isWrite;
dummyPage.wired_count = 0;
#ifdef DEBUG_PAGE_CACHE_TRANSITIONS
dummyPage.debug_flags = 0;
-2
View File
@@ -635,8 +635,6 @@ if (consumer->virtual_base == 0x11000)
page->debug_flags |= 0x1;
if (consumerPage->type == PAGE_TYPE_DUMMY)
page->debug_flags |= 0x2;
if (!consumerPage->busy_writing)
page->debug_flags |= 0x4;
page->collided_page = consumerPage;
consumerPage->collided_page = page;
#endif // DEBUG_PAGE_CACHE_TRANSITIONS
+72 -113
View File
@@ -916,29 +916,27 @@ vm_mark_page_inuse(addr_t page)
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;
vm_page *page;
addr_t i;
TRACE(("vm_mark_page_range_inuse: start 0x%lx, len 0x%lx\n",
startPage, length));
TRACE(("vm_mark_page_range_inuse: start 0x%lx, len 0x%lx\n", start_page, length));
if (sPhysicalPageOffset > start_page) {
dprintf("vm_mark_page_range_inuse: start page %ld is before free list\n", start_page);
if (sPhysicalPageOffset > startPage) {
TRACE(("vm_mark_page_range_inuse: start page %ld is before free list\n",
startPage));
return B_BAD_VALUE;
}
start_page -= sPhysicalPageOffset;
if (start_page + length > sNumPages) {
dprintf("vm_mark_page_range_inuse: range would extend past free list\n");
startPage -= sPhysicalPageOffset;
if (startPage + length > sNumPages) {
TRACE(("vm_mark_page_range_inuse: range would extend past free list\n"));
return B_BAD_VALUE;
}
state = disable_interrupts();
cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock);
for (i = 0; i < length; i++) {
page = &sPages[start_page + i];
for (addr_t i = 0; i < length; i++) {
vm_page *page = &sPages[startPage + i];
switch (page->state) {
case PAGE_STATE_FREE:
case PAGE_STATE_CLEAR:
@@ -953,7 +951,9 @@ vm_mark_page_range_inuse(addr_t start_page, addr_t length)
case PAGE_STATE_UNUSED:
default:
// 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_allocate_specific_page(addr_t page_num, int page_state)
vm_page_allocate_page(int pageState)
{
vm_page *p;
int old_page_state = PAGE_STATE_BUSY;
int state;
page_queue *queue;
page_queue *otherQueue;
state = disable_interrupts();
acquire_spinlock(&sPageLock);
p = vm_lookup_page(page_num);
if (p == NULL)
goto out;
switch (p->state) {
switch (pageState) {
case PAGE_STATE_FREE:
remove_page_from_queue(&sFreePageQueue, p);
queue = &sFreePageQueue;
otherQueue = &sClearPageQueue;
break;
case PAGE_STATE_CLEAR:
remove_page_from_queue(&sClearPageQueue, p);
break;
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;
queue = &sClearPageQueue;
otherQueue = &sFreePageQueue;
break;
default:
return NULL; // invalid
}
state = disable_interrupts();
cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock);
p = dequeue_page(q);
if (p == NULL) {
vm_page *page = dequeue_page(queue);
if (page == NULL) {
#ifdef DEBUG
if (q->count != 0)
panic("queue %p corrupted, count = %d\n", q, q->count);
if (queue->count != 0)
panic("queue %p corrupted, count = %d\n", queue, queue->count);
#endif
// if the primary queue was empty, grap the page from the
// secondary queue
p = dequeue_page(q_other);
if (p == NULL) {
page = dequeue_page(otherQueue);
if (page == NULL) {
#ifdef DEBUG
if (q_other->count != 0)
panic("other queue %p corrupted, count = %d\n", q_other, q_other->count);
if (otherQueue->count != 0) {
panic("other queue %p corrupted, count = %d\n", otherQueue,
otherQueue->count);
}
#endif
// ToDo: issue "someone" to free up some pages for us, and go into wait state until that's done
panic("vm_allocate_page: out of memory! page state = %d\n", page_state);
// ToDo: issue "someone" to free up some pages for us, and go into
// wait state until that's done
panic("vm_allocate_page: out of memory! page state = %d\n",
pageState);
}
}
if (p->cache != NULL)
panic("supposed to be free page %p has cache\n", p);
if (page->cache != NULL)
panic("supposed to be free page %p has cache\n", page);
old_page_state = p->state;
p->state = PAGE_STATE_BUSY;
int oldPageState = page->state;
page->state = PAGE_STATE_BUSY;
enqueue_page(&sActivePageQueue, p);
enqueue_page(&sActivePageQueue, page);
release_spinlock(&sPageLock);
restore_interrupts(state);
// 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)
clear_page(p->physical_page_number * B_PAGE_SIZE);
if (pageState == PAGE_STATE_CLEAR && oldPageState != PAGE_STATE_CLEAR)
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_allocate_page_run(int page_state, addr_t len)
vm_page_allocate_page_run(int pageState, addr_t length)
{
unsigned int start;
unsigned int i;
vm_page *first_page = NULL;
int state;
vm_page *firstPage = NULL;
uint32 start = 0;
start = 0;
state = disable_interrupts();
cpu_status state = disable_interrupts();
acquire_spinlock(&sPageLock);
for (;;) {
bool foundit = true;
if (start + len > sNumPages)
bool foundRun = true;
if (start + length > sNumPages)
break;
for (i = 0; i < len; i++) {
uint32 i;
for (i = 0; i < length; i++) {
if (sPages[start + i].state != PAGE_STATE_FREE
&& sPages[start + i].state != PAGE_STATE_CLEAR) {
foundit = false;
foundRun = false;
i++;
break;
}
}
if (foundit) {
if (foundRun) {
// 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);
}
first_page = &sPages[start];
firstPage = &sPages[start];
break;
} else {
start += i;
@@ -1142,7 +1094,16 @@ vm_page_allocate_page_run(int page_state, addr_t len)
release_spinlock(&sPageLock);
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
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();
acquire_spinlock(&sPageLock);
status = set_page_state_nolock(page, page_state);
status_t status = set_page_state_nolock(page, pageState);
release_spinlock(&sPageLock);
restore_interrupts(state);