Few more fixes.

Boot files and tasks are now initialised together. Theads can ask for particular
space and thread ids, if they're unused. This enables us to get predefined ids for
known tasks such as the VFS task.

Fixes to README
Other minor fixes.
This commit is contained in:
Bahadir Balban
2008-02-09 14:24:49 +00:00
parent 4aa26af61d
commit ba0e3ada21
14 changed files with 134 additions and 64 deletions

20
README
View File

@@ -33,8 +33,8 @@ the project is written from scratch, so the name emphasises that.
Design & Features:
Codezero microkernel: Based on L4 microkernel principles, there are only a few
system calls and the microkernel provides purely mechanism; threads and address
Based on L4 microkernel principles, there are only a few system calls in
Codezero. These system calls provide purely mechanism; threads and address
spaces, and the methods of inter-process communication between them. Anything
beyond these are policy and they are implemented in the userspace. Due to this
rigorously simple design the same microkernel can be used to design completely
@@ -42,13 +42,13 @@ different operating systems. In terms of other features, the microkernel is
preemptive, and smp-ready. Currently only synchronous communication is
implemented, but this will change in the near future.
MM0: Implements memory management. It contains memory and page allocators. It
implements demand paging by managing page faults, physical pages and their
file/task associations.
MM0 is the systm task that implements memory management. It contains memory and
page allocators. It implements demand paging by managing page faults, physical
pages and their file/task associations.
FS0: Implements a simple, modern virtual filesystem layer. Since it abstracts
the low-level filesystem details, it is a relatively easy job to port a new
filesystem to be used under FS0.
FS0 is the system task implements a simple, modern virtual filesystem layer.
Since it abstracts the low-level filesystem details, it is a relatively easy job
to port a new filesystem to be used under FS0.
License:
@@ -65,9 +65,9 @@ party source code is open source in the OSI definition. Please check these
directories for their respective licenses.
Why yet another Posix (micro) kernel?
Why yet another POSIX microkernel?
There are many open source Posix operating systems with advanced features such
There are many open source POSIX operating systems with advanced features such
as *BSD and Linux. However these were originally not designed for embedded
systems. Unix itself and all the tools built upon weren't meant for using on
small devices. Accordingly, these operating systems contain a lot of historical

View File

@@ -4,6 +4,7 @@
unsigned int __clz(unsigned int bitvector);
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
int check_and_clear_bit(u32 *word, int bit);
int check_and_set_bit(u32 *word, int bit);
/* Set */

View File

@@ -11,5 +11,6 @@ struct id_pool {
struct id_pool *id_pool_new_init(int mapsize);
int id_new(struct id_pool *pool);
int id_del(struct id_pool *pool, int id);
int id_get(struct id_pool *pool, int id);
#endif /* __IDPOOL_H__ */

View File

@@ -83,11 +83,29 @@ int thread_create(struct task_ids *ids)
copy_pgd_kern_all(new->pgd);
/* Get new space id */
ids->spid = id_new(space_id_pool);
if (ids->spid == TASK_ID_INVALID) {
ids->spid = id_new(space_id_pool);
printk("Got new space id: %d\n", ids->spid);
} else {
printk("Try new space id: %d\n", ids->spid);
if ((ids->spid = id_get(space_id_pool, ids->spid)) < 0)
ids->spid = id_new(space_id_pool);
else
printk("Success.\n");
}
spc_found:
/* Get a new thread id */
ids->tid = id_new(thread_id_pool);
if (ids->tid == TASK_ID_INVALID) {
ids->tid = id_new(thread_id_pool);
printk("Got new thread id: %d\n", ids->tid);
} else {
printk("Try new thread id: %d\n", ids->tid);
if ((ids->tid = id_get(thread_id_pool, ids->tid)) < 0)
ids->tid = id_new(thread_id_pool);
else
printk("Success.\n");
}
/* Set all ids */
set_task_ids(new, ids);

View File

@@ -250,7 +250,7 @@ void switch_to_user(struct ktcb *task)
jump(task);
}
void init_inittask(char *name, struct task_ids *ids)
void init_pager(char *name, struct task_ids *ids)
{
struct svc_image *taskimg = 0;
struct ktcb *task;
@@ -262,7 +262,7 @@ void init_inittask(char *name, struct task_ids *ids)
* This also solves the problem of freeing the bootstack and making use
* of the initial kspace pgd.
*/
if (!strcmp(name, "mm0"))
if (!strcmp(name, __PAGERNAME__))
task = current; /* mm0 is the mockup current during init */
else
task = (struct ktcb *)zalloc_page();
@@ -341,7 +341,7 @@ void init_tasks()
* This must come last so that other tasks can copy its pgd before it
* modifies it for its own specifics.
*/
init_inittask("mm0", &ids);
init_pager(__PAGERNAME__, &ids);
}
void start_kernel(void)

