From b31ab82437693ee7ee5e5a73574f324b60606b75 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Wed, 4 Nov 2009 20:48:59 +0200 Subject: [PATCH] The first step in creating a thread library. The difference between this thread library and the existing ones like pthreads is the necessity of informing the library about the address range of the stack and the l4 specific utcb. Utcb has not been supported yet. As for stack, there is also a drawback: library does not support mapping. In other words, the stack area in question has to be already mapped-in. Thus, for now we only support threads sharing their address spaces: TC_SHARE_SPACE. In this respect, it is very similar to pthreads. --- conts/libl4thread/SConscript | 10 +- conts/libl4thread/include/l4thread/thread.h | 12 +- conts/libl4thread/src/arch | 1 + conts/libl4thread/src/arch-arm/new_thread.S | 11 ++ conts/libl4thread/src/thread.c | 121 +++++++++++++++++++- conts/libl4thread/src/utcb_test.c | 55 --------- 6 files changed, 148 insertions(+), 62 deletions(-) create mode 120000 conts/libl4thread/src/arch create mode 100644 conts/libl4thread/src/arch-arm/new_thread.S delete mode 100644 conts/libl4thread/src/utcb_test.c 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; - } -}