mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Finished adding untested shm syscalls. Finished adding untested l4 send/recv helpers Everything compiles. Now going to fix lots of bugs ;-)
179 lines
4.2 KiB
C
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();
|
|
}
|
|
}
|
|
|