From 496fba81c804bf95e32bde9d7a58e7db773c46a8 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Tue, 17 Nov 2009 21:48:46 +0200 Subject: [PATCH] A shared space multi-threaded example application presenting the use of the thread library. It also exemplifies how a new sample application can be added. --- config/cml/container_ruleset.template | 4 +- conts/examples/example2/SConstruct | 67 +++++++++++++++ conts/examples/example2/container.c | 21 +++++ conts/examples/example2/main.c | 116 ++++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 conts/examples/example2/SConstruct create mode 100644 conts/examples/example2/container.c create mode 100644 conts/examples/example2/main.c diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index d06580f..1e4a58f 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -133,12 +133,14 @@ cont%(cn)d_posix_pager_params 'Container %(cn)d POSIX Pager Parameters' cont%(cn)d_examples_params 'Example Applications List' CONT%(cn)d_EXAMPLE_APP0 'Empty Application' -CONT%(cn)d_EXAMPLE_APP1 'Hello world' +CONT%(cn)d_EXAMPLE_APP1 'Hello World' +CONT%(cn)d_EXAMPLE_APP2 'Thread Library Demo' choices cont%(cn)d_examples_params CONT%(cn)d_EXAMPLE_APP0 CONT%(cn)d_EXAMPLE_APP1 + CONT%(cn)d_EXAMPLE_APP2 default CONT%(cn)d_EXAMPLE_APP0 menu cont%(cn)d_default_pager_params diff --git a/conts/examples/example2/SConstruct b/conts/examples/example2/SConstruct new file mode 100644 index 0000000..63134bb --- /dev/null +++ b/conts/examples/example2/SConstruct @@ -0,0 +1,67 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd +# +import os, shelve, sys +from os.path import * + +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * +from config.configuration import * + + +config = configuration_retrieve() + +arch = config.arch + +LIBL4_RELDIR = 'conts/libl4' +KERNEL_INCLUDE = join(PROJROOT, 'include') +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') +LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR) + +# Locally important paths are here +LIBC_RELDIR = 'conts/libc' +LIBC_DIR = join(PROJROOT, LIBC_RELDIR) +LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) +LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \ + join(LIBC_DIR, 'include/arch' + '/' + arch)] + +LIBL4THREAD_RELDIR = 'conts/libl4thread' +LIBL4THREAD_DIR = join(PROJROOT, LIBL4THREAD_RELDIR) +LIBL4THREAD_LIBPATH = join(BUILDDIR, LIBL4THREAD_RELDIR) +LIBL4THREAD_INCLUDE = join(LIBL4THREAD_DIR, 'include') + +LIBMEM_RELDIR = 'conts/libmem' +LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) +LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR) +LIBMEM_INCLUDE = LIBMEM_DIR + +env = Environment(CC = 'arm-none-linux-gnueabi-gcc', + # We don't use -nostdinc because sometimes we need standard headers, + # such as stdarg.h e.g. for variable args, as in printk(). + CCFLAGS = ['-g', '-mcpu=arm926ej-s', '-nostdlib', '-ffreestanding', \ + '-std=gnu99', '-Wall', '-Werror'], + LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"], + ASFLAGS = ['-D__ASSEMBLY__'], + PROGSUFFIX = '.elf', # The suffix to use for final executable + ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path + LIBS = ['libl4thread', 'libl4', 'libmalloc', 'c-userspace', \ + 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBC_INCLUDE, \ + LIBL4THREAD_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBC_LIBPATH, LIBL4THREAD_LIBPATH, \ + LIBMEM_LIBPATH], + CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') + +src = Glob('*.[cS]') +src += Glob('src/*.[cS]') + +objs = env.Object(src) +prog = env.Program('main.elf', objs) +Depends(prog, 'include/linker.lds') diff --git a/conts/examples/example2/container.c b/conts/examples/example2/container.c new file mode 100644 index 0000000..f570c3d --- /dev/null +++ b/conts/examples/example2/container.c @@ -0,0 +1,21 @@ +/* + * Container entry point for pager + * + * Copyright (C) 2007-2009 B Labs Ltd. + */ + +#include +#include + + +extern void main(void); + +void __container_init(void) +{ + /* Generic L4 initialisation */ + __l4_init(); + + /* Entry to main */ + main(); +} + diff --git a/conts/examples/example2/main.c b/conts/examples/example2/main.c new file mode 100644 index 0000000..272021e --- /dev/null +++ b/conts/examples/example2/main.c @@ -0,0 +1,116 @@ +/* + * Main function for this container + */ +#include +#include +#include +#include + +/* Symbolic constants */ +#define STACK_SIZE 0x1000 +#define NTHREADS 10 + +/* Stack and utcb region */ +static char stack[NTHREADS * STACK_SIZE]; +DECLARE_UTCB_SPACE(utcb, NTHREADS) + +/* Function definitions */ +static void init_thread_lib(void) +{ + /* Thread lib is informed about the stack region. */ + l4_set_stack_params((unsigned long)stack, + (unsigned long)(stack + sizeof(stack)), + STACK_SIZE); + + /* Thread lib is informed about the utcb region. */ + l4_set_utcb_params((unsigned long)utcb, + (unsigned long)(utcb + sizeof(utcb))); + + /* Now, we are ready to make calls to the library. */ +} + +static int do_some_work1(void *arg) +{ + struct task_ids ids; + int value = *(int *)arg; + int j; + + l4_getid(&ids); + printf("tid = %d is called with the value of (%d).\n", + __raw_tid(ids.tid), value); + + /* Wait for a while before exiting */ + j = 0x400000; + while (--j) + ; + + return ids.tid; +} + +static int do_some_work2(void *arg) +{ + struct task_ids ids; + int value = *(int *)arg; + int j; + + l4_getid(&ids); + printf("tid = %d is called with the value of (%d).\n", + __raw_tid(ids.tid), value); + + /* Wait for a while before exiting */ + j = 0x400000; + while (--j) + ; + + l4_thread_exit(ids.tid); + + /* Should never reach here */ + return 0; +} + +static int thread_demo(void) +{ + struct task_ids ids[NTHREADS]; + int arg[NTHREADS]; + int j; + + memset(ids, 0, sizeof(ids)); + + /* Create threads. */ + for (int i = 0; i < NTHREADS; ++i) { + /* The argument passed to the thread in question. */ + arg[i] = i; + + /* Threads are created. */ + if (i % 2) + l4_thread_create(&ids[i], TC_SHARE_SPACE | TC_SHARE_PAGER, + do_some_work1, (void *)&arg[i]); + else + l4_thread_create(&ids[i], TC_SHARE_SPACE | TC_SHARE_PAGER, + do_some_work2, (void *)&arg[i]); + + /* Wait for a while before launching another thread. */ + j = 0x100000; + while (--j) + ; + } + + /* Wait for them to exit. */ + for (int i = 0; i < NTHREADS; ++i) + printf("tid = %d exited with (%d).\n", __raw_tid(ids[i].tid), + l4_thread_control(THREAD_WAIT, &ids[i])); + + return 0; +} + +int main(void) +{ + /* Before using the thread lib, we have to initialize it. */ + init_thread_lib(); + + /* Demonstrates the usage of the thread lib. */ + thread_demo(); + + return 0; +} +