aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/process.c
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-02-14 22:37:35 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-02-14 22:37:35 +0100
commit73cf3eddd480f2bd7e987c58da82c243861a5314 (patch)
treeb6cf499e261cd2e4d87bd08b499ebdf1b97adf90 /src/kernel/user/process.c
parentfcc321d0ef1771edff61a986df62d2cda2d7485e (diff)
downloadkogata-73cf3eddd480f2bd7e987c58da82c243861a5314.tar.gz
kogata-73cf3eddd480f2bd7e987c58da82c243861a5314.zip
Many things :
- fix context switching (it actually worked only because of optimizations!) - complete mchmap implementation - adjust elf parser to load binaries correctly even without FM_MMAP
Diffstat (limited to 'src/kernel/user/process.c')
-rw-r--r--src/kernel/user/process.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index a4383f7..72042d9 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -177,6 +177,10 @@ bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_
if ((uint32_t)addr & (~PAGE_MASK)) return false;
+ int fmode = file_get_mode(h);
+ if (!(fmode & FM_MMAP) || !(fmode & FM_READ)) return false;
+ if ((mode & MM_WRITE) && !(fmode & FM_WRITE)) return false;
+
user_region_t *r = (user_region_t*)malloc(sizeof(user_region_t));
if (r == 0) return false;
@@ -212,6 +216,24 @@ bool mchmap(process_t *proc, void* addr, int mode) {
if (r == 0) return false;
r->mode = mode;
+
+ // change mode on already mapped pages
+ pagedir_t *save_pd = get_current_pagedir();
+ switch_pagedir(proc->pd);
+ for (void* it = r->addr; it < r->addr + r->size; r += PAGE_SIZE) {
+ uint32_t ent = pd_get_entry(it);
+ uint32_t frame = pd_get_frame(it);
+
+ if (ent & PTE_PRESENT) {
+ bool can_w = (ent & PTE_RW) != 0;
+ bool should_w = (mode & MM_WRITE) != 0;
+ if (can_w != should_w) {
+ pd_map_page(it, frame, should_w);
+ }
+ }
+ }
+ switch_pagedir(save_pd);
+
return true;
}
@@ -230,12 +252,27 @@ bool munmap(process_t *proc, void* addr) {
}
}
- // TODO : write modified pages back to file!
- // TODO : unmap mapped page for region...
+ btree_remove_v(proc->regions_idx, r->addr, r);
+
+ // Unmap that stuff
+ pagedir_t *save_pd = get_current_pagedir();
+ switch_pagedir(proc->pd);
+ for (void* it = r->addr; it < r->addr + r->size; r += PAGE_SIZE) {
+ uint32_t ent = pd_get_entry(it);
+ uint32_t frame = pd_get_frame(it);
+
+ if (ent & PTE_PRESENT) {
+ if ((ent & PTE_DIRTY) && (r->mode & MM_WRITE) && r->file != 0) {
+ file_write(r->file, it - r->addr + r->file_offset, PAGE_SIZE, it);
+ }
+ pd_unmap_page(it);
+ frame_free(frame, 1);
+ }
+ }
+ switch_pagedir(save_pd);
if (r->file != 0) unref_file(r->file);
- btree_remove_v(proc->regions_idx, r->addr, r);
free(r);
return true;