* 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:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user