diff --git a/kernel-src/include/kernel/mm.h b/kernel-src/include/kernel/mm.h index d0ef47bf..4e96d3e5 100644 --- a/kernel-src/include/kernel/mm.h +++ b/kernel-src/include/kernel/mm.h @@ -46,6 +46,8 @@ typedef struct { rbtree_t *ranges; void *start; void *end; + + mm_range_t *last_pagefault; } mm_space_t; typedef struct { diff --git a/kernel-src/mm/mm.c b/kernel-src/mm/mm.c index 126e83c0..28f50d57 100644 --- a/kernel-src/mm/mm.c +++ b/kernel-src/mm/mm.c @@ -273,7 +273,13 @@ bool mm_handle_page_fault(void *addr, bool user, int actions) { } MUTEX_ACQUIRE(&space->lock); - mm_range_t *range = mm_get_range(space, addr); + + // we look at the last page fault range and check if the address is in this range + // this might avoid a more expensive tree lookup + mm_range_t *range = space->last_pagefault; + if (range == NULL || range->start > addr || addr >= range->start + range->size) { + range = mm_get_range(space, addr); + } bool status = false; @@ -282,6 +288,8 @@ bool mm_handle_page_fault(void *addr, bool user, int actions) { goto cleanup; } + space->last_pagefault = range; + // check if valid int invalid_actions = 0; @@ -486,8 +494,12 @@ void *mm_map(void *addr, volatile size_t size, int flags, mmuflags_t mmuflags, v mm_insert_range(space, range); cleanup: - if (ret_addr == NULL && range) + if (ret_addr == NULL && range) { + if (space->last_pagefault == range) + space->last_pagefault = NULL; + mm_free_range(range); + } MUTEX_RELEASE(&space->lock); return ret_addr; diff --git a/kernel-src/mm/range.c b/kernel-src/mm/range.c index 93414034..99404fa9 100644 --- a/kernel-src/mm/range.c +++ b/kernel-src/mm/range.c @@ -122,6 +122,9 @@ void mm_insert_range(mm_space_t *space, mm_range_t *new_range) { if (next_range && ranges_compatible(new_range, next_range)) { new_range->size += next_range->size; + if (space->last_pagefault == next_range) + space->last_pagefault = NULL; + rbtree_remove(&space->ranges, &next_range->rbtree_node); mm_free_range(next_range); if (new_range->flags & MM_RANGE_FLAGS_FILE) { @@ -133,6 +136,9 @@ void mm_insert_range(mm_space_t *space, mm_range_t *new_range) { if (prev_range && ranges_compatible(prev_range, new_range)) { prev_range->size += new_range->size; + if (space->last_pagefault == new_range) + space->last_pagefault = NULL; + rbtree_remove(&space->ranges, &new_range->rbtree_node); mm_free_range(new_range); if (prev_range->flags & MM_RANGE_FLAGS_FILE) { @@ -382,6 +388,9 @@ int mm_change_range(mm_space_t *space, void *address, size_t size, bool free, in // remove or change the flags of the range if (free) { + if (space->last_pagefault == range) + space->last_pagefault = NULL; + rbtree_remove(&space->ranges, &range->rbtree_node); mm_destroy_range(range, 0, range->size, 0); mm_free_range(range); @@ -410,8 +419,9 @@ int mm_change_range(mm_space_t *space, void *address, size_t size, bool free, in } size_t difference = (uintptr_t)top - (uintptr_t)range->start; - if (free) + if (free) { mm_destroy_range(range, 0, difference, 0); + } range->start = (void *)((uintptr_t)range->start + difference); range->size -= difference;