diff --git a/conts/libl4thread/SConscript b/conts/libl4thread/SConscript index 876bf5c..abcda27 100644 --- a/conts/libl4thread/SConscript +++ b/conts/libl4thread/SConscript @@ -18,10 +18,14 @@ Import('env') LIBMEM_RELDIR = 'conts/libmem' LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) -e = env.Clone() -e.Append(CPPPATH = ['include/l4thread', LIBMEM_DIR]) +LIBL4_RELDIR = 'conts/libl4' +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') -source = [Glob('*.[cS]') + Glob('src/*.[cS]')] +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) diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h index 31ced16..658d17b 100644 --- a/conts/libl4thread/include/l4thread/thread.h +++ b/conts/libl4thread/include/l4thread/thread.h @@ -1,9 +1,19 @@ /* + * Thread creation userspace helpers * + * Copyright (C) 2009 B Labs Ltd. */ #ifndef __LIB_THREAD_H__ #define __LIB_THREAD_H__ -void l4thread_print(void); +#define STACK_TOP_ADDR(stack) ((unsigned long)(stack)) +#define STACK_BOTTOM_ADDR(stack) \ + ((unsigned long)((stack) + (sizeof(stack)))) + +int set_stack_params(unsigned long stack_top_addr, + unsigned long stack_bottom_addr, + unsigned long stack_size); +int thread_create(struct task_ids *ids, unsigned int flags, + int (*func)(void *), void *arg); #endif /* __LIB_THREAD_H__ */ 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/arch-arm/new_thread.S b/conts/libl4thread/src/arch-arm/new_thread.S new file mode 100644 index 0000000..908569d --- /dev/null +++ b/conts/libl4thread/src/arch-arm/new_thread.S @@ -0,0 +1,11 @@ +#include + + +BEGIN_PROC(setup_new_thread) + ldr r0, [sp], #-4 @ Load first argument. + mov lr, pc @ Save return address + ldr pc, [sp], #-4 @ Load function pointer from stack +new_thread_exit: + b new_thread_exit @ We infinitely loop for now. +END_PROC(setup_new_thread) + diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index c362960..e11572c 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -1,11 +1,126 @@ /* + * Thread creation userspace helpers * + * Copyright (C) 2009 B Labs Ltd. */ #include +#include +#include +#include +#include -extern void utcb_test(unsigned long utcb_start, unsigned long utcb_end); +/* Symbolic constants and macros */ +#define STACK_PTR(addr) align((addr - 1), 8) +#define IS_STACK_SETUP() (lib_stack_size) -void l4thread_print(void) +/* Extern declarations */ +extern void setup_new_thread(void); + +/* Static variable definitions */ +static unsigned long lib_stack_top_addr; +static unsigned long lib_stack_bot_addr; +static unsigned long lib_stack_size; + +/* Function definitions */ +int set_stack_params(unsigned long stack_top_addr, + unsigned long stack_bottom_addr, + unsigned long stack_size) { - printf("Hello world from libl4thread!\n"); + if (IS_STACK_SETUP()) { + printf("libl4thread: You have already called: %s. Simply, " + "this will have no effect!\n", __FUNCTION__); + return -EPERM; + } + /* + * Stack grows downward so the top of the stack will have + * the lowest numbered address. + */ + if (stack_top_addr >= stack_bottom_addr) { + printf("libl4thread: Stack bottom address must be bigger " + "than stack top address!\n"); + return -EINVAL; + } + if (!stack_size) { + printf("libl4thread: Stack size cannot be zero!\n"); + return -EINVAL; + } + /* stack_size at least must be equal to the difference */ + if ((stack_bottom_addr - stack_top_addr) < stack_size) { + printf("libl4thread: the given range size is lesser than " + "the stack size!\n"); + return -EINVAL; + } + lib_stack_bot_addr = stack_bottom_addr; + lib_stack_top_addr = stack_top_addr; + lib_stack_size = stack_size; + + return 0; +} + +int thread_create(struct task_ids *ids, unsigned int flags, + int (*func)(void *), void *arg) +{ + struct exregs_data exregs; + int err; + + /* A few controls before granting access to thread creation */ + if (!IS_STACK_SETUP()) { + printf("libl4thread: Stack has not been set up. Before " + "calling thread_create, set_stack_params " + "has to be called!\n"); + return -EPERM; + } + + /* Is there enough stack space for the new thread? */ + if (lib_stack_top_addr >= lib_stack_bot_addr) { + printf("libl4thread: no stack space left!\n"); + return -ENOMEM; + } + + if (!(TC_SHARE_SPACE & flags)) { + printf("libl4thread: SAME address space is supported, which " + "means the only way to create a thread is with " + "TC_SHARE_SPACE flag. Other means of creating a " + "thread have not been supported yet!\n"); + return -EINVAL; + } + + /* Get parent's ids */ + l4_getid(ids); + + /* Create thread */ + if ((err = l4_thread_control(THREAD_CREATE | flags, ids)) < 0) { + printf("libl4thread: l4_thread_control(THREAD_CREATE) " + "failed with (%d)!\n", err); + return err; + } + + /* Setup new thread pc, sp, utcb */ + memset(&exregs, 0, sizeof(exregs)); + exregs_set_stack(&exregs, STACK_PTR(lib_stack_bot_addr)); + exregs_set_pc(&exregs, (unsigned long)setup_new_thread); + + if ((err = l4_exchange_registers(&exregs, ids->tid)) < 0) { + printf("libl4thread: l4_exchange_registers failed with " + "(%d)!\n", err); + return err; + } + + /* First word of new stack is arg */ + ((unsigned long *)STACK_PTR(lib_stack_bot_addr))[0] = + (unsigned long)arg; + /* Second word of new stack is function address */ + ((unsigned long *)STACK_PTR(lib_stack_bot_addr))[-1] = + (unsigned long)func; + /* Update the stack address */ + lib_stack_bot_addr -= lib_stack_size; + + /* Start the new thread */ + if ((err = l4_thread_control(THREAD_RUN, ids)) < 0) { + printf("libl4thread: l4_thread_control(THREAD_RUN) " + "failed with (%d)!\n", err); + return err; + } + + return 0; } diff --git a/conts/libl4thread/src/utcb_test.c b/conts/libl4thread/src/utcb_test.c deleted file mode 100644 index b05b7ca..0000000 --- a/conts/libl4thread/src/utcb_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This is for testing utcb port from POSIX - */ -#include -#include - -void utcb_test(unsigned long utcb_start, unsigned long utcb_end) -{ - struct utcb_desc *udesc[20]; - unsigned long addr; - int idx = -1; - - printf("%s\n", __FUNCTION__); - - utcb_pool_init(utcb_start, utcb_end); - - // Test-1 - for (int i = 0; i < 10; i++) - udesc[++idx] = utcb_new_desc(); - for (int j = 0; j < 20; ++j) - addr = utcb_new_slot(udesc[idx]); - - // Test 2 - for (int i = 0; i < 3; i++) - udesc[++idx] = utcb_new_desc(); - for (int j = 0; j < 10; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 8; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - for (int j = 0; j < 2; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 4; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - // Test 3 - for (int i = 0; i < 7; i++) { - utcb_delete_desc(udesc[idx]); - --idx; - } - for (int j = 0; j < 4; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 2; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - for (int i = 0; i < 3; i++) - udesc[++idx] = utcb_new_desc(); - for (int i = 0; i < 7; i++) { - utcb_delete_desc(udesc[idx]); - --idx; - } -}