diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-12 15:52:25 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-12 15:52:25 +0300 |
| commit | 1ea7d9dec1b460ab76dfd6270596c8138c9c2b40 (patch) | |
| tree | 0e8799fe0d7a653e864bd90c65a29e4012026f71 /common/vmem.c | |
| parent | 42a1e087ce99f07b48aaea5552f8e1ce5219d228 (diff) | |
| download | kmi-1ea7d9dec1b460ab76dfd6270596c8138c9c2b40.tar.gz kmi-1ea7d9dec1b460ab76dfd6270596c8138c9c2b40.zip | |
initial workings of shared memory
+ Should document this better but essentially a server requests a shared
buffer, and chan then share this buffer to a thread. Freeing the
buffer is done through normal means. MR_SHARED is used for buffers
that are shared, and MR_OWNED tells whoever is freeing that region
that it is allowed to free the physical memory behind the shared
buffer.
Diffstat (limited to 'common/vmem.c')
| -rw-r--r-- | common/vmem.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/common/vmem.c b/common/vmem.c index d0d40ec..89e1140 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -1,4 +1,5 @@ #include <apos/mem_regions.h> +#include <apos/bits.h> #include <apos/vmem.h> #include <arch/vmem.h> @@ -9,16 +10,51 @@ stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top) vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) { - vm_t v = alloc_region(&t->sp_r, size, &size); + vm_t v = alloc_region(&t->sp_r, size, &size, flags); return map_allocd_region(t->b_r, v, size, flags); } vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) { - vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size); + vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size, flags); return map_allocd_region(t->b_r, v, size, flags); } +/* free_shared_uvmem shouldn't be needed, likely to work with free_uvmem */ +vm_t alloc_shared_uvmem(struct tcb *t, size_t size, + vmflags_t flags) +{ + /* TODO: proper error handling */ + vm_t v = alloc_region(&t->sp_r, size, &size, + flags | MR_SHARED | MR_OWNED); + return map_shared_region(t->b_r, v, size, flags); +} + +vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags) +{ + struct mem_region *m = find_used_region(&t1->sp_r, va); + if (!m) + return 0; + + if (!__is_set(m->flags, MR_OWNED)) + return 0; + + /* loop over all pages in this region */ + size_t size = m->end - m->start; + size_t pages = __pages(size); + vm_t v = alloc_region(&t2->sp_r, size, &size, flags | MR_SHARED); + /* a for each page could be cool? */ + vm_t runner = v; + for (; pages; --pages) { + pm_t paddr; + stat_vpage(t1->b_r, v, &paddr, 0, 0); + map_vpage(t2->b_r, paddr, runner, flags, MM_O0); + runner += __o_size(MM_O0); + } + + return v; +} + stat_t free_uvmem(struct tcb *t, vm_t va) { struct mem_region *m = find_used_region(&t->sp_r, va); @@ -27,8 +63,9 @@ stat_t free_uvmem(struct tcb *t, vm_t va) pm_t pa = __addr(m->end - m->start); + vmflags_t flags = m->flags; free_region(&t->sp_r, va); - unmap_freed_region(t->b_r, va, pa); + unmap_freed_region(t->b_r, va, pa, flags); return 0; } @@ -43,6 +80,17 @@ stat_t alloc_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, return OK; } +stat_t alloc_shared_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, + vmflags_t flags, enum mm_order order) +{ + if (order != MM_O0) + return REGION_TRY_AGAIN; + + *offset = alloc_page(MM_O0, *offset); + map_vpage(b, *offset, vaddr, flags, order); + return OK; +} + stat_t free_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order) { @@ -56,6 +104,8 @@ stat_t free_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, return REGION_TRY_AGAIN; unmap_vpage(b, vaddr); - free_page(order, paddr); + /* don't free shared pages, unless they're owned */ + if (!__is_set(flags, MR_SHARED) || __is_set(flags, MR_OWNED)) + free_page(order, paddr); return OK; } |
