diff --git a/conts/libl4thread/include/l4thread/stack.h b/conts/libl4thread/include/l4thread/stack.h index d49a79a..6f382e2 100644 --- a/conts/libl4thread/include/l4thread/stack.h +++ b/conts/libl4thread/include/l4thread/stack.h @@ -6,11 +6,14 @@ #ifndef __LIB_STACK_H__ #define __LIB_STACK_H__ +/* Symbolic constants and macros */ +#define IS_STACK_SETUP() (lib_stack_size) + int stack_pool_init(unsigned long stack_start, unsigned long stack_end, unsigned long stack_size); -void *stack_new_space(int nitems, int size); -int stack_delete_space(void *stack_address, int nitems, int size); +void *get_stack_space(int nitems, int size); +int delete_stack_space(void *stack_address, int nitems, int size); #endif /* __LIB_STACK_H__ */ diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h index 319233e..77246e3 100644 --- a/conts/libl4thread/include/l4thread/thread.h +++ b/conts/libl4thread/include/l4thread/thread.h @@ -6,13 +6,13 @@ #ifndef __LIB_THREAD_H__ #define __LIB_THREAD_H__ -int set_stack_params(unsigned long stack_top, +int l4_set_stack_params(unsigned long stack_top, unsigned long stack_bottom, unsigned long stack_size); -int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end); +int l4_set_utcb_params(unsigned long utcb_start, unsigned long utcb_end); -int l4thread_create(struct task_ids *ids, unsigned int flags, - int (*func)(void *), void *arg); -void l4thread_kill(struct task_ids *ids); +int l4_thread_create(struct task_ids *ids, unsigned int flags, + void *(*func)(void *), void *arg); +void l4_thread_exit(void *retval); #endif /* __LIB_THREAD_H__ */ diff --git a/conts/libl4thread/src/arch-arm/new_thread.S b/conts/libl4thread/src/arch-arm/new_thread.S index 908569d..1014817 100644 --- a/conts/libl4thread/src/arch-arm/new_thread.S +++ b/conts/libl4thread/src/arch-arm/new_thread.S @@ -2,10 +2,11 @@ BEGIN_PROC(setup_new_thread) - ldr r0, [sp], #-4 @ Load first argument. + ldr r0, [sp], #-4 @ Load first argument mov lr, pc @ Save return address ldr pc, [sp], #-4 @ Load function pointer from stack + b l4_thread_exit @ Call l4_thread_exit for cleanup new_thread_exit: - b new_thread_exit @ We infinitely loop for now. + b new_thread_exit @ Never reaches here END_PROC(setup_new_thread) diff --git a/conts/libl4thread/src/stack.c b/conts/libl4thread/src/stack.c index a48de63..36b86b8 100644 --- a/conts/libl4thread/src/stack.c +++ b/conts/libl4thread/src/stack.c @@ -5,6 +5,15 @@ */ #include #include +#include +#include +#include + +/* Extern declarations */ +extern struct l4_mutex lib_mutex; + +/* Global variables */ +unsigned long lib_stack_size; /* Stack virtual region pool */ static struct address_pool stack_region_pool; @@ -26,12 +35,66 @@ int stack_pool_init(unsigned long stack_start, return 0; } -void *stack_new_space(int nitems, int size) +void *get_stack_space(int nitems, int size) { return address_new(&stack_region_pool, nitems, size); } -int stack_delete_space(void *stack_address, int nitems, int size) +int delete_stack_space(void *stack_address, int nitems, int size) { return address_del(&stack_region_pool, stack_address, nitems, size); } + +int l4_set_stack_params(unsigned long stack_top, + unsigned long stack_bottom, + unsigned long stack_size) +{ + /* Ensure that arguments are valid. */ + // FIXME: Check if lib_stack_size is convenient to use + // for ensuring stack space is setup. + if (IS_STACK_SETUP()) { + printf("libl4thread: You have already called: %s.\n", + __FUNCTION__); + return -EPERM; + } + if (!stack_top || !stack_bottom) { + printf("libl4thread: Stack address range cannot contain " + "0x0 as a start and/or end address(es).\n"); + return -EINVAL; + } + // FIXME: Aligning should be taken into account. + /* + * Stack grows downward so the top of the stack will have + * the lowest numbered address. + */ + if (stack_top >= stack_bottom) { + 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 - stack_top) < stack_size) { + printf("libl4thread: The given range size is lesser than " + "the stack size(0x%x).\n", stack_size); + return -EINVAL; + } + /* Arguments passed the validity tests. */ + + /* Initialize internal variables. */ + lib_stack_size = stack_size; + + /* Init stack virtual address pool. */ + stack_pool_init(stack_top, stack_bottom, stack_size); + + /* Init the global mutex. */ + //FIXME: Ensure that l4thread_create will not be called + // before the mutex is initialized. + l4_mutex_init(&lib_mutex); + + return 0; +} + diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index c7f643b..d2f0c3e 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -5,71 +5,25 @@ */ #include #include +#include #include +#include #include #include #include #include #include -/* Symbolic constants and macros */ -#define IS_STACK_SETUP() (lib_stack_size) - /* Extern declarations */ extern void setup_new_thread(void); +extern unsigned long lib_stack_size; /* Static variable definitions */ -static unsigned long lib_stack_size; +struct l4_mutex lib_mutex; /* Function definitions */ -int set_stack_params(unsigned long stack_top, - unsigned long stack_bottom, - unsigned long stack_size) -{ - /* Ensure that arguments are valid. */ - if (IS_STACK_SETUP()) { - printf("libl4thread: You have already called: %s.\n", - __FUNCTION__); - return -EPERM; - } - if (!stack_top || !stack_bottom) { - printf("libl4thread: Stack address range cannot contain " - "0x0 as a start and/or end address(es).\n"); - return -EINVAL; - } - // FIXME: Aligning should be taken into account. - /* - * Stack grows downward so the top of the stack will have - * the lowest numbered address. - */ - if (stack_top >= stack_bottom) { - 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 - stack_top) < stack_size) { - printf("libl4thread: The given range size is lesser than " - "the stack size(0x%x).\n", stack_size); - return -EINVAL; - } - /* Arguments passed the validity tests. */ - - /* Initialize internal variables. */ - lib_stack_size = stack_size; - - /* Init stack virtual address pool. */ - stack_pool_init(stack_top, stack_bottom, stack_size); - - return 0; -} - -int l4thread_create(struct task_ids *ids, unsigned int flags, - int (*func)(void *), void *arg) +int l4_thread_create(struct task_ids *ids, unsigned int flags, + void *(*func)(void *), void *arg) { struct exregs_data exregs; unsigned long utcb_addr; @@ -96,6 +50,9 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, return -EINVAL; } + /* Before doing any operation get the global mutex. */ + l4_mutex_lock(&lib_mutex); + /* Get parent's ids and find the tcb belonging to it. */ l4_getid(ids); if (!(parent = l4t_find_task(ids->tid))) @@ -126,7 +83,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, } /* Get a stack space and calculate the bottom addr of the stack. */ - stack_top_addr = (unsigned long)stack_new_space(1, lib_stack_size); + stack_top_addr = (unsigned long)get_stack_space(1, lib_stack_size); stack_bot_addr = stack_top_addr + lib_stack_size; child->stack_addr = stack_top_addr; @@ -156,26 +113,37 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, /* Start the new thread */ if ((err = l4_thread_control(THREAD_RUN, ids)) < 0) { + // FIXME: Check if there is any memory leak printf("libl4thread: l4_thread_control(THREAD_RUN) " "failed with (%d).\n", err); return err; } + /* Release the global mutex. */ + l4_mutex_unlock(&lib_mutex); + return 0; } -void l4thread_kill(struct task_ids *ids) +void l4_thread_exit(void *retval) { struct l4t_tcb *task; + struct task_ids ids; - /* Find the task to be killed. */ - task = l4t_find_task(ids->tid); + /* Before doing any operation get the global mutex. */ + l4_mutex_lock(&lib_mutex); + + /* Find the task. */ + l4_getid(&ids); + /* Cant find the thread means it wasnt added to the list. */ + if (!(task = l4t_find_task(ids.tid))) + BUG(); /* Delete the utcb address. */ delete_utcb_addr(task); /* Delete the stack region. */ - stack_delete_space((void *)task->stack_addr, 1, lib_stack_size); + delete_stack_space((void *)task->stack_addr, 1, lib_stack_size); /* Remove child from the global task list. */ l4t_global_remove_task(task); @@ -183,6 +151,46 @@ void l4thread_kill(struct task_ids *ids) // FIXME: We assume that main thread never leaves the scene kfree(task); + /* Release the global mutex. */ + l4_mutex_unlock(&lib_mutex); + + /* Relinquish the control. */ + l4_exit(*(unsigned int *)retval); + + /* Should never reach here. */ + BUG(); +} + +int l4_thread_kill(struct task_ids *ids) +{ + struct l4t_tcb *task; + + /* Before doing any operation get the global mutex. */ + l4_mutex_lock(&lib_mutex); + + /* Find the task to be killed. */ + if (!(task = l4t_find_task(ids->tid))) { + l4_mutex_unlock(&lib_mutex); + return -ESRCH; + } + + /* Delete the utcb address. */ + delete_utcb_addr(task); + + /* Delete the stack region. */ + delete_stack_space((void *)task->stack_addr, 1, lib_stack_size); + + /* Remove child from the global task list. */ + l4t_global_remove_task(task); + + // FIXME: We assume that main thread never leaves the scene + kfree(task); + + /* Release the global mutex. */ + l4_mutex_unlock(&lib_mutex); + /* Finally, destroy the thread. */ l4_thread_control(THREAD_DESTROY, ids); + + return 0; } diff --git a/conts/libl4thread/src/utcb.c b/conts/libl4thread/src/utcb.c index 2a20623..8415ff8 100644 --- a/conts/libl4thread/src/utcb.c +++ b/conts/libl4thread/src/utcb.c @@ -97,7 +97,7 @@ static int set_utcb_addr(void) return 0; } -int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end) +int l4_set_utcb_params(unsigned long utcb_start, unsigned long utcb_end) { int err;