diff --git a/SConstruct.userlibs b/SConstruct.userlibs index 652dca6..13b537e 100644 --- a/SConstruct.userlibs +++ b/SConstruct.userlibs @@ -49,6 +49,9 @@ libmm, libmc, libmalloc = SConscript('conts/libmem/SConscript', \ duplicate = 0, variant_dir = \ join(BUILDDIR, os.path.relpath('conts/libmem', PROJROOT))) +libl4thread = SConscript('conts/libl4thread/SConscript', \ + exports = { 'env' : env }, duplicate = 0, \ + variant_dir = join(BUILDDIR, os.path.relpath('conts/libl4thread', PROJROOT))) Alias('libl4', libl4) Alias('libdev', libdev) @@ -56,3 +59,4 @@ Alias('libc', libc) Alias('libmm', libmm) Alias('libmc', libmc) Alias('libmalloc', libmalloc) +Alias('libl4thread', libl4thread) diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index 707745e..f911d9b 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -1,7 +1,7 @@ symbols CONT%(cn)d_TYPE_LINUX 'Linux Container' -CONT%(cn)d_TYPE_BARE 'Bare Container' -CONT%(cn)d_TYPE_POSIX 'POSIX Container' +CONT%(cn)d_TYPE_EXAMPLES 'Examples Container' +CONT%(cn)d_TYPE_POSIX 'Codezero POSIX Services' CONT%(cn)d_TYPE_TEST 'Test Container' CONT%(cn)d_OPT_NAME 'Container Name' @@ -139,12 +139,12 @@ default CONT%(cn)d_VIRT4_END from 0xe0000000 default CONT%(cn)d_VIRT5_START from 0xe0000000 default CONT%(cn)d_VIRT5_END from 0xf0000000 -default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_BARE==y) ? "bare%(cn)d" : ((CONT%(cn)d_TYPE_TEST==y) ? "test%(cn)d" : "posix%(cn)d")) +default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_EXAMPLES==y) ? "example%(cn)d" : ((CONT%(cn)d_TYPE_TEST==y) ? "test%(cn)d" : "posix%(cn)d")) -when CONT%(cn)d_TYPE_LINUX==y suppress cont%(cn)d_bare_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_BARE==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_TEST==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_POSIX==y suppress cont%(cn)d_linux_pager_params +when CONT%(cn)d_TYPE_LINUX==y suppress cont%(cn)d_default_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_examples_params +when CONT%(cn)d_TYPE_EXAMPLES==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params +when CONT%(cn)d_TYPE_TEST==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_examples_params +when CONT%(cn)d_TYPE_POSIX==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_examples_params symbols cont%(cn)d_menu 'Container %(cn)d Parameters' @@ -154,10 +154,22 @@ container%(cn)d_type 'Container %(cn)d Type' container%(cn)d_options 'Container %(cn)d Options' cont%(cn)d_linux_pager_params 'Container %(cn)d Linux Pager Parameters' -cont%(cn)d_bare_pager_params 'Container %(cn)d Default Pager Parameters' +cont%(cn)d_default_pager_params 'Container %(cn)d Default Pager Parameters' cont%(cn)d_posix_pager_params 'Container %(cn)d POSIX Pager Parameters' -menu cont%(cn)d_bare_pager_params +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_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 CONT%(cn)d_PAGER_LMA@ CONT%(cn)d_PAGER_VMA@ @@ -625,21 +637,21 @@ menu cont%(cn)d_capability_list menu container%(cn)d_options CONT%(cn)d_OPT_NAME$ + cont%(cn)d_examples_params cont%(cn)d_linux_pager_params - cont%(cn)d_bare_pager_params + cont%(cn)d_default_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_physmem_list cont%(cn)d_virtmem_list cont%(cn)d_capability_list choices container%(cn)d_type - CONT%(cn)d_TYPE_BARE + CONT%(cn)d_TYPE_EXAMPLES + CONT%(cn)d_TYPE_LINUX CONT%(cn)d_TYPE_POSIX - CONT%(cn)d_TYPE_LINUX CONT%(cn)d_TYPE_TEST - default CONT%(cn)d_TYPE_BARE + default CONT%(cn)d_TYPE_EXAMPLES menu cont%(cn)d_menu container%(cn)d_type container%(cn)d_options - diff --git a/config/configuration.py b/config/configuration.py index ae2b829..6bf498c 100644 --- a/config/configuration.py +++ b/config/configuration.py @@ -12,6 +12,7 @@ class Container: self.name = None self.type = None self.id = id + self.example_id = 0 self.pager_lma = 0 self.pager_vma = 0 self.pager_size = 0 @@ -172,6 +173,9 @@ class configuration: dirname = val[1:-1].lower() self.containers[id].dirname = dirname self.containers[id].name = dirname + elif param[:len("EXAMPLE_APP")] == "EXAMPLE_APP": + param1 = param.split("_", 1) + self.containers[id].example_id = param1[1][-1:] elif param[:len("CAP_")] == "CAP_": prefix, param_rest = param.split('_', 1) prepare_capability(self.containers[id], param_rest, val) @@ -182,11 +186,10 @@ class configuration: self.containers[id].type = "linux" elif param2 == "POSIX": self.containers[id].type = "posix" - elif param2 == "BARE": - self.containers[id].type = "bare" + elif param2 == "EXAMPLES": + self.containers[id].type = "examples" elif param2 == "TEST": self.containers[id].type = "test" - # Extract parameters for containers def get_container_parameters(self, name, val): matchobj = re.match(r"(CONFIG_CONT){1}([0-9]){1}(\w+)", name) diff --git a/configure.py b/configure.py index 0f99d8b..5ab1410 100755 --- a/configure.py +++ b/configure.py @@ -4,7 +4,7 @@ import os, sys, shelve, shutil from os.path import join from config.projpaths import * from config.configuration import * -from scripts.bare.bare_generator import * +from scripts.examples.examples_generator import * from scripts.kernel.generate_kernel_cinfo import * from scripts.cml.generate_container_cml import * from optparse import OptionParser @@ -184,9 +184,9 @@ def configure_system(options, args): configuration_save(config) - # Generate bare container files if new ones defined - bare_cont_gen = BareContGenerator() - bare_cont_gen.bare_container_generate(config) + # Generate example container files if new ones defined + examples_cont_gen = ExamplesContGenerator() + examples_cont_gen.examples_container_generate(config) # Print out the configuration if asked if options.print_config: diff --git a/conts/examples/example0/SConstruct b/conts/examples/example0/SConstruct new file mode 100644 index 0000000..23e059c --- /dev/null +++ b/conts/examples/example0/SConstruct @@ -0,0 +1,55 @@ +# -*- 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)] + + +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 = ['gcc', 'libl4', 'c-userspace', 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBC_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBC_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/bare_src/container.c b/conts/examples/example0/container.c similarity index 91% rename from conts/bare_src/container.c rename to conts/examples/example0/container.c index 7bcbf9e..f570c3d 100644 --- a/conts/bare_src/container.c +++ b/conts/examples/example0/container.c @@ -8,7 +8,7 @@ #include -void main(void); +extern void main(void); void __container_init(void) { diff --git a/conts/bare_src/include/test.h b/conts/examples/example0/include/test.h similarity index 100% rename from conts/bare_src/include/test.h rename to conts/examples/example0/include/test.h diff --git a/conts/examples/example0/main.c b/conts/examples/example0/main.c new file mode 100644 index 0000000..8397a52 --- /dev/null +++ b/conts/examples/example0/main.c @@ -0,0 +1,12 @@ +/* + * Main function for this container + */ +#include +#include +#include + +int main(void) +{ + return 0; +} + diff --git a/conts/bare_src/src/test.c b/conts/examples/example0/src/test.c similarity index 100% rename from conts/bare_src/src/test.c rename to conts/examples/example0/src/test.c diff --git a/conts/bare_src/SConstruct b/conts/examples/example1/SConstruct similarity index 87% rename from conts/bare_src/SConstruct rename to conts/examples/example1/SConstruct index ae537d4..2130add 100644 --- a/conts/bare_src/SConstruct +++ b/conts/examples/example1/SConstruct @@ -13,20 +13,19 @@ sys.path.append(PROJRELROOT) from config.projpaths import * from config.configuration import * -from configure import * + config = configuration_retrieve() -arch = config.arch -gcc_cpu_flag = config.gcc_cpu_flag -# Wrapper library for system calls +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) -# Some user-space libraries +# Locally important paths are here LIBC_RELDIR = 'conts/libc' LIBC_DIR = join(PROJROOT, LIBC_RELDIR) LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) @@ -43,11 +42,11 @@ LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR) LIBMEM_INCLUDE = LIBMEM_DIR -env = Environment(CC = config.user_toolchain + 'gcc', +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', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \ - '-Werror', ('-mcpu=' + gcc_cpu_flag)], \ + 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 diff --git a/conts/examples/example1/container.c b/conts/examples/example1/container.c new file mode 100644 index 0000000..f570c3d --- /dev/null +++ b/conts/examples/example1/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/bare_src/hello.c b/conts/examples/example1/hello.c similarity index 100% rename from conts/bare_src/hello.c rename to conts/examples/example1/hello.c diff --git a/scripts/bare/__init__.py b/conts/examples/example1/include/test.h similarity index 100% rename from scripts/bare/__init__.py rename to conts/examples/example1/include/test.h diff --git a/conts/bare_src/main.c b/conts/examples/example1/main.c similarity index 100% rename from conts/bare_src/main.c rename to conts/examples/example1/main.c diff --git a/scripts/bare/files/SConstruct.in b/conts/examples/example1/src/test.c similarity index 100% rename from scripts/bare/files/SConstruct.in rename to conts/examples/example1/src/test.c 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; +} + diff --git a/conts/libl4thread/SConscript b/conts/libl4thread/SConscript new file mode 100644 index 0000000..abcda27 --- /dev/null +++ b/conts/libl4thread/SConscript @@ -0,0 +1,32 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd + +import os, sys + +# Get global paths +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * + +Import('env') + +LIBMEM_RELDIR = 'conts/libmem' +LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) + +LIBL4_RELDIR = 'conts/libl4' +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') + +e = env.Clone() +e.Append(CPPPATH = ['include/l4thread', LIBMEM_DIR, LIBL4_INCLUDE]) + +source = [Glob('*.[cS]') + Glob('src/*.[cS]') + Glob('src/arch/*.[cS]')] +objects = e.StaticObject(source) +library = e.StaticLibrary('l4thread', objects) + +Return('library') diff --git a/conts/libl4thread/include/l4thread/bit.h b/conts/libl4thread/include/l4thread/bit.h new file mode 100644 index 0000000..3ab6822 --- /dev/null +++ b/conts/libl4thread/include/l4thread/bit.h @@ -0,0 +1,42 @@ +#ifndef __BIT_H__ +#define __BIT_H__ + +unsigned int __clz(unsigned int bitvector); +int find_and_set_first_free_bit(u32 *word, unsigned int lastbit); +int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit, + int nbits); +int check_and_clear_bit(u32 *word, int bit); +int check_and_clear_contig_bits(u32 *word, int first, int nbits); + +int check_and_set_bit(u32 *word, int bit); + +/* Set */ +static inline void setbit(unsigned int *w, unsigned int flags) +{ + *w |= flags; +} + + +/* Clear */ +static inline void clrbit(unsigned int *w, unsigned int flags) +{ + *w &= ~flags; +} + +/* Test */ +static inline int tstbit(unsigned int *w, unsigned int flags) +{ + return *w & flags; +} + +/* Test and clear */ +static inline int tstclr(unsigned int *w, unsigned int flags) +{ + int res = tstbit(w, flags); + + clrbit(w, flags); + + return res; +} + +#endif /* __BIT_H__ */ diff --git a/conts/libl4thread/include/l4thread/idpool.h b/conts/libl4thread/include/l4thread/idpool.h new file mode 100644 index 0000000..67667c2 --- /dev/null +++ b/conts/libl4thread/include/l4thread/idpool.h @@ -0,0 +1,30 @@ +#ifndef __IDPOOL_H__ +#define __IDPOOL_H__ + +#include +#include +#include INC_GLUE(memory.h) + +struct id_pool { + int nwords; + int bitlimit; + u32 bitmap[]; +}; + +/* Copy one id pool to another by calculating its size */ +static inline void id_pool_copy(struct id_pool *to, struct id_pool *from, int totalbits) +{ + int nwords = BITWISE_GETWORD(totalbits); + + memcpy(to, from, nwords * SZ_WORD + sizeof(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); +int id_is_empty(struct id_pool *pool); +int ids_new_contiguous(struct id_pool *pool, int numids); +int ids_del_contiguous(struct id_pool *pool, int first, int numids); + +#endif /* __IDPOOL_H__ */ diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h index 8cd3125..7afe124 100644 --- a/conts/libl4thread/include/l4thread/thread.h +++ b/conts/libl4thread/include/l4thread/thread.h @@ -6,6 +6,10 @@ #ifndef __LIB_THREAD_H__ #define __LIB_THREAD_H__ +/* A helper macro easing utcb space creation. */ +#define DECLARE_UTCB_SPACE(name, entries) \ + char name[(entries + PAGE_SIZE / UTCB_SIZE) * UTCB_SIZE] ALIGN(PAGE_SIZE); + int l4_set_stack_params(unsigned long stack_top, unsigned long stack_bottom, unsigned long stack_size); diff --git a/conts/libl4thread/src/arch b/conts/libl4thread/src/arch new file mode 120000 index 0000000..3e9770f --- /dev/null +++ b/conts/libl4thread/src/arch @@ -0,0 +1 @@ +arch-arm/ \ No newline at end of file diff --git a/conts/libl4thread/src/bit.c b/conts/libl4thread/src/bit.c new file mode 100644 index 0000000..7c0ab4e --- /dev/null +++ b/conts/libl4thread/src/bit.c @@ -0,0 +1,108 @@ +/* + * Bit manipulation functions. + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include +#include INC_GLUE(memory.h) + +/* Emulation of ARM's CLZ (count leading zeroes) instruction */ +unsigned int __clz(unsigned int bitvector) +{ + unsigned int x = 0; + while((!(bitvector & ((unsigned)1 << 31))) && (x < 32)) { + bitvector <<= 1; + x++; + } + return x; +} + +int find_and_set_first_free_bit(u32 *word, unsigned int limit) +{ + int success = 0; + int i; + + for(i = 0; i < limit; i++) { + /* Find first unset bit */ + if (!(word[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i))) { + /* Set it */ + word[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i); + success = 1; + break; + } + } + /* Return bit just set */ + if (success) + return i; + else + return -1; +} + +int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit, + int nbits) +{ + int i = 0, first = 0, last = 0, found = 0; + + /* Can't allocate more than the limit */ + if (nbits > limit) + return -1; + + /* This is a state machine that checks n contiguous free bits. */ + while (i + nbits <= limit) { + first = i; + last = i; + while (!(word[BITWISE_GETWORD(last)] & BITWISE_GETBIT(last))) { + last++; + i++; + if (last == first + nbits) { + found = 1; + break; + } + } + if (found) + break; + i++; + } + + /* If found, set the bits */ + if (found) { + for (int x = first; x < first + nbits; x++) + word[BITWISE_GETWORD(x)] |= BITWISE_GETBIT(x); + return first; + } else + return -1; +} + +int check_and_clear_bit(u32 *word, int bit) +{ + /* Check that bit was set */ + if (word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit)) { + word[BITWISE_GETWORD(bit)] &= ~BITWISE_GETBIT(bit); + return 0; + } else { + printf("Trying to clear already clear bit\n"); + return -1; + } +} + +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; + } +} + +int check_and_clear_contig_bits(u32 *word, int first, int nbits) +{ + for (int i = first; i < first + nbits; i++) + if (check_and_clear_bit(word, i) < 0) + return -1; + return 0; +} + diff --git a/conts/posix/mm0/lib/bit.c b/conts/posix/mm0/lib/bit.c index 84750e3..6c1688b 100644 --- a/conts/posix/mm0/lib/bit.c +++ b/conts/posix/mm0/lib/bit.c @@ -51,8 +51,7 @@ int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit, return -1; /* This is a state machine that checks n contiguous free bits. */ - /* FIXME: It should be <= instead of <. Fix & test in a single patch */ - while (i + nbits < limit) { + while (i + nbits <= limit) { first = i; last = i; while (!(word[BITWISE_GETWORD(last)] & BITWISE_GETBIT(last))) { diff --git a/scripts/conts/containers.py b/scripts/conts/containers.py index 4514880..f42bca9 100755 --- a/scripts/conts/containers.py +++ b/scripts/conts/containers.py @@ -55,7 +55,7 @@ def source_to_builddir(srcdir, id): return join(BUILDDIR, cont_builddir) # We simply use SCons to figure all this out from container.id -# This is very similar to default container builder: +# This is very similar to examples container builder: # In fact this notion may become a standard convention for # calling specific bare containers def build_posix_container(config, projpaths, container): @@ -110,7 +110,7 @@ def build_default_container(config, projpaths, container): os.path.walk(projdir, glob_by_walk, ['*.elf', images]) # Calculate and store size of pager - pager_binary = "conts/bare" + str(container.id) + "/main.elf" + pager_binary = "conts/" + container.name + "/main.elf" config.containers[container.id].pager_size = \ conv_hex(elf_binary_size(join(PROJROOT, pager_binary))) @@ -124,7 +124,7 @@ def build_all_containers(): if container.type == 'linux': pass cont_images.append(build_linux_container(config, projpaths, container)) - elif container.type == 'bare': + elif container.type == 'examples': cont_images.append(build_default_container(config, projpaths, container)) elif container.type == 'posix': cont_images.append(build_posix_container(config, projpaths, container)) diff --git a/scripts/examples/__init__.py b/scripts/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/bare/bare_generator.py b/scripts/examples/examples_generator.py similarity index 78% rename from scripts/bare/bare_generator.py rename to scripts/examples/examples_generator.py index 3c6f1c2..17663d7 100755 --- a/scripts/bare/bare_generator.py +++ b/scripts/examples/examples_generator.py @@ -19,11 +19,11 @@ from config.projpaths import * from config.configuration import * from config.lib import * -class BareContGenerator: +class ExamplesContGenerator: def __init__(self): self.CONT_SRC_DIR = '' # Set when container is selected - self.BARE_SRC_BASEDIR = join(PROJROOT, 'conts') - self.EXAMPLE_PROJ_SRC_DIR = join(PROJROOT, 'conts/bare_src') + self.EXAMPLES_SRC_BASEDIR = join(PROJROOT, 'conts') + self.EXAMPLES_PROJ_SRC_DIR = join(PROJROOT, 'conts/examples') self.main_builder_name = 'build.py' self.main_configurator_name = 'configure.py' @@ -47,11 +47,12 @@ class BareContGenerator: self.build_desc_out = None self.src_main_out = None - def create_bare_srctree(self, config, cont): + def create_examples_srctree(self, config, cont): # First, create the base project directory and sources - shutil.copytree(self.EXAMPLE_PROJ_SRC_DIR, self.CONT_SRC_DIR) + str = 'example' + cont.example_id + shutil.copytree(join(self.EXAMPLES_PROJ_SRC_DIR, str), self.CONT_SRC_DIR) - def copy_bare_build_desc(self, config, cont): + def copy_examples_build_desc(self, config, cont): id_header = '[Container ID]\n' type_header = '\n[Container Type]\n' name_header = '\n[Container Name]\n' @@ -78,7 +79,7 @@ class BareContGenerator: fout.write(pager_physmem_header % ireg) fout.write('\t' + cont.physmem["START"][ireg] + ' - ' + cont.physmem["END"][ireg] + '\n') - def copy_bare_build_readme(self, config, cont): + def copy_examples_build_readme(self, config, cont): with open(self.build_readme_in) as fin: str = fin.read() with open(self.build_readme_out, 'w+') as fout: @@ -90,30 +91,30 @@ class BareContGenerator: self.main_configurator_name, \ self.main_configurator_name)) - def copy_bare_container_h(self, config, cont): + def copy_examples_container_h(self, config, cont): with open(self.container_h_in) as fin: str = fin.read() with open(self.container_h_out, 'w+') as fout: # Make any manipulations here fout.write(str % (cont.name, cont.id, cont.id)) - def create_bare_sources(self, config, cont): - self.create_bare_srctree(config, cont) - self.copy_bare_build_readme(config, cont) - self.copy_bare_build_desc(config, cont) + def create_examples_sources(self, config, cont): + self.create_examples_srctree(config, cont) + self.copy_examples_build_readme(config, cont) + self.copy_examples_build_desc(config, cont) self.generate_linker_script(config, cont) - self.copy_bare_container_h(config, cont) + self.copy_examples_container_h(config, cont) def update_configuration(self, config, cont): - self.copy_bare_build_desc(config, cont) + self.copy_examples_build_desc(config, cont) self.generate_linker_script(config, cont) - self.copy_bare_container_h(config, cont) + self.copy_examples_container_h(config, cont) - def check_create_bare_sources(self, config): + def check_create_examples_sources(self, config): for cont in config.containers: - if cont.type == "bare": + if cont.type == "examples": # Determine container directory name. - self.CONT_SRC_DIR = join(self.BARE_SRC_BASEDIR, cont.dirname.lower()) + self.CONT_SRC_DIR = join(self.EXAMPLES_SRC_BASEDIR, cont.dirname.lower()) self.build_readme_out = join(self.CONT_SRC_DIR, self.build_readme_name) self.build_desc_out = join(self.CONT_SRC_DIR, self.build_desc_name) self.linker_lds_out = join(join(self.CONT_SRC_DIR, 'include'), \ @@ -121,8 +122,8 @@ class BareContGenerator: self.container_h_out = join(join(self.CONT_SRC_DIR, 'include'), \ self.container_h_name) - if not os.path.exists(join(self.BARE_SRC_BASEDIR, cont.dirname)): - self.create_bare_sources(config, cont) + if not os.path.exists(join(self.EXAMPLES_SRC_BASEDIR, cont.dirname)): + self.create_examples_sources(config, cont) else: # Don't create new sources but update configuration self.update_configuration(config, cont) @@ -134,12 +135,12 @@ class BareContGenerator: fout.write(str % (conv_hex(cont.pager_vma), \ conv_hex(cont.pager_lma))) - def bare_container_generate(self, config): - self.check_create_bare_sources(config) + def examples_container_generate(self, config): + self.check_create_examples_sources(config) if __name__ == "__main__": config = configuration_retrieve() config.config_print() - bare_cont = BareContGenerator() - bare_cont.bare_container_generate(config) + examples_cont = ExamplesContGenerator() + examples_cont.examples_container_generate(config) diff --git a/scripts/examples/files/SConstruct.in b/scripts/examples/files/SConstruct.in new file mode 100644 index 0000000..e69de29 diff --git a/scripts/bare/files/build.readme.in b/scripts/examples/files/build.readme.in similarity index 100% rename from scripts/bare/files/build.readme.in rename to scripts/examples/files/build.readme.in diff --git a/scripts/bare/files/container.desc.in b/scripts/examples/files/container.desc.in similarity index 100% rename from scripts/bare/files/container.desc.in rename to scripts/examples/files/container.desc.in diff --git a/scripts/bare/files/container.h.in b/scripts/examples/files/container.h.in similarity index 100% rename from scripts/bare/files/container.h.in rename to scripts/examples/files/container.h.in diff --git a/scripts/bare/files/linker.lds.in b/scripts/examples/files/linker.lds.in similarity index 100% rename from scripts/bare/files/linker.lds.in rename to scripts/examples/files/linker.lds.in diff --git a/src/api/mutex.c b/src/api/mutex.c index d17fed3..829d190 100644 --- a/src/api/mutex.c +++ b/src/api/mutex.c @@ -210,7 +210,7 @@ int mutex_control_unlock(struct mutex_queue_head *mqhead, * now wake all of them up in FIFO order. * FIXME: Make sure this is FIFO order. It doesn't seem so. */ - wake_up(&mutex_queue->wqh_contenders, WAKEUP_ASYNC); + wake_up_all(&mutex_queue->wqh_contenders, WAKEUP_ASYNC); /* Since noone is left, delete the mutex queue */ mutex_control_remove(mqhead, mutex_queue); diff --git a/src/api/thread.c b/src/api/thread.c index 618a16d..1da38c3 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -105,12 +105,18 @@ int thread_destroy_children(void) void thread_destroy_self(unsigned int exit_code) { thread_destroy_children(); + + /* Wake up waiters */ + wake_up_all(¤t->wqh_send, WAKEUP_INTERRUPT); + wake_up_all(¤t->wqh_recv, WAKEUP_INTERRUPT); + current->exit_code = exit_code; sched_exit_sync(); } int thread_wait(struct ktcb *task) { + unsigned int exit_code; int ret; /* Wait until task switches to desired state */ @@ -118,8 +124,12 @@ int thread_wait(struct ktcb *task) task->state == TASK_DEAD, ret); if (ret < 0) return ret; - else - return (int)task->exit_code; + else { + exit_code = (int)task->exit_code; + tcb_remove(task); + tcb_delete(task); + return exit_code; + } } int thread_destroy(struct ktcb *task, unsigned int exit_code) diff --git a/src/arch/arm/v5/mmu_ops.S b/src/arch/arm/v5/mmu_ops.S index eb6d9da..ceda880 100644 --- a/src/arch/arm/v5/mmu_ops.S +++ b/src/arch/arm/v5/mmu_ops.S @@ -105,7 +105,7 @@ BEGIN_PROC(arm_invalidate_dcache) END_PROC(arm_invalidate_dcache) BEGIN_PROC(arm_clean_dcache) - mcr p15, 0 , pc, c7, c10, 3 @ Test/clean dcache line + mrc p15, 0 , pc, c7, c10, 3 @ Test/clean dcache line bne arm_clean_dcache mcr p15, 0, ip, c7, c10, 4 @ Drain WB mov pc, lr diff --git a/src/generic/scheduler.c b/src/generic/scheduler.c index f6934f0..4f88fd2 100644 --- a/src/generic/scheduler.c +++ b/src/generic/scheduler.c @@ -233,10 +233,10 @@ void sched_exit_sync(void) sched_rq_remove_task(current); current->state = TASK_DEAD; current->flags &= ~TASK_EXITING; - preempt_enable(); if (current->pagerid != current->tid) wake_up(¤t->wqh_pager, 0); + preempt_enable(); schedule(); } @@ -247,10 +247,10 @@ void sched_exit_async(void) sched_rq_remove_task(current); current->state = TASK_DEAD; current->flags &= ~TASK_EXITING; - preempt_enable(); if (current->pagerid != current->tid) wake_up(¤t->wqh_pager, 0); + preempt_enable(); need_resched = 1; } @@ -265,10 +265,10 @@ void sched_suspend_sync(void) sched_rq_remove_task(current); current->state = TASK_INACTIVE; current->flags &= ~TASK_SUSPENDING; - preempt_enable(); if (current->pagerid != current->tid) wake_up(¤t->wqh_pager, 0); + preempt_enable(); schedule(); } @@ -279,10 +279,10 @@ void sched_suspend_async(void) sched_rq_remove_task(current); current->state = TASK_INACTIVE; current->flags &= ~TASK_SUSPENDING; - preempt_enable(); if (current->pagerid != current->tid) wake_up(¤t->wqh_pager, 0); + preempt_enable(); need_resched = 1; }