Efficient reallocation of SHM chunks (mostly)

This commit is contained in:
Kevin Lange 2014-04-20 17:11:35 -07:00
parent deeb1c42a5
commit d0bfc0a5bb
3 changed files with 92 additions and 0 deletions

View File

@ -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));

View File

@ -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

View File

@ -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) {