Commit 854f1a37 authored by Léo Grange's avatar Léo Grange
Browse files

implement memory area manipulation functions

parent 5c141032
Loading
Loading
Loading
Loading

sys/mem_area.c

0 → 100644
+104 −0
Original line number Diff line number Diff line
#include "mem_area.h"
#include <sys/process.h>
#include <utils/pool_alloc.h>
#include <fs/vfs_file.h>
#include <utils/log.h>


// pool allocation data
static struct pool_alloc _mem_area_pool = POOL_INIT(struct mem_area);


void mem_area_init() {
	printk(LOG_DEBUG, "mem_area: area/page=%d\n", _mem_area_pool.perpage);
}


struct mem_area *mem_area_alloc() {
	struct mem_area *ret;

	ret = pool_alloc(&_mem_area_pool);
	if(ret != NULL) {
		ret->flags = 0;
		ret->address = NULL;
		ret->max_size = 0;
	}

	return ret;
}

void mem_area_free(struct mem_area *area) {
	pool_free(&_mem_area_pool, area);
}


struct mem_area *mem_area_find(struct process *proc, void *address) {
	// for now, the list is not sorted, so check for each
	struct list_head *cur;
	struct mem_area *ret = NULL;

	list_for_each(cur, &(proc->mem_areas)) {
		// check if address is inside this area
		struct mem_area *area = container_of(cur, struct mem_area, list);
		if(address >= area->address && address < (area->address + area->max_size)) {
			ret = area;
			break;
		}
	}

	return ret;
}


/**
 * internal function, check if an area is defined in the given address range
 * Return 0 if this range is empty, 1 if an area exists.
 */
static int mem_area_check_range(struct process *proc, void *addr_begin, size_t size) {
	struct list_head *cur;

	list_for_each(cur, &(proc->mem_areas)) {
		// check if address range intersects with this area
		struct mem_area *area = container_of(cur, struct mem_area, list);
		if(area->address < (addr_begin + size)
				&& (area->address + area->max_size) > addr_begin)
			return 1;
	}

	return 0;
}


int mem_area_insert(struct process *proc, struct mem_area *area) {
	// check for any overlayed area
	if(!mem_area_check_range(proc, area->address, area->max_size)) {
		// not sorted, insert in front
		list_push_front(& proc->mem_areas, & area->list);
		return 0;
	}

	printk(LOG_ERR, "mem_area: unable to insert area (overlay)\n");
	return -1;
}


int mem_area_copy_raw(struct mem_area *area, size_t offset, void *dest, size_t size) {
	int ret = -1;

	if(area->flags & MEM_AREA_TYPE_ANON) {
		// anonymous area, the current implementation do nothing...
		ret = 0;
	}
	else if(area->flags & MEM_AREA_TYPE_FILE) {
		// file mapped to memory, for now use a generic way to handle them
		// TODO improve this with map_area_ops struct to allow "override"
		size_t nbread;

		vfs_lseek(area->file.filep, SEEK_SET, offset);
		nbread = vfs_read(area->file.filep, dest, size);
		ret = nbread == size ? 0 : -1;
	}

	return ret;
}
+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ struct mem_area {
	union {
		struct {
			// file structure of the file mapped to this area
			struct file *f;
			struct file *filep;

			// origin's position in the file
			size_t origin;
@@ -61,6 +61,7 @@ void mem_area_init();
 * Return a newly allocated memory area, not initialized.
 */
struct mem_area *mem_area_alloc();
void mem_area_free(struct mem_area *area);


/**
+2 −2
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
#include <utils/bitfield.h>
#include <interface/fixos/fcntl.h>
#include <interface/fixos/errno.h>
#include <sys/mem_areas.h>
#include <sys/mem_area.h>

#include <loader/elfloader/loader.h>
#include <fs/vfs_file.h>
@@ -111,7 +111,7 @@ struct process *process_alloc() {

			arch_adrsp_init(& proc->addr_space);
			proc->dir_list = NULL;
			INIT_LIST_HEAD(proc->mem_areas);
			INIT_LIST_HEAD(& proc->mem_areas);


			sigemptyset(& proc->sig_blocked);
+2 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@ C_SRC_L:= \
	kdebug.c \
	sysctl.c \
	waitqueue.c \
	tty.c
	tty.c \
	mem_area.c


CURDIR:=sys