Files
codezero/tasks/mm0/src/task.c
Bahadir Balban e2b791a3d8 Initial commit
2008-01-13 13:53:52 +00:00

150 lines
3.7 KiB
C

/*
* Task management.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/lib/list.h>
#include <l4/api/thread.h>
#include INC_GLUE(memory.h)
#include <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
#include <lib/vaddr.h>
#include <task.h>
#include <kdata.h>
#include <kmalloc/kmalloc.h>
#include <string.h>
#include <vm_area.h>
#include <memory.h>
struct tcb_head {
struct list_head list;
int total; /* Total threads */
} tcb_head;
struct tcb *find_task(int tid)
{
struct tcb *t;
list_for_each_entry(t, &tcb_head.list, list)
if (t->tid == tid)
return t;
return 0;
}
#if 0
void dump_tasks(void)
{
struct tcb *t;
list_for_each_entry(t, &tcb_head.list, list) {
printf("Task %s: id/spid: %d/%d\n", &t->name[0], t->tid, t->spid);
printf("Task vm areas:\n");
dump_vm_areas(t);
printf("Task swapfile:\n");
dump_task_swapfile(t);
}
}
#endif
void create_init_tcbs(struct initdata *initdata)
{
struct bootdesc *bd = initdata->bootdesc;
INIT_LIST_HEAD(&tcb_head.list);
tcb_head.total++;
for (int i = BOOTDESC_IMAGE_START; i < bd->total_images; i++) {
struct tcb *task = kzalloc(sizeof(struct tcb));
/* Ids will be acquired from the kernel */
task->tid = TASK_ID_INVALID;
task->spid = TASK_ID_INVALID;
task->swap_file = kzalloc(sizeof(struct vm_file));
task->swap_file->pager = &swap_pager;
vaddr_pool_init(task->swap_file_offset_pool, 0,
__pfn(TASK_SWAPFILE_MAXSIZE));
INIT_LIST_HEAD(&task->swap_file->page_cache_list);
INIT_LIST_HEAD(&task->list);
INIT_LIST_HEAD(&task->vm_area_list);
list_add_tail(&task->list, &tcb_head.list);
}
}
int start_init_tasks(struct initdata *initdata)
{
struct tcb *task;
int err;
int i = BOOTDESC_IMAGE_START;
list_for_each_entry(task, &tcb_head.list, list) {
struct vm_file *file = &initdata->memfile[i++];
unsigned int sp = align(USER_AREA_END - 1, 8);
unsigned int pc = USER_AREA_START;
struct task_ids ids = { .tid = task->tid, .spid = task->spid };
/* mmap each task's physical image to task's address space. */
if ((err = do_mmap(file, 0, task, USER_AREA_START,
VM_READ | VM_WRITE | VM_EXEC,
__pfn(page_align_up(file->length)))) < 0) {
printf("do_mmap: failed with %d.\n", err);
goto error;
}
/* mmap each task's stack as single page anonymous memory. */
if ((err = do_mmap(0, 0, task, USER_AREA_END - PAGE_SIZE,
VM_READ | VM_WRITE | VMA_ANON, 1) < 0)) {
printf("do_mmap: Mapping stack failed with %d.\n", err);
goto error;
}
/* mmap each task's utcb as single page anonymous memory. */
if ((err = do_mmap(0, 0, task, (unsigned long)__L4_ARM_Utcb(),
VM_READ | VM_WRITE | VMA_ANON, 1) < 0)) {
printf("do_mmap: Mapping stack failed with %d.\n", err);
goto error;
}
printf("Creating new thread.\n");
/* Create the thread structures and address space */
if ((err = l4_thread_control(THREAD_CREATE, &ids)) < 0) {
printf("l4_thread_control failed with %d.\n", err);
goto error;
}
printf("New task with id: %d, space id: %d\n", ids.tid, ids.spid);
/* Use returned space and thread ids. */
task->tid = ids.tid;
task->spid = ids.spid;
/* Set up the task's thread details, (pc, sp, pager etc.) */
if ((err = l4_exchange_registers(pc, sp, self_tid(), task->tid) < 0)) {
printf("l4_exchange_registers failed with %d.\n", err);
goto error;
}
printf("Starting task with id %d\n", task->tid);
/* Start the thread */
if ((err = l4_thread_control(THREAD_RUN, &ids) < 0)) {
printf("l4_thread_control failed with %d\n");
goto error;
}
}
return 0;
error:
BUG();
}
void init_pm(struct initdata *initdata)
{
create_init_tcbs(initdata);
start_init_tasks(initdata);
}