aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/wm.c3
-rw-r--r--kernel/features/mm.c188
-rw-r--r--kernel/features/proc.c15
-rw-r--r--kernel/features/syscall.c17
-rw-r--r--kernel/inc/mm.h5
-rw-r--r--kernel/inc/proc.h1
-rw-r--r--libc/alloc.c7
-rw-r--r--libc/inc/sys.h7
-rw-r--r--libc/sys.c19
9 files changed, 136 insertions, 126 deletions
diff --git a/apps/wm.c b/apps/wm.c
index 531559f..6088a30 100644
--- a/apps/wm.c
+++ b/apps/wm.c
@@ -84,8 +84,7 @@ static struct window *window_new(struct client client, const char *name, struct
if ((flags & WF_NO_FB) != 0) {
win->ctx.fb = NULL;
} else {
- assert(shalloc(win->ctx.bytes, &win->shid) == EOK);
- assert(shaccess(win->shid, (u32 *)&win->ctx.fb, &win->ctx.bytes) == EOK);
+ assert(shalloc(win->ctx.bytes, (u32 *)&win->ctx.fb, &win->shid) == EOK);
}
win->client = client;
win->flags = flags;
diff --git a/kernel/features/mm.c b/kernel/features/mm.c
index 7e0d62a..d01c978 100644
--- a/kernel/features/mm.c
+++ b/kernel/features/mm.c
@@ -373,81 +373,106 @@ void *memory_alloc_identity(struct page_dir *dir, u32 flags)
}
}
- return 0;
+ print("Memory allocation error!\n");
+ return NULL;
}
-#define SHARED_MEMORY_MAX 128
-struct shared_memory {
+// TODO: Free by address instead of vrange (combine with shmem map?)
+void memory_free(struct page_dir *dir, struct memory_range vrange)
+{
+ assert(PAGE_ALIGNED(vrange.base) && PAGE_ALIGNED(vrange.size));
+
+ for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) {
+ u32 vaddr = vrange.base + i * PAGE_SIZE;
+ if (virtual_present(dir, vaddr)) {
+ struct memory_range page_prange =
+ memory_range(virtual_to_physical(dir, vaddr), PAGE_SIZE);
+ struct memory_range page_vrange = memory_range(vaddr, PAGE_SIZE);
+ physical_free(page_prange);
+ virtual_free(dir, page_vrange);
+ }
+ }
+}
+
+void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags)
+{
+ assert(PAGE_ALIGNED(prange.base) && PAGE_ALIGNED(prange.size));
+
+ physical_set_used(prange);
+ virtual_map(dir, prange, prange.base, flags);
+ if (flags & MEMORY_CLEAR)
+ memset((void *)prange.base, 0, prange.size);
+}
+
+struct memory_object {
u32 id;
u32 refs;
- u8 used;
+ u8 shared;
struct memory_range prange;
};
-static struct shared_memory shmem[SHARED_MEMORY_MAX] = { 0 };
-res memory_shalloc(struct page_dir *dir, u32 size, u32 *id, u32 flags)
+struct memory_proc_link {
+ struct memory_object *obj;
+ struct memory_range vrange;
+};
+static struct list *memory_objects = NULL;
+res memory_sys_alloc(struct page_dir *dir, u32 size, u32 *addr, u32 *id, u8 shared)
{
- if (!id || !memory_valid(id))
+ if (!addr || !memory_valid(addr) || !id || !memory_valid(id))
return -EFAULT;
- *id = 0;
+ size = PAGE_ALIGN_UP(size);
- u32 slot = SHARED_MEMORY_MAX + 1;
-
- for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
- if (!shmem[i].used) {
- slot = i;
- break;
- }
- }
-
- if (slot >= SHARED_MEMORY_MAX)
+ u32 vaddr = (u32)memory_alloc(dir, size, MEMORY_CLEAR | MEMORY_USER);
+ if (!vaddr)
return -ENOMEM;
- void *addr = memory_alloc(dir, size, flags);
- if (!addr)
- return -ENOMEM;
+ struct memory_object *obj = zalloc(sizeof(*obj));
+ obj->id = rdrand() + 1;
+ obj->prange = memory_range(virtual_to_physical(dir, vaddr), size);
+ obj->refs = 1;
+ obj->shared = shared;
+ list_add(memory_objects, obj);
- // TODO: Verify that shid isn't used already
- // TODO: Check for colliding prange
- u32 shid = rdseed() + 1;
- shmem[slot].id = shid;
- shmem[slot].used = 1;
- shmem[slot].prange = memory_range(virtual_to_physical(dir, (u32)addr), size);
+ struct memory_proc_link *link = zalloc(sizeof(*link));
+ link->obj = obj;
+ link->vrange = memory_range(vaddr, size);
+ list_add(proc_current()->memory, link);
- *id = shid;
+ *addr = vaddr;
+ *id = obj->id;
return EOK;
}
-static struct shared_memory memory_shresolve_range(struct memory_range prange)
-{
- for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
- if (!shmem[i].used)
- continue;
-
- struct memory_range shrange = shmem[i].prange;
- if (prange.base < shrange.base + shrange.size &&
- prange.base + prange.size > shrange.base)
- return shmem[i];
- }
-
- return (struct shared_memory){ 0 };
-}
-
-static struct shared_memory memory_shresolve_id(u32 shid)
+res memory_sys_free(struct page_dir *dir, u32 addr)
{
- for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
- if (!shmem[i].used)
- continue;
+ if (!addr || !memory_valid((void *)addr))
+ return -EFAULT;
- if (shmem[i].id == shid)
- return shmem[i];
+ struct list *links = proc_current()->memory;
+ struct node *iterator = links->head;
+ while (iterator) {
+ struct memory_proc_link *link = iterator->data;
+ if (link->vrange.base == addr) {
+ virtual_free(dir, link->vrange);
+ link->obj->refs--;
+ if (link->obj->refs == 0) {
+ list_remove(memory_objects,
+ list_first_data(memory_objects, link->obj));
+ physical_free(link->obj->prange);
+ free(link->obj);
+ }
+ list_remove(links, list_first_data(links, link));
+ free(link);
+ return EOK;
+ }
+ iterator = iterator->next;
}
- return (struct shared_memory){ 0 };
+ return -ENOENT;
}
-res memory_shaccess(struct page_dir *dir, u32 shid, u32 *addr, u32 *size)
+res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size)
{
if (!addr || !memory_valid(addr) || !size || !memory_valid(size))
return -EFAULT;
@@ -455,54 +480,31 @@ res memory_shaccess(struct page_dir *dir, u32 shid, u32 *addr, u32 *size)
*addr = 0;
*size = 0;
- struct shared_memory sh = memory_shresolve_id(shid);
- struct memory_range prange = sh.prange;
- if (sh.used == 0 || prange.base == 0 || prange.size == 0)
- return -ENOENT;
+ struct node *iterator = memory_objects->head;
+ while (iterator) {
+ struct memory_object *obj = iterator->data;
+ if (obj->id == id) {
+ if (!obj->shared)
+ return -EACCES;
- sh.refs++;
+ obj->refs++;
+ struct memory_range shrange =
+ virtual_alloc(dir, obj->prange, MEMORY_CLEAR | MEMORY_USER);
- struct memory_range shrange = virtual_alloc(dir, prange, MEMORY_CLEAR | MEMORY_USER);
- *addr = shrange.base;
- *size = shrange.size;
+ *addr = shrange.base;
+ *size = shrange.size;
- return EOK;
-}
-
-// TODO: Free by address instead of vrange (combine with shmem map?)
-void memory_free(struct page_dir *dir, struct memory_range vrange)
-{
- assert(PAGE_ALIGNED(vrange.base) && PAGE_ALIGNED(vrange.size));
-
- struct memory_range prange =
- memory_range(virtual_to_physical(dir, vrange.base), vrange.size);
- struct shared_memory sh = memory_shresolve_range(prange);
- if (sh.used != 0 && sh.refs > 1) {
- panic("Freeing busy memory!\n");
- return;
- }
- /* sh.used = 0; */
+ struct memory_proc_link *link = zalloc(sizeof(*link));
+ link->obj = obj;
+ link->vrange = shrange;
+ list_add(proc_current()->memory, link);
- for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) {
- u32 vaddr = vrange.base + i * PAGE_SIZE;
- if (virtual_present(dir, vaddr)) {
- struct memory_range page_prange =
- memory_range(virtual_to_physical(dir, vaddr), PAGE_SIZE);
- struct memory_range page_vrange = memory_range(vaddr, PAGE_SIZE);
- physical_free(page_prange);
- virtual_free(dir, page_vrange);
+ return EOK;
}
+ iterator = iterator->next;
}
-}
-void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags)
-{
- assert(PAGE_ALIGNED(prange.base) && PAGE_ALIGNED(prange.size));
-
- physical_set_used(prange);
- virtual_map(dir, prange, prange.base, flags);
- if (flags & MEMORY_CLEAR)
- memset((void *)prange.base, 0, prange.size);
+ return -ENOENT;
}
void memory_switch_dir(struct page_dir *dir)
@@ -627,4 +629,6 @@ void memory_install(struct mem_info *mem_info, struct vid_info *vid_info)
memory_switch_dir(&kernel_dir);
paging_enable();
+
+ memory_objects = list_new();
}
diff --git a/kernel/features/proc.c b/kernel/features/proc.c
index 88c477f..624a835 100644
--- a/kernel/features/proc.c
+++ b/kernel/features/proc.c
@@ -140,15 +140,21 @@ void proc_exit(struct proc *proc, s32 status)
iterator = iterator->next;
}
+ assert(found);
+
if (memcmp(proc, current->data, sizeof(*proc)) == 0)
current = NULL;
- if (found)
- printf("Process %s (%d) exited with status %d (%s)\n",
- proc->name[0] ? proc->name : "UNKNOWN", proc->pid, status,
- status == 0 ? "success" : "error");
+ printf("Process %s (%d) exited with status %d (%s)\n",
+ proc->name[0] ? proc->name : "UNKNOWN", proc->pid, status,
+ status == 0 ? "success" : "error");
+ stack_destroy(proc->messages);
+ list_destroy(proc->memory); // TODO: Decrement memory ref links
virtual_destroy_dir(proc->page_dir);
+
+ free(proc);
+
proc_clear_quantum(); // TODO: Add quantum to each process struct?
// The caller has to yield itself
@@ -250,6 +256,7 @@ struct proc *proc_make(enum proc_priv priv)
proc->pid = current_pid++;
proc->priv = priv;
proc->messages = stack_new();
+ proc->memory = list_new();
proc->state = PROC_RUNNING;
if (priv == PROC_PRIV_KERNEL)
diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c
index 48a5850..44caff8 100644
--- a/kernel/features/syscall.c
+++ b/kernel/features/syscall.c
@@ -29,22 +29,17 @@ static void syscall_handler(struct regs *r)
break;
}
case SYS_ALLOC: {
- r->eax = (u32)memory_alloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx),
- MEMORY_CLEAR | MEMORY_USER);
+ r->eax = (u32)memory_sys_alloc(proc_current()->page_dir, r->ebx, (u32 *)r->ecx,
+ (u32 *)r->edx, (u8)r->esi);
break;
}
- case SYS_SHALLOC: {
- r->eax = memory_shalloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx),
- (u32 *)r->ecx, MEMORY_CLEAR | MEMORY_USER);
+ case SYS_FREE: {
+ r->eax = memory_sys_free(proc_current()->page_dir, r->ebx);
break;
}
case SYS_SHACCESS: {
- r->eax = memory_shaccess(proc_current()->page_dir, r->ebx, (u32 *)r->ecx,
- (u32 *)r->edx);
- break;
- }
- case SYS_FREE: {
- memory_free(proc_current()->page_dir, memory_range(r->ebx, r->ecx));
+ r->eax = memory_sys_shaccess(proc_current()->page_dir, r->ebx, (u32 *)r->ecx,
+ (u32 *)r->edx);
break;
}
case SYS_STAT: {
diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h
index 5e49aa7..ae4e962 100644
--- a/kernel/inc/mm.h
+++ b/kernel/inc/mm.h
@@ -117,8 +117,9 @@ u8 memory_is_user(u32 addr);
u8 memory_valid(const void *addr);
// User interface
-res memory_shalloc(struct page_dir *dir, u32 size, u32 *id, u32 flags);
-res memory_shaccess(struct page_dir *dir, u32 shid, u32 *addr, u32 *size);
+res memory_sys_alloc(struct page_dir *dir, u32 size, u32 *addr, u32 *id, u8 shared);
+res memory_sys_free(struct page_dir *dir, u32 addr);
+res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size);
void memory_install(struct mem_info *mem_info, struct vid_info *vid_info);
diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h
index c946116..eb972d3 100644
--- a/kernel/inc/proc.h
+++ b/kernel/inc/proc.h
@@ -56,6 +56,7 @@ struct proc {
struct proc_wait wait; // dev_id
enum proc_state state;
struct stack *messages;
+ struct list *memory;
};
void scheduler(struct regs *regs);
diff --git a/libc/alloc.c b/libc/alloc.c
index 8522203..b8139d0 100644
--- a/libc/alloc.c
+++ b/libc/alloc.c
@@ -26,12 +26,15 @@ static int liballoc_free(void *ptr, u32 p)
static void *liballoc_alloc(u32 p)
{
- return sys_alloc(p);
+ u32 addr;
+ assert(sys_alloc(p, &addr) == EOK);
+ return (void *)addr;
}
static int liballoc_free(void *ptr, u32 p)
{
- sys_free(ptr, p);
+ UNUSED(p);
+ assert(sys_free(ptr) == EOK);
return 0;
}
diff --git a/libc/inc/sys.h b/libc/inc/sys.h
index 8f30dbb..caa1dbd 100644
--- a/libc/inc/sys.h
+++ b/libc/inc/sys.h
@@ -17,7 +17,6 @@
enum sys {
SYS_LOOP, // To infinity and beyond (debug)!
SYS_ALLOC, // Allocate memory
- SYS_SHALLOC, // Allocate shared memory
SYS_SHACCESS, // Access shared memory
SYS_FREE, // Free memory
SYS_STAT, // Get file information
@@ -78,10 +77,10 @@ res yield(void);
res boot(u32 cmd);
u32 time(void);
-void *sys_alloc(u32 size);
-res shalloc(u32 size, u32 *id);
+res sys_alloc(u32 size, u32 *addr);
+res sys_free(void *ptr);
+res shalloc(u32 size, u32 *addr, u32 *id);
res shaccess(u32 id, u32 *addr, u32 *size);
-void sys_free(void *ptr, u32 size);
static inline u32 getpid(void)
{
diff --git a/libc/sys.c b/libc/sys.c
index b40b84d..491c37c 100644
--- a/libc/sys.c
+++ b/libc/sys.c
@@ -2,6 +2,7 @@
// Syscall implementation
#include <arg.h>
+#include <assert.h>
#include <errno.h>
#include <sys.h>
@@ -78,25 +79,25 @@ res sys5(enum sys num, int d1, int d2, int d3, int d4, int d5)
* Syscalls
*/
-void *sys_alloc(u32 size)
+res sys_alloc(u32 size, u32 *addr)
{
- return (void *)sys1(SYS_ALLOC, (int)size);
+ u32 id = 0;
+ return sys4(SYS_ALLOC, (int)size, (int)addr, (int)&id, 0);
}
-res shalloc(u32 size, u32 *id)
+res sys_free(void *ptr)
{
- return (res)sys2(SYS_SHALLOC, (int)size, (int)id);
+ return sys1(SYS_FREE, (int)ptr);
}
-res shaccess(u32 id, u32 *addr, u32 *size)
+res shalloc(u32 size, u32 *addr, u32 *id)
{
- return (res)sys3(SYS_SHACCESS, (int)id, (int)addr, (int)size);
+ return sys4(SYS_ALLOC, (int)size, (int)addr, (int)id, 1);
}
-// TODO: Freeing by ptr + size could be a security risk -> only by address!
-void sys_free(void *ptr, u32 size)
+res shaccess(u32 id, u32 *addr, u32 *size)
{
- sys2(SYS_FREE, (int)ptr, (int)size);
+ return sys3(SYS_SHACCESS, (int)id, (int)addr, (int)size);
}
void loop(void)