From d0bfc0a5bb80880d8414498408a3637802d0abf1 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Sun, 20 Apr 2014 17:11:35 -0700 Subject: [PATCH] Efficient reallocation of SHM chunks (mostly) --- kernel/ds/list.c | 36 +++++++++++++++++++++++++++++ kernel/include/list.h | 3 +++ kernel/mem/shm.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/kernel/ds/list.c b/kernel/ds/list.c index 24a58464..eb7f8b77 100644 --- a/kernel/ds/list.c +++ b/kernel/ds/list.c @@ -98,6 +98,42 @@ node_t * list_insert_after(list_t * list, node_t * before, void * item) { return node; } +void list_append_before(list_t * list, node_t * after, node_t * node) { + assert(!(node->next || node->prev) && "Node is already in a list."); + node->owner = list; + if (!list->length) { + list_append(list, node); + return; + } + if (after == NULL) { + node->next = NULL; + node->prev = list->tail; + list->tail->next = node; + list->tail = node; + list->length++; + return; + } + if (after == list->head) { + list->head = node; + } else { + after->prev->next = node; + node->prev = after->prev; + } + node->next = after; + after->prev = node; + list->length++; +} + +node_t * list_insert_before(list_t * list, node_t * after, void * item) { + node_t * node = malloc(sizeof(node_t)); + node->value = item; + node->next = NULL; + node->prev = NULL; + node->owner = NULL; + list_append_before(list, after, node); + return node; +} + list_t * list_create(void) { /* Create a fresh list */ list_t * out = malloc(sizeof(list_t)); diff --git a/kernel/include/list.h b/kernel/include/list.h index 756a0c30..b809de85 100644 --- a/kernel/include/list.h +++ b/kernel/include/list.h @@ -43,6 +43,9 @@ void list_merge(list_t * target, list_t * source); void list_append_after(list_t * list, node_t * before, node_t * node); node_t * list_insert_after(list_t * list, node_t * before, void * item); +void list_append_before(list_t * list, node_t * after, node_t * node); +node_t * list_insert_before(list_t * list, node_t * after, void * item); + #define foreach(i, list) for (node_t * i = list->head; i != NULL; i = i->next) #endif diff --git a/kernel/mem/shm.c b/kernel/mem/shm.c index a8501917..e4ff7675 100644 --- a/kernel/mem/shm.c +++ b/kernel/mem/shm.c @@ -163,6 +163,55 @@ static void * map_in (shm_chunk_t * chunk, process_t * proc) { mapping->num_vaddrs = chunk->num_frames; mapping->vaddrs = malloc(sizeof(uintptr_t) * mapping->num_vaddrs); + debug_print(INFO, "want %d bytes, running through mappings...", mapping->num_vaddrs * 0x1000); + uintptr_t last_address = SHM_START; + foreach(node, proc->shm_mappings) { + shm_mapping_t * m = node->value; + if (m->vaddrs[0] > last_address) { + size_t gap = (uintptr_t)m->vaddrs[0] - last_address; + debug_print(INFO, "gap found at 0x%x of size %d", last_address, gap); + if (gap >= mapping->num_vaddrs * 0x1000) { + debug_print(INFO, "Gap is sufficient, we can insert here."); + + /* Map the gap */ + for (unsigned int i = 0; i < chunk->num_frames; ++i) { + page_t * page = get_page(last_address + i * 0x1000, 1, proc->thread.page_directory); + alloc_frame(page, 0, 1); + page->frame = chunk->frames[i]; + mapping->vaddrs[i] = last_address + i * 0x1000; + } + + /* Insert us before this node */ + list_insert_before(proc->shm_mappings, node, mapping); + + return (void *)mapping->vaddrs[0]; + } + } + last_address = m->vaddrs[0] + m->num_vaddrs * 0x1000; + debug_print(INFO, "[0x%x:0x%x] %s", m->vaddrs[0], last_address, m->chunk->parent->name); + } + if (proc->image.shm_heap > last_address) { + size_t gap = proc->image.shm_heap - last_address; + debug_print(INFO, "gap found at 0x%x of size %d", last_address, gap); + if (gap >= mapping->num_vaddrs * 0x1000) { + debug_print(INFO, "Gap is sufficient, we can insert here."); + + for (unsigned int i = 0; i < chunk->num_frames; ++i) { + page_t * page = get_page(last_address + i * 0x1000, 1, proc->thread.page_directory); + alloc_frame(page, 0, 1); + page->frame = chunk->frames[i]; + mapping->vaddrs[i] = last_address + i * 0x1000; + } + + list_insert(proc->shm_mappings, mapping); + + return (void *)mapping->vaddrs[0]; + } else { + debug_print(INFO, "should be more efficient here - there is space available, but we are not going to use it"); + } + } + + for (uint32_t i = 0; i < chunk->num_frames; i++) { uintptr_t new_vpage = proc_sbrk(1, proc); assert(new_vpage % 0x1000 == 0); @@ -241,6 +290,10 @@ int shm_release (char * path) { spin_lock(&bsl); process_t * proc = (process_t *)current_process; + if (proc->group != 0) { + proc = process_from_pid(proc->group); + } + /* First, find the right chunk */ shm_node_t * _node = get_node(path, 0); if (!_node) {