View File

@@ -50,3 +50,15 @@ int check_and_clear_bit(u32 *word, int bit)
}
}
int check_and_set_bit(u32 *word, int bit)
{
/* Check that bit was clear */
if (!(word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit))) {
word[BITWISE_GETWORD(bit)] |= BITWISE_GETBIT(bit);
return 0;
} else {
//printf("Trying to set already set bit\n");
return -1;
}
}

View File

@@ -33,3 +33,14 @@ int id_del(struct id_pool *pool, int id)
return ret;
}
/* Return a specific id, if available */
int id_get(struct id_pool *pool, int id)
{
int ret = check_and_set_bit(pool->bitmap, id);
if (ret < 0)
return ret;
else
return id;
}

View File

@@ -71,6 +71,7 @@ static inline struct superblock *vfs_alloc_superblock(void)
{
struct superblock *sb = kmalloc(sizeof(struct superblock));
INIT_LIST_HEAD(&sb->list);
return sb;
}

View File

@@ -6,6 +6,8 @@
#include <init.h>
#include <fs.h>
#include <vfs.h>
#include <task.h>
#include <stdio.h>
#include <memfs/memfs.h>
#include <memfs/vnode.h>
#include <lib/idpool.h>
@@ -138,11 +140,16 @@ struct superblock *memfs_get_superblock(void *block)
struct memfs_superblock *sb = block;
struct superblock *vfs_sb;
printf("%s: %s: Reading superblock.\n", __TASKNAME__, __FUNCTION__);
/* We don't do sanity checks here, just confirm id. */
if (!strcmp(sb->name, "memfs"))
if (strcmp(sb->name, "memfs")) {
printf("%s: Name does not match: %s\n", __FUNCTION__, sb->name);
return 0;
if (sb->magic != MEMFS_MAGIC)
}
if (sb->magic != MEMFS_MAGIC) {
printf("%s: Magic number not match: %s\n", __FUNCTION__, sb->magic);
return 0;
}
/* Allocate a vfs superblock. */
vfs_sb = vfs_alloc_superblock();
@@ -154,6 +161,10 @@ struct superblock *memfs_get_superblock(void *block)
/* Registers sfs as an available filesystem type */
void memfs_register_fstype(struct list_head *fslist)
{
/* Initialise superblock list for this fstype */
INIT_LIST_HEAD(&memfs_fstype.sblist);
/* Add this fstype to list of available fstypes. */
list_add(&memfs_fstype.list, fslist);
}

View File

