Files
codezero/tasks/mm0/src/task.c
Bahadir Balban cab2e8bdd3 Finished adding untested bare functionality vfs
Finished adding untested shm syscalls.
Finished adding untested l4 send/recv helpers

Everything compiles. Now going to fix lots of bugs ;-)
2008-02-03 17:42:38 +00:00

179 lines
4.2 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 <l4lib/ipcdefs.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);
}
void send_task_data(l4id_t requester)
{
struct tcb *t;
int li, err;
if (requester != VFS_TID) {
printf("Task data is not requested by FS0, ignoring.\n");
return;
}
/* First word is total number of tcbs */
write_mr(L4SYS_ARG0, tcb_head.total);
/* Write each tcb's tid */
li = 0;
list_for_each_entry(t, &tcb_head.list, list) {
BUG_ON(li >= MR_USABLE_TOTAL);
write_mr(L4SYS_ARG1 + li, t->tid);
li++;
}
/* Reply */
if ((err = l4_ipc_return(0)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
BUG();
}
}