From c8a55f88344c79bc47a2c9829033721a927906b3 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Tue, 10 Nov 2009 21:48:48 +0200 Subject: [PATCH] Stack recycling is added to the thread library. Still, it does not support thread trees which have more than one level depth. --- conts/libl4thread/include/l4thread/addr.h | 4 +- conts/libl4thread/include/l4thread/stack.h | 16 ++++++++ conts/libl4thread/include/l4thread/tcb.h | 1 + .../include/l4thread/utcb-common.h | 2 +- conts/libl4thread/src/addr.c | 14 +++---- conts/libl4thread/src/stack.c | 37 ++++++++++++++++++ conts/libl4thread/src/thread.c | 39 ++++++++++--------- conts/libl4thread/src/utcb-common.c | 12 +++--- conts/libl4thread/src/utcb.c | 4 +- 9 files changed, 93 insertions(+), 36 deletions(-) create mode 100644 conts/libl4thread/include/l4thread/stack.h create mode 100644 conts/libl4thread/src/stack.c diff --git a/conts/libl4thread/include/l4thread/addr.h b/conts/libl4thread/include/l4thread/addr.h index e7b4519..900d790 100644 --- a/conts/libl4thread/include/l4thread/addr.h +++ b/conts/libl4thread/include/l4thread/addr.h @@ -21,7 +21,7 @@ int address_pool_init_with_idpool(struct address_pool *pool, int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end, int size); -void *address_new(struct address_pool *pool, int npages); -int address_del(struct address_pool *, void *addr, int npages); +void *address_new(struct address_pool *pool, int nitems, int size); +int address_del(struct address_pool *, void *addr, int nitems, int size); #endif /* __ADDR_H__ */ diff --git a/conts/libl4thread/include/l4thread/stack.h b/conts/libl4thread/include/l4thread/stack.h new file mode 100644 index 0000000..d49a79a --- /dev/null +++ b/conts/libl4thread/include/l4thread/stack.h @@ -0,0 +1,16 @@ +/* + * Stack region helper routines. + * + * Copyright (C) 2009 B Labs Ltd. + */ +#ifndef __LIB_STACK_H__ +#define __LIB_STACK_H__ + +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); + +#endif /* __LIB_STACK_H__ */ diff --git a/conts/libl4thread/include/l4thread/tcb.h b/conts/libl4thread/include/l4thread/tcb.h index 1c81111..a2f399e 100644 --- a/conts/libl4thread/include/l4thread/tcb.h +++ b/conts/libl4thread/include/l4thread/tcb.h @@ -19,6 +19,7 @@ struct l4t_tcb { int tid; struct utcb_head *utcb_head; unsigned long utcb_addr; + unsigned long stack_addr; }; /* This struct keeps track of all the threads handled by the thread lib. */ diff --git a/conts/libl4thread/include/l4thread/utcb-common.h b/conts/libl4thread/include/l4thread/utcb-common.h index e5f5fef..47d71f8 100644 --- a/conts/libl4thread/include/l4thread/utcb-common.h +++ b/conts/libl4thread/include/l4thread/utcb-common.h @@ -1,5 +1,5 @@ /* - * UTCB handling common helper routines + * UTCB handling common helper routines. * * Copyright (C) 2009 B Labs Ltd. */ diff --git a/conts/libl4thread/src/addr.c b/conts/libl4thread/src/addr.c index 90c67dd..7318aca 100644 --- a/conts/libl4thread/src/addr.c +++ b/conts/libl4thread/src/addr.c @@ -33,21 +33,21 @@ int address_pool_init(struct address_pool *pool, return 0; } -void *address_new(struct address_pool *pool, int npages) +void *address_new(struct address_pool *pool, int nitems, int size) { - unsigned int pfn; + unsigned int idx; - if ((int)(pfn = ids_new_contiguous(pool->idpool, npages)) < 0) + if ((int)(idx = ids_new_contiguous(pool->idpool, nitems)) < 0) return 0; - return (void *)__pfn_to_addr(pfn) + pool->start; + return (void *)(idx * size) + pool->start; } -int address_del(struct address_pool *pool, void *addr, int npages) +int address_del(struct address_pool *pool, void *addr, int nitems, int size) { - unsigned long pfn = __pfn(page_align(addr) - pool->start); + unsigned long idx = (addr - (void *)pool->start) / size; - if (ids_del_contiguous(pool->idpool, pfn, npages) < 0) { + if (ids_del_contiguous(pool->idpool, idx, nitems) < 0) { printf("%s: Invalid address range returned to " "virtual address pool.\n", __FUNCTION__); return -1; diff --git a/conts/libl4thread/src/stack.c b/conts/libl4thread/src/stack.c new file mode 100644 index 0000000..a48de63 --- /dev/null +++ b/conts/libl4thread/src/stack.c @@ -0,0 +1,37 @@ +/* + * Stack management in libl4thread. + * + * Copyright © 2009 B Labs Ltd. + */ +#include +#include + +/* Stack virtual region pool */ +static struct address_pool stack_region_pool; + +int stack_pool_init(unsigned long stack_start, + unsigned long stack_end, + unsigned long stack_size) +{ + int err; + + /* Initialise the global stack virtual address pool. */ + if ((err = address_pool_init(&stack_region_pool, + stack_start, stack_end, + stack_size) < 0)) { + printf("Stack address pool initialisation failed.\n"); + return err; + } + + return 0; +} + +void *stack_new_space(int nitems, int size) +{ + return address_new(&stack_region_pool, nitems, size); +} + +int stack_delete_space(void *stack_address, int nitems, int size) +{ + return address_del(&stack_region_pool, stack_address, nitems, size); +} diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index 87e84b4..c7f643b 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -10,6 +10,7 @@ #include #include #include +#include /* Symbolic constants and macros */ #define IS_STACK_SETUP() (lib_stack_size) @@ -18,8 +19,6 @@ 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 */ @@ -60,11 +59,12 @@ int set_stack_params(unsigned long stack_top, } /* Arguments passed the validity tests. */ - /* Initialize internal variables */ - lib_stack_bot_addr = stack_bottom; - lib_stack_top_addr = stack_top; + /* Initialize internal variables. */ lib_stack_size = stack_size; + /* Init stack virtual address pool. */ + stack_pool_init(stack_top, stack_bottom, stack_size); + return 0; } @@ -75,6 +75,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, unsigned long utcb_addr; struct l4t_tcb *parent, *child; int err; + unsigned long stack_top_addr, stack_bot_addr; /* A few controls before granting access to thread creation */ // FIXME: check if utcb region is setup @@ -84,11 +85,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, 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; - } + // FIXME: Check if there is enough stack space // FIXME: Check if there is enough utcb space @@ -110,7 +107,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, return -ENOMEM; } - /* Get a utcb addr for this thread */ + /* Get a utcb addr. */ if (!(utcb_addr = get_utcb_addr(child))) { printf("libl4thread: No utcb address left.\n"); // FIXME: Check if there is any memory leak @@ -128,9 +125,14 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, return err; } + /* 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_bot_addr = stack_top_addr + lib_stack_size; + child->stack_addr = stack_top_addr; + /* Setup new thread pc, sp, utcb */ memset(&exregs, 0, sizeof(exregs)); - exregs_set_stack(&exregs, align((lib_stack_bot_addr - 1), 8)); + exregs_set_stack(&exregs, align((stack_bot_addr - 1), 8)); exregs_set_pc(&exregs, (unsigned long)setup_new_thread); exregs_set_utcb(&exregs, (unsigned long)utcb_addr); @@ -142,13 +144,11 @@ int l4thread_create(struct task_ids *ids, unsigned int flags, } /* First word of new stack is arg */ - ((unsigned long *)align((lib_stack_bot_addr - 1), 8))[0] = - (unsigned long)arg; + ((unsigned long *)align((stack_bot_addr - 1), 8))[0] = + (unsigned long)arg; /* Second word of new stack is function address */ - ((unsigned long *)align((lib_stack_bot_addr - 1), 8))[-1] = - (unsigned long)func; - /* Update the stack address */ - lib_stack_bot_addr -= lib_stack_size; + ((unsigned long *)align((stack_bot_addr - 1), 8))[-1] = + (unsigned long)func; /* Add child to the global task list */ child->tid = ids->tid; @@ -174,6 +174,9 @@ void l4thread_kill(struct task_ids *ids) /* Delete the utcb address. */ delete_utcb_addr(task); + /* Delete the stack region. */ + stack_delete_space((void *)task->stack_addr, 1, lib_stack_size); + /* Remove child from the global task list. */ l4t_global_remove_task(task); diff --git a/conts/libl4thread/src/utcb-common.c b/conts/libl4thread/src/utcb-common.c index 38df843..4356be9 100644 --- a/conts/libl4thread/src/utcb-common.c +++ b/conts/libl4thread/src/utcb-common.c @@ -1,7 +1,7 @@ /* - * UTCB management in Codezero + * UTCB management in libl4thread. * - * Copyright © 2009 B Labs Ltd + * Copyright © 2009 B Labs Ltd. */ #include #include @@ -26,14 +26,14 @@ int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end) return 0; } -static inline void *utcb_new_address(int npages) +static inline void *utcb_new_address(int nitems) { - return address_new(&utcb_region_pool, npages); + return address_new(&utcb_region_pool, nitems, PAGE_SIZE); } -static inline int utcb_delete_address(void *utcb_address, int npages) +static inline int utcb_delete_address(void *utcb_address, int nitems) { - return address_del(&utcb_region_pool, utcb_address, npages); + return address_del(&utcb_region_pool, utcb_address, nitems, PAGE_SIZE); } /* Return an empty utcb slot in this descriptor */ diff --git a/conts/libl4thread/src/utcb.c b/conts/libl4thread/src/utcb.c index 4dd7fef..2a20623 100644 --- a/conts/libl4thread/src/utcb.c +++ b/conts/libl4thread/src/utcb.c @@ -128,7 +128,7 @@ int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end) /* * This check guarantees two things: * 1. The range must be multiple of UTCB_SIZE, at least one item. - * 2. utcb_end is aligned on UTCB_SIZE + * 2. utcb_end is aligned on UTCB_SIZE. */ if ((utcb_end - utcb_start) % UTCB_SIZE) { printf("libl4thread: The given range size must be multiple " @@ -137,7 +137,7 @@ int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end) } /* Arguments passed the validity tests. */ - /* Init utcb virtual address pool */ + /* Init utcb virtual address pool. */ utcb_pool_init(utcb_start, utcb_end); /* The very first thread's utcb address is assigned. */