use atomic operations for manipulating page.count

This commit is contained in:
NAKAMURA Gou
2014-05-07 18:16:13 +09:00
parent 604d1da50f
commit 29c7d40005
3 changed files with 20 additions and 10 deletions

View File

@@ -253,23 +253,25 @@ static void fileobj_release(struct memobj *memobj)
/* zap page_list */ /* zap page_list */
for (;;) { for (;;) {
struct page *page; struct page *page;
int count;
page = page_list_first(obj); page = page_list_first(obj);
if (!page) { if (!page) {
break; break;
} }
page_list_remove(obj, page); page_list_remove(obj, page);
count = ihk_atomic_sub_return(1, &page->count);
if (!((page->mode == PM_WILL_PAGEIO) if (!((page->mode == PM_WILL_PAGEIO)
|| (page->mode == PM_DONE_PAGEIO) || (page->mode == PM_DONE_PAGEIO)
|| (page->mode == PM_PAGEIO_EOF) || (page->mode == PM_PAGEIO_EOF)
|| (page->mode == PM_PAGEIO_ERROR) || (page->mode == PM_PAGEIO_ERROR)
|| ((page->mode == PM_MAPPED) || ((page->mode == PM_MAPPED)
&& (page->count <= 0)))) { && (count <= 0)))) {
kprintf("fileobj_release(%p %lx): " kprintf("fileobj_release(%p %lx): "
"mode %x, count %d, off %lx\n", "mode %x, count %d, off %lx\n",
obj, obj->handle, page->mode, obj, obj->handle, page->mode,
page->count, page->offset); count, page->offset);
panic("fileobj_release"); panic("fileobj_release");
} }
@@ -429,6 +431,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off, int p2align, uintp
} }
page->mode = PM_WILL_PAGEIO; page->mode = PM_WILL_PAGEIO;
page->offset = off; page->offset = off;
ihk_atomic_set(&page->count, 1);
page_list_insert(obj, page); page_list_insert(obj, page);
} }
@@ -448,7 +451,6 @@ static int fileobj_get_page(struct memobj *memobj, off_t off, int p2align, uintp
} }
else if (page->mode == PM_DONE_PAGEIO) { else if (page->mode == PM_DONE_PAGEIO) {
page->mode = PM_MAPPED; page->mode = PM_MAPPED;
page->count = 0;
} }
else if (page->mode == PM_PAGEIO_EOF) { else if (page->mode == PM_PAGEIO_EOF) {
error = -ERANGE; error = -ERANGE;
@@ -459,7 +461,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off, int p2align, uintp
goto out; goto out;
} }
++page->count; ihk_atomic_inc(&page->count);
error = 0; error = 0;
*physp = page_to_phys(page); *physp = page_to_phys(page);
@@ -486,6 +488,7 @@ static uintptr_t fileobj_copy_page(
void *newkva = NULL; void *newkva = NULL;
uintptr_t newpa = -1; uintptr_t newpa = -1;
void *orgkva; void *orgkva;
int count;
dkprintf("fileobj_copy_page(%p,%lx,%d)\n", memobj, orgpa, p2align); dkprintf("fileobj_copy_page(%p,%lx,%d)\n", memobj, orgpa, p2align);
if (p2align != PAGE_P2ALIGN) { if (p2align != PAGE_P2ALIGN) {
@@ -500,22 +503,24 @@ static uintptr_t fileobj_copy_page(
memobj, orgpa, p2align, orgpage->mode); memobj, orgpa, p2align, orgpage->mode);
panic("fileobj_copy_page:invalid cow page"); panic("fileobj_copy_page:invalid cow page");
} }
if (orgpage->count == 1) { // XXX: private only count = ihk_atomic_read(&orgpage->count);
if (count == 2) { // XXX: private only
list_del(&orgpage->list); list_del(&orgpage->list);
ihk_atomic_dec(&orgpage->count);
orgpage->mode = PM_NONE; orgpage->mode = PM_NONE;
newpa = orgpa; newpa = orgpa;
break; break;
} }
if (orgpage->count <= 0) { if (count <= 0) {
kprintf("fileobj_copy_page(%p,%lx,%d):" kprintf("fileobj_copy_page(%p,%lx,%d):"
"orgpage count corrupted. %x\n", "orgpage count corrupted. %x\n",
memobj, orgpa, p2align, orgpage->count); memobj, orgpa, p2align, count);
panic("fileobj_copy_page:orgpage count corrupted"); panic("fileobj_copy_page:orgpage count corrupted");
} }
if (newkva) { if (newkva) {
orgkva = phys_to_virt(orgpa); orgkva = phys_to_virt(orgpa);
memcpy(newkva, orgkva, pgsize); memcpy(newkva, orgkva, pgsize);
--orgpage->count; ihk_atomic_dec(&orgpage->count);
newpa = virt_to_phys(newkva); newpa = virt_to_phys(newkva);
newkva = NULL; /* avoid ihk_mc_free_pages() */ newkva = NULL; /* avoid ihk_mc_free_pages() */
break; break;

View File

@@ -13,11 +13,13 @@
#ifndef __HEADER_PAGE_H #ifndef __HEADER_PAGE_H
#define __HEADER_PAGE_H #define __HEADER_PAGE_H
#include <ihk/atomic.h>
struct page { struct page {
struct list_head list; struct list_head list;
uint8_t mode; uint8_t mode;
uint8_t padding[3]; uint8_t padding[3];
int32_t count; ihk_atomic_t count;
off_t offset; off_t offset;
}; };

View File

@@ -343,7 +343,7 @@ int page_unmap(struct page *page)
return 1; return 1;
} }
if (--page->count > 0) { if (ihk_atomic_sub_return(1, &page->count) > 0) {
/* other mapping exist */ /* other mapping exist */
dkprintf("page_unmap(%p %x %d): 0\n", dkprintf("page_unmap(%p %x %d): 0\n",
page, page->mode, page->count); page, page->mode, page->count);
@@ -363,6 +363,9 @@ static void page_init(void)
size_t allocsize; size_t allocsize;
size_t allocpages; size_t allocpages;
if (sizeof(ihk_atomic_t) != sizeof(uint32_t)) {
panic("sizeof(ihk_atomic_t) is not 32 bit");
}
npages = (pa_end - pa_start) >> PAGE_SHIFT; npages = (pa_end - pa_start) >> PAGE_SHIFT;
allocsize = sizeof(struct page) * npages; allocsize = sizeof(struct page) * npages;
allocpages = (allocsize + PAGE_SIZE - 1) >> PAGE_SHIFT; allocpages = (allocsize + PAGE_SIZE - 1) >> PAGE_SHIFT;