lib: Add epoch-based SMR

This commit is contained in:
2026-11-01 21:06:48 +01:00
parent 3ff068e944
commit 7c04530681
24 changed files with 1059 additions and 84 deletions
+9
View File
@@ -29,6 +29,15 @@ void page_hold(struct page* page) {
atomic_fetch_add(&page->holds, 1, ATOMIC_RELAXED);
}
bool page_try_hold(struct page* page) {
size_t holds = atomic_load(&page->holds, ATOMIC_RELAXED);
while (holds) {
if (atomic_compare_exchange_weak(&page->holds, &holds, holds + 1, ATOMIC_ACQUIRE, ATOMIC_RELAXED))
return true;
}
return false;
}
void page_unhold(struct page* page) {
if (atomic_fetch_sub(&page->holds, 1, ATOMIC_RELEASE) != 1)
return;
+1 -1
View File
@@ -445,7 +445,7 @@ static errno_t fault_anon(
errno_t status = anon_new(anon->page, &copy);
if (status)
return status;
*radix_slot(&m->amap->anons, slot) = copy;
radix_replace(&m->amap->anons, slot, copy);
anon_unref(anon);
anon = copy;
writable = true;
+25
View File
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: ISC
#include <zinnia/alloc.h>
#include <zinnia/epoch.h>
#include <zinnia/errno.h>
#include <zinnia/print.h>
#include <zinnia/utils.h>
@@ -143,10 +144,34 @@ static errno_t fill(struct vmo* vmo, uint64_t index, enum vmo_access access, str
return 0;
}
static struct page* lookup_fast(struct vmo* vmo, uint64_t index) {
epoch_enter();
struct page* page = radix_lookup(&vmo->pages, index);
if (page && !page_try_hold(page))
page = nullptr;
const bool valid =
page && radix_lookup(&vmo->pages, index) == page && !(atomic_load(&page->flags, ATOMIC_ACQUIRE) & PAGE_BUSY);
epoch_exit();
if (page && !valid) {
page_unhold(page);
return nullptr;
}
return page;
}
errno_t vmo_get_page(struct vmo* vmo, uint64_t index, enum vmo_access access, struct page** out) {
if (vmo->pager->lookup)
return ENOTSUP;
if (access == VMO_READ) {
struct page* page = lookup_fast(vmo, index);
if (page) {
*out = page;
return 0;
}
}
mutex_lock(&vmo->lock);
while (true) {
struct page* page = radix_lookup(&vmo->pages, index);