use atomic operations for manipulating page.count
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user