mirror of
https://github.com/drasko/codezero.git
synced 2026-08-29 17:50:07 +02:00
Stack recycling is added to the thread library.
Still, it does not support thread trees which have more than one level depth.
This commit is contained in:
@@ -21,7 +21,7 @@ int address_pool_init_with_idpool(struct address_pool *pool,
|
|||||||
int address_pool_init(struct address_pool *pool,
|
int address_pool_init(struct address_pool *pool,
|
||||||
unsigned long start, unsigned long end,
|
unsigned long start, unsigned long end,
|
||||||
int size);
|
int size);
|
||||||
void *address_new(struct address_pool *pool, int npages);
|
void *address_new(struct address_pool *pool, int nitems, int size);
|
||||||
int address_del(struct address_pool *, void *addr, int npages);
|
int address_del(struct address_pool *, void *addr, int nitems, int size);
|
||||||
|
|
||||||
#endif /* __ADDR_H__ */
|
#endif /* __ADDR_H__ */
|
||||||
|
|||||||
16
conts/libl4thread/include/l4thread/stack.h
Normal file
16
conts/libl4thread/include/l4thread/stack.h
Normal file
@@ -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__ */
|
||||||
@@ -19,6 +19,7 @@ struct l4t_tcb {
|
|||||||
int tid;
|
int tid;
|
||||||
struct utcb_head *utcb_head;
|
struct utcb_head *utcb_head;
|
||||||
unsigned long utcb_addr;
|
unsigned long utcb_addr;
|
||||||
|
unsigned long stack_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This struct keeps track of all the threads handled by the thread lib. */
|
/* This struct keeps track of all the threads handled by the thread lib. */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* UTCB handling common helper routines
|
* UTCB handling common helper routines.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 B Labs Ltd.
|
* Copyright (C) 2009 B Labs Ltd.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -33,21 +33,21 @@ int address_pool_init(struct address_pool *pool,
|
|||||||
return 0;
|
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 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 "
|
printf("%s: Invalid address range returned to "
|
||||||
"virtual address pool.\n", __FUNCTION__);
|
"virtual address pool.\n", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
37
conts/libl4thread/src/stack.c
Normal file
37
conts/libl4thread/src/stack.c
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Stack management in libl4thread.
|
||||||
|
*
|
||||||
|
* Copyright © 2009 B Labs Ltd.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <addr.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <l4/api/errno.h>
|
#include <l4/api/errno.h>
|
||||||
#include <malloc/malloc.h>
|
#include <malloc/malloc.h>
|
||||||
#include <utcb.h>
|
#include <utcb.h>
|
||||||
|
#include <stack.h>
|
||||||
|
|
||||||
/* Symbolic constants and macros */
|
/* Symbolic constants and macros */
|
||||||
#define IS_STACK_SETUP() (lib_stack_size)
|
#define IS_STACK_SETUP() (lib_stack_size)
|
||||||
@@ -18,8 +19,6 @@
|
|||||||
extern void setup_new_thread(void);
|
extern void setup_new_thread(void);
|
||||||
|
|
||||||
/* Static variable definitions */
|
/* Static variable definitions */
|
||||||
static unsigned long lib_stack_top_addr;
|
|
||||||
static unsigned long lib_stack_bot_addr;
|
|
||||||
static unsigned long lib_stack_size;
|
static unsigned long lib_stack_size;
|
||||||
|
|
||||||
/* Function definitions */
|
/* Function definitions */
|
||||||
@@ -60,11 +59,12 @@ int set_stack_params(unsigned long stack_top,
|
|||||||
}
|
}
|
||||||
/* Arguments passed the validity tests. */
|
/* Arguments passed the validity tests. */
|
||||||
|
|
||||||
/* Initialize internal variables */
|
/* Initialize internal variables. */
|
||||||
lib_stack_bot_addr = stack_bottom;
|
|
||||||
lib_stack_top_addr = stack_top;
|
|
||||||
lib_stack_size = stack_size;
|
lib_stack_size = stack_size;
|
||||||
|
|
||||||
|
/* Init stack virtual address pool. */
|
||||||
|
stack_pool_init(stack_top, stack_bottom, stack_size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +75,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags,
|
|||||||
unsigned long utcb_addr;
|
unsigned long utcb_addr;
|
||||||
struct l4t_tcb *parent, *child;
|
struct l4t_tcb *parent, *child;
|
||||||
int err;
|
int err;
|
||||||
|
unsigned long stack_top_addr, stack_bot_addr;
|
||||||
|
|
||||||
/* A few controls before granting access to thread creation */
|
/* A few controls before granting access to thread creation */
|
||||||
// FIXME: check if utcb region is setup
|
// FIXME: check if utcb region is setup
|
||||||
@@ -84,11 +85,7 @@ int l4thread_create(struct task_ids *ids, unsigned int flags,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is there enough stack space for the new thread? */
|
// FIXME: Check if there is enough stack space
|
||||||
if (lib_stack_top_addr >= lib_stack_bot_addr) {
|
|
||||||
printf("libl4thread: No stack space left.\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Check if there is enough utcb 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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a utcb addr for this thread */
|
/* Get a utcb addr. */
|
||||||
if (!(utcb_addr = get_utcb_addr(child))) {
|
if (!(utcb_addr = get_utcb_addr(child))) {
|
||||||
printf("libl4thread: No utcb address left.\n");
|
printf("libl4thread: No utcb address left.\n");
|
||||||
// FIXME: Check if there is any memory leak
|
// FIXME: Check if there is any memory leak
|
||||||
@@ -128,9 +125,14 @@ int l4thread_create(struct task_ids *ids, unsigned int flags,
|
|||||||
return err;
|
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 */
|
/* Setup new thread pc, sp, utcb */
|
||||||
memset(&exregs, 0, sizeof(exregs));
|
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_pc(&exregs, (unsigned long)setup_new_thread);
|
||||||
exregs_set_utcb(&exregs, (unsigned long)utcb_addr);
|
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 */
|
/* First word of new stack is arg */
|
||||||
((unsigned long *)align((lib_stack_bot_addr - 1), 8))[0] =
|
((unsigned long *)align((stack_bot_addr - 1), 8))[0] =
|
||||||
(unsigned long)arg;
|
(unsigned long)arg;
|
||||||
/* Second word of new stack is function address */
|
/* Second word of new stack is function address */
|
||||||
((unsigned long *)align((lib_stack_bot_addr - 1), 8))[-1] =
|
((unsigned long *)align((stack_bot_addr - 1), 8))[-1] =
|
||||||
(unsigned long)func;
|
(unsigned long)func;
|
||||||
/* Update the stack address */
|
|
||||||
lib_stack_bot_addr -= lib_stack_size;
|
|
||||||
|
|
||||||
/* Add child to the global task list */
|
/* Add child to the global task list */
|
||||||
child->tid = ids->tid;
|
child->tid = ids->tid;
|
||||||
@@ -174,6 +174,9 @@ void l4thread_kill(struct task_ids *ids)
|
|||||||
/* Delete the utcb address. */
|
/* Delete the utcb address. */
|
||||||
delete_utcb_addr(task);
|
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. */
|
/* Remove child from the global task list. */
|
||||||
l4t_global_remove_task(task);
|
l4t_global_remove_task(task);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* UTCB management in Codezero
|
* UTCB management in libl4thread.
|
||||||
*
|
*
|
||||||
* Copyright © 2009 B Labs Ltd
|
* Copyright © 2009 B Labs Ltd.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <addr.h>
|
#include <addr.h>
|
||||||
@@ -26,14 +26,14 @@ int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end)
|
|||||||
return 0;
|
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 */
|
/* Return an empty utcb slot in this descriptor */
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end)
|
|||||||
/*
|
/*
|
||||||
* This check guarantees two things:
|
* This check guarantees two things:
|
||||||
* 1. The range must be multiple of UTCB_SIZE, at least one item.
|
* 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) {
|
if ((utcb_end - utcb_start) % UTCB_SIZE) {
|
||||||
printf("libl4thread: The given range size must be multiple "
|
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. */
|
/* Arguments passed the validity tests. */
|
||||||
|
|
||||||
/* Init utcb virtual address pool */
|
/* Init utcb virtual address pool. */
|
||||||
utcb_pool_init(utcb_start, utcb_end);
|
utcb_pool_init(utcb_start, utcb_end);
|
||||||
|
|
||||||
/* The very first thread's utcb address is assigned. */
|
/* The very first thread's utcb address is assigned. */
|
||||||
|
|||||||
Reference in New Issue
Block a user