Files
codezero/tasks/mm0/src/vm_object.c
Bahadir Balban 46937eab88 Added preliminary support for execve(). Updates to clone, fork, exit, task handling.
It turned out we used one version of kmalloc for malloc() and another for kfree()!
Now fixed.
Added parent-child relationship to tasks. Need to polish handling CLONE_PARENT and THREAD.
2008-11-19 12:59:52 +02:00

218 lines
4.5 KiB
C

/*
* vm object utility functions.
*
* Copyright (C) 2008 Bahadir Balban
*/
#include <file.h>
#include <vm_area.h>
#include <l4/macros.h>
#include <l4/api/errno.h>
#include <lib/malloc.h>
#include <globals.h>
/* Global list of all in-memory files on the system */
struct global_list global_vm_files = {
.list = { &global_vm_files.list, &global_vm_files.list },
.total = 0,
};
/* Global list of in-memory vm objects in the system */
struct global_list global_vm_objects = {
.list = { &global_vm_objects.list, &global_vm_objects.list },
.total = 0,
};
void global_add_vm_object(struct vm_object *obj)
{
BUG_ON(!list_empty(&obj->list));
list_add(&obj->list, &global_vm_objects.list);
global_vm_objects.total++;
}
void global_remove_vm_object(struct vm_object *obj)
{
BUG_ON(list_empty(&obj->list));
list_del_init(&obj->list);
BUG_ON(--global_vm_objects.total < 0);
}
void global_add_vm_file(struct vm_file *f)
{
BUG_ON(!list_empty(&f->list));
list_add(&f->list, &global_vm_files.list);
global_vm_files.total++;
global_add_vm_object(&f->vm_obj);
}
void global_remove_vm_file(struct vm_file *f)
{
BUG_ON(list_empty(&f->list));
list_del_init(&f->list);
BUG_ON(--global_vm_files.total < 0);
global_remove_vm_object(&f->vm_obj);
}
void print_cache_pages(struct vm_object *vmo)
{
struct page *p;
if (!list_empty(&vmo->page_cache))
printf("Pages:\n======\n");
list_for_each_entry(p, &vmo->page_cache, list) {
dprintf("Page offset: 0x%x, virtual: 0x%x, refcnt: %d\n", p->offset,
p->virtual, p->refcnt);
}
}
void vm_object_print(struct vm_object *vmo)
{
struct vm_file *f;
printf("Object type: %s %s. links: %d, shadows: %d, Pages in cache: %d.\n",
vmo->flags & VM_WRITE ? "writeable" : "read-only",
vmo->flags & VM_OBJ_FILE ? "file" : "shadow", vmo->nlinks, vmo->shadows,
vmo->npages);
if (vmo->flags & VM_OBJ_FILE) {
f = vm_object_to_file(vmo);
char *ftype;
if (f->type == VM_FILE_DEVZERO)
ftype = "devzero";
else if (f->type == VM_FILE_BOOTFILE)
ftype = "bootfile";
else if (f->type == VM_FILE_SHM)
ftype = "shm file";
else if (f->type == VM_FILE_VFS)
ftype = "regular";
else
BUG();
printf("File type: %s\n", ftype);
}
// print_cache_pages(vmo);
// printf("\n");
}
void vm_print_files(struct list_head *files)
{
struct vm_file *f;
list_for_each_entry(f, files, list)
vm_object_print(&f->vm_obj);
}
void vm_print_objects(struct list_head *objects)
{
struct vm_object *vmo;
list_for_each_entry(vmo, objects, list)
vm_object_print(vmo);
}
struct vm_object *vm_object_init(struct vm_object *obj)
{
INIT_LIST_HEAD(&obj->list);
INIT_LIST_HEAD(&obj->shref);
INIT_LIST_HEAD(&obj->shdw_list);
INIT_LIST_HEAD(&obj->page_cache);
INIT_LIST_HEAD(&obj->link_list);
return obj;
}
/* Allocate and initialise a vmfile, and return it */
struct vm_object *vm_object_create(void)
{
struct vm_object *obj;
if (!(obj = kzalloc(sizeof(*obj))))
return 0;
return vm_object_init(obj);
}
struct vm_file *vm_file_create(void)
{
struct vm_file *f;
if (!(f = kzalloc(sizeof(*f))))
return PTR_ERR(-ENOMEM);
INIT_LIST_HEAD(&f->list);
vm_object_init(&f->vm_obj);
f->vm_obj.flags = VM_OBJ_FILE;
return f;
}
/*
* Populates the priv_data with vfs-file-specific
* information.
*/
struct vm_file *vfs_file_create(void)
{
struct vm_file *f = vm_file_create();
if (IS_ERR(f))
return f;
f->priv_data = kzalloc(sizeof(struct vfs_file_data));
f->type = VM_FILE_VFS;
return f;
}
/* Deletes the object via its base, along with all its pages */
int vm_object_delete(struct vm_object *vmo)
{
struct vm_file *f;
// vm_object_print(vmo);
/* Release all pages */
vmo->pager->ops.release_pages(vmo);
/* Remove from global list */
if (vmo->flags & VM_OBJ_FILE)
global_remove_vm_file(vm_object_to_file(vmo));
else if (vmo->flags & VM_OBJ_SHADOW)
global_remove_vm_object(vmo);
else BUG();
/* Check any references */
BUG_ON(vmo->nlinks);
BUG_ON(vmo->shadows);
BUG_ON(!list_empty(&vmo->shdw_list));
BUG_ON(!list_empty(&vmo->link_list));
BUG_ON(!list_empty(&vmo->page_cache));
BUG_ON(!list_empty(&vmo->shref));
/* Obtain and free via the base object */
if (vmo->flags & VM_OBJ_FILE) {
f = vm_object_to_file(vmo);
BUG_ON(!list_empty(&f->list));
if (f->priv_data) {
if (f->destroy_priv_data)
f->destroy_priv_data(f);
else
kfree(f->priv_data);
}
kfree(f);
} else if (vmo->flags & VM_OBJ_SHADOW)
kfree(vmo);
else BUG();
return 0;
}
int vm_file_delete(struct vm_file *f)
{
/* Delete file via base object */
return vm_object_delete(&f->vm_obj);
}