@@ -16,8 +16,6 @@
#include INC_ARCH(bootdesc.h)
#include <vm_area.h>
#define BOOTDESC_IMAGE_START 1
struct initdata {
struct bootdesc *bootdesc;
struct list_head boot_file_list;

View File

@@ -34,7 +34,7 @@ void handle_requests(void)
u32 tag;
int err;
printf("%s: Initiating ipc.\n", __TASKNAME__);
// printf("%s: Initiating ipc.\n", __TASKNAME__);
if ((err = l4_receive(L4_ANYTHREAD)) < 0) {
printf("%s: %s: IPC Error: %d. Quitting...\n", __TASKNAME__,
__FUNCTION__, err);
@@ -55,7 +55,7 @@ void handle_requests(void)
* A thread that wants to sync with us would have
* started here.
*/
printf("%s: Synced with waiting thread.\n", __TASKNAME__);
// printf("%s: Synced with waiting thread.\n", __TASKNAME__);
break;
case L4_IPC_TAG_PFAULT:

View File

@@ -50,44 +50,13 @@ void init_mm(struct initdata *initdata)
l4_kmem_grant(__pfn(alloc_page(__pfn(SZ_1MB))), __pfn(SZ_1MB));
}
/* Create temporary run-time files in memory to test with mmap */
void init_boot_files(struct initdata *initdata)
{
struct vm_file *f;
struct svc_image *img;
struct bootdesc *bd = initdata->bootdesc;
INIT_LIST_HEAD(&initdata->boot_file_list);
for (int i = BOOTDESC_IMAGE_START; i < bd->total_images; i++) {
img = &bd->images[i];
if (!(!strcmp(img->name, "fs0") || !strcmp(img->name, "test0")))
continue; /* Img is not what we want */
f = kzalloc(sizeof(*f));
INIT_LIST_HEAD(&f->list);
INIT_LIST_HEAD(&f->page_cache_list);
list_add(&f->list, &initdata->boot_file_list);
/*
* For boot files, we use the physical address of the memory
* file as its inode.
*/
f->inode.i_addr = img->phys_start;
f->length = img->phys_end - img->phys_start;
f->pager = &default_file_pager;
}
}
void initialise(void)
{
request_initdata(&initdata);
init_mm(&initdata);
init_boot_files(&initdata);
// printf("INITTASK: Initialised mock-up bootfiles.\n");
init_pm(&initdata);
// printf("INITTASK: Initialised the memory/process manager.\n");
printf("%s: Initialised the memory/process manager.\n", __TASKNAME__);
}

View File

@@ -8,6 +8,7 @@
#include <l4/types.h>
#include <l4/lib/list.h>
#include <l4/api/thread.h>
#include <l4/api/kip.h>
#include INC_GLUE(memory.h)
#include <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
@@ -72,17 +73,62 @@ struct tcb *create_init_tcb(struct tcb_head *tcbs)
return task;
}
/* Create temporary run-time files in memory to test with mmap */
struct vm_file *create_init_vmfile(struct list_head *vmfile_head)
{
struct vm_file *file = kzalloc(sizeof(*file));
INIT_LIST_HEAD(&file->list);
INIT_LIST_HEAD(&file->page_cache_list);
list_add(&file->list, vmfile_head);
return file;
}
int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
{
struct vm_file *file;
int err;
struct vm_file *file;
struct svc_image *img;
unsigned int sp, pc;
struct tcb *task;
struct task_ids ids;
struct bootdesc *bd = initdata->bootdesc;
INIT_LIST_HEAD(&tcb_head.list);
list_for_each_entry(file, &initdata->boot_file_list, list) {
struct tcb *task = create_init_tcb(tcbs);
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 };
INIT_LIST_HEAD(&initdata->boot_file_list);
for (int i = 0; i < bd->total_images; i++) {
img = &bd->images[i];
/* Skip self */
if (!strcmp(img->name, __PAGERNAME__))
continue;
/* Set up task ids */
if (!strcmp(img->name, __VFSNAME__)) {
ids.tid = VFS_TID;
ids.spid = VFS_TID;
} else {
ids.tid = -1;
ids.spid = -1;
}
/* Set up task's registers */
sp = align(USER_AREA_END - 1, 8);
pc = USER_AREA_START;
/* Create vm file and tcb */
file = create_init_vmfile(&initdata->boot_file_list);
task = create_init_tcb(tcbs);
/*
* For boot files, we use the physical address of the memory
* file as its mock-up inode.
*/
file->inode.i_addr = img->phys_start;
file->length = img->phys_end - img->phys_start;
file->pager = &default_file_pager;
/* mmap each task's physical image to task's address space. */
if ((err = do_mmap(file, 0, task, USER_AREA_START,
@@ -102,7 +148,7 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
/* 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);
printf("do_mmap: Mapping utcb failed with %d.\n", err);
goto error;
}
@@ -113,8 +159,8 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
goto error;
}
printf("New task with id: %d, space id: %d\n", ids.tid, ids.spid);
/* Use returned space and thread ids. */
printf("New task with id: %d, space id: %d\n", ids.tid, ids.spid);
task->tid = ids.tid;
task->spid = ids.spid;
@@ -154,7 +200,9 @@ void send_task_data(l4id_t requester)
int li, err;
if (requester != VFS_TID) {
printf("Task data is not requested by FS0, ignoring.\n");
printf("%s: Task data requested by %d, which is not "
"FS0 id %d, ignoring.\n", __TASKNAME__, requester,
VFS_TID);
return;
}

View File

@@ -16,11 +16,11 @@
void wait_pager(l4id_t partner)
{
printf("%s: Syncing with pager.\n", __TASKNAME__);
// printf("%s: Syncing with pager.\n", __TASKNAME__);
for (int i = 0; i < 6; i++)
write_mr(i, i);
l4_send(partner, L4_IPC_TAG_WAIT);
printf("Pager synced with us.\n");
// printf("Pager synced with us.\n");
}
void main(void)