mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Trying to fix merge / revert problems related to the thread library.
Revert "Merge branch 'libl4thread' of git://www.b-labs.co.uk/bora/git/codezero into bora"
This reverts commit dc7fd0d24d.
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Address allocation pool
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#ifndef __ADDR_H__
|
||||
#define __ADDR_H__
|
||||
|
||||
#include <idpool.h>
|
||||
|
||||
/* Address pool to allocate from a range of addresses */
|
||||
struct address_pool {
|
||||
struct id_pool *idpool;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
};
|
||||
|
||||
int address_pool_init_with_idpool(struct address_pool *pool,
|
||||
struct id_pool *idpool,
|
||||
unsigned long start, unsigned long end);
|
||||
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);
|
||||
|
||||
#endif /* __ADDR_H__ */
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Thread control block.
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#ifndef __LIB_TCB_H__
|
||||
#define __LIB_TCB_H__
|
||||
|
||||
#include <l4/lib/list.h>
|
||||
|
||||
/* Keeps all the struct utcb_descs belonging to a thread group together. */
|
||||
struct utcb_head {
|
||||
struct link list;
|
||||
};
|
||||
|
||||
/* A simple thread control block for the thread library. */
|
||||
struct l4t_tcb {
|
||||
struct link list;
|
||||
int tid;
|
||||
struct utcb_head *utcb_head;
|
||||
unsigned long utcb_addr;
|
||||
};
|
||||
|
||||
/* This struct keeps track of all the threads handled by the thread lib. */
|
||||
struct l4t_global_list {
|
||||
int total;
|
||||
struct link list;
|
||||
};
|
||||
|
||||
struct l4t_tcb *l4t_find_task(int tid);
|
||||
struct l4t_tcb *l4t_tcb_alloc_init(struct l4t_tcb *parent, unsigned int flags);
|
||||
void l4t_global_add_task(struct l4t_tcb *task);
|
||||
void l4t_global_remove_task(struct l4t_tcb *task);
|
||||
|
||||
#endif /* __LIB_TCB_H__ */
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Thread creation userspace helpers
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#ifndef __LIB_THREAD_H__
|
||||
#define __LIB_THREAD_H__
|
||||
|
||||
int 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 l4thread_create(struct task_ids *ids, unsigned int flags,
|
||||
int (*func)(void *), void *arg);
|
||||
void l4thread_kill(struct task_ids *ids);
|
||||
|
||||
#endif /* __LIB_THREAD_H__ */
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* UTCB handling common helper routines
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#ifndef __UTCB_COMMON_H__
|
||||
#define __UTCB_COMMON_H__
|
||||
|
||||
#include <l4/lib/list.h>
|
||||
|
||||
struct utcb_desc {
|
||||
struct link list;
|
||||
unsigned long utcb_base;
|
||||
struct id_pool *slots;
|
||||
};
|
||||
|
||||
int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end);
|
||||
|
||||
unsigned long utcb_new_slot(struct utcb_desc *desc);
|
||||
int utcb_delete_slot(struct utcb_desc *desc, unsigned long address);
|
||||
|
||||
struct utcb_desc *utcb_new_desc(void);
|
||||
int utcb_delete_desc(struct utcb_desc *desc);
|
||||
|
||||
#endif /* __UTCB_COMMON_H__ */
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* UTCB handling helper routines
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#ifndef __LIB_UTCB_H__
|
||||
#define __LIB_UTCB_H__
|
||||
|
||||
#include <tcb.h>
|
||||
|
||||
unsigned long get_utcb_addr(struct l4t_tcb *task);
|
||||
int delete_utcb_addr(struct l4t_tcb *task);
|
||||
|
||||
#endif /* __LIB_UTCB_H__ */
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This module allocates an unused address range from
|
||||
* a given memory region defined as the pool range.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#include <addr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Initializes an address pool, but uses an already
|
||||
* allocated id pool for it.
|
||||
*/
|
||||
int address_pool_init_with_idpool(struct address_pool *pool,
|
||||
struct id_pool *idpool,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
pool->idpool = idpool;
|
||||
pool->start = start;
|
||||
pool->end = end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int address_pool_init(struct address_pool *pool,
|
||||
unsigned long start, unsigned long end,
|
||||
int size)
|
||||
{
|
||||
if ((pool->idpool = id_pool_new_init((end - start) / size)) < 0)
|
||||
return (int)pool->idpool;
|
||||
pool->start = start;
|
||||
pool->end = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *address_new(struct address_pool *pool, int npages)
|
||||
{
|
||||
unsigned int pfn;
|
||||
|
||||
if ((int)(pfn = ids_new_contiguous(pool->idpool, npages)) < 0)
|
||||
return 0;
|
||||
|
||||
return (void *)__pfn_to_addr(pfn) + pool->start;
|
||||
}
|
||||
|
||||
int address_del(struct address_pool *pool, void *addr, int npages)
|
||||
{
|
||||
unsigned long pfn = __pfn(page_align(addr) - pool->start);
|
||||
|
||||
if (ids_del_contiguous(pool->idpool, pfn, npages) < 0) {
|
||||
printf("%s: Invalid address range returned to "
|
||||
"virtual address pool.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <l4/api/thread.h>
|
||||
#include <tcb.h>
|
||||
|
||||
/* Global task list. */
|
||||
struct l4t_global_list l4t_global_tasks = {
|
||||
.list = { &l4t_global_tasks.list, &l4t_global_tasks.list },
|
||||
.total = 0,
|
||||
};
|
||||
|
||||
/* Function definitions */
|
||||
void l4t_global_add_task(struct l4t_tcb *task)
|
||||
{
|
||||
BUG_ON(!list_empty(&task->list));
|
||||
list_insert_tail(&task->list, &l4t_global_tasks.list);
|
||||
l4t_global_tasks.total++;
|
||||
}
|
||||
|
||||
void l4t_global_remove_task(struct l4t_tcb *task)
|
||||
{
|
||||
BUG_ON(list_empty(&task->list));
|
||||
list_remove_init(&task->list);
|
||||
BUG_ON(--l4t_global_tasks.total < 0);
|
||||
}
|
||||
|
||||
struct l4t_tcb *l4t_find_task(int tid)
|
||||
{
|
||||
struct l4t_tcb *t;
|
||||
|
||||
list_foreach_struct(t, &l4t_global_tasks.list, list)
|
||||
if (t->tid == tid)
|
||||
return t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct l4t_tcb *l4t_tcb_alloc_init(struct l4t_tcb *parent, unsigned int flags)
|
||||
{
|
||||
struct l4t_tcb *task;
|
||||
|
||||
if (!(task = kzalloc(sizeof(struct l4t_tcb))))
|
||||
return PTR_ERR(-ENOMEM);
|
||||
|
||||
link_init(&task->list);
|
||||
|
||||
if ((parent) && (flags & TC_SHARE_SPACE))
|
||||
task->utcb_head = parent->utcb_head;
|
||||
else {
|
||||
if (!(task->utcb_head = kzalloc(sizeof(struct utcb_head))))
|
||||
return PTR_ERR(-ENOMEM);
|
||||
link_init(&task->utcb_head->list);
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Thread creation userspace helpers
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/exregs.h>
|
||||
#include <l4/api/thread.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <utcb.h>
|
||||
|
||||
/* Symbolic constants and macros */
|
||||
#define IS_STACK_SETUP() (lib_stack_size)
|
||||
|
||||
/* 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,
|
||||
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_bot_addr = stack_bottom;
|
||||
lib_stack_top_addr = stack_top;
|
||||
lib_stack_size = stack_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l4thread_create(struct task_ids *ids, unsigned int flags,
|
||||
int (*func)(void *), void *arg)
|
||||
{
|
||||
struct exregs_data exregs;
|
||||
unsigned long utcb_addr;
|
||||
struct l4t_tcb *parent, *child;
|
||||
int err;
|
||||
|
||||
/* A few controls before granting access to thread creation */
|
||||
// FIXME: check if utcb region is setup
|
||||
if (!IS_STACK_SETUP()) {
|
||||
printf("libl4thread: Stack and/or utcb have not been "
|
||||
"set up.\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;
|
||||
}
|
||||
|
||||
// FIXME: Check if there is enough utcb space
|
||||
|
||||
if (!(TC_SHARE_SPACE & flags)) {
|
||||
printf("libl4thread: Only allows shared space thread "
|
||||
"creation.\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get parent's ids and find the tcb belonging to it. */
|
||||
l4_getid(ids);
|
||||
if (!(parent = l4t_find_task(ids->tid)))
|
||||
return-ESRCH;
|
||||
|
||||
/* Allocate tcb for the child. */
|
||||
if (!(child = l4t_tcb_alloc_init(parent, flags))) {
|
||||
printf("libl4thread: No heap space left.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get a utcb addr for this thread */
|
||||
if (!(utcb_addr = get_utcb_addr(child))) {
|
||||
printf("libl4thread: No utcb address left.\n");
|
||||
// FIXME: Check if there is any memory leak
|
||||
kfree(child);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Create thread */
|
||||
if ((err = l4_thread_control(THREAD_CREATE | flags, ids)) < 0) {
|
||||
printf("libl4thread: l4_thread_control(THREAD_CREATE) "
|
||||
"failed with (%d).\n", err);
|
||||
// FIXME: Check if there is any memory leak
|
||||
kfree(child);
|
||||
delete_utcb_addr(child);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Setup new thread pc, sp, utcb */
|
||||
memset(&exregs, 0, sizeof(exregs));
|
||||
exregs_set_stack(&exregs, align((lib_stack_bot_addr - 1), 8));
|
||||
exregs_set_pc(&exregs, (unsigned long)setup_new_thread);
|
||||
exregs_set_utcb(&exregs, (unsigned long)utcb_addr);
|
||||
|
||||
if ((err = l4_exchange_registers(&exregs, ids->tid)) < 0) {
|
||||
printf("libl4thread: l4_exchange_registers failed with "
|
||||
"(%d).\n", err);
|
||||
// FIXME: Check if there is any memory leak
|
||||
return err;
|
||||
}
|
||||
|
||||
/* First word of new stack is arg */
|
||||
((unsigned long *)align((lib_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;
|
||||
|
||||
/* Add child to the global task list */
|
||||
child->tid = ids->tid;
|
||||
l4t_global_add_task(child);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void l4thread_kill(struct task_ids *ids)
|
||||
{
|
||||
struct l4t_tcb *task;
|
||||
|
||||
/* Find the task to be killed. */
|
||||
task = l4t_find_task(ids->tid);
|
||||
|
||||
/* Delete the utcb address. */
|
||||
delete_utcb_addr(task);
|
||||
|
||||
/* Remove child from the global task list. */
|
||||
l4t_global_remove_task(task);
|
||||
|
||||
// FIXME: We assume that main thread never leaves the scene
|
||||
kfree(task);
|
||||
|
||||
/* Finally, destroy the thread. */
|
||||
l4_thread_control(THREAD_DESTROY, ids);
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* UTCB management in Codezero
|
||||
*
|
||||
* Copyright © 2009 B Labs Ltd
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <addr.h>
|
||||
#include <utcb-common.h>
|
||||
#include <malloc/malloc.h>
|
||||
|
||||
/* Globally disjoint utcb virtual region pool */
|
||||
static struct address_pool utcb_region_pool;
|
||||
|
||||
int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Initialise the global utcb virtual address pool */
|
||||
if ((err = address_pool_init(&utcb_region_pool,
|
||||
utcb_start, utcb_end,
|
||||
UTCB_SIZE) < 0)) {
|
||||
printf("UTCB address pool initialisation failed.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void *utcb_new_address(int npages)
|
||||
{
|
||||
return address_new(&utcb_region_pool, npages);
|
||||
}
|
||||
|
||||
static inline int utcb_delete_address(void *utcb_address, int npages)
|
||||
{
|
||||
return address_del(&utcb_region_pool, utcb_address, npages);
|
||||
}
|
||||
|
||||
/* Return an empty utcb slot in this descriptor */
|
||||
unsigned long utcb_new_slot(struct utcb_desc *desc)
|
||||
{
|
||||
int slot;
|
||||
|
||||
if ((slot = id_new(desc->slots)) < 0)
|
||||
return 0;
|
||||
else
|
||||
return desc->utcb_base + (unsigned long)slot * UTCB_SIZE;
|
||||
}
|
||||
|
||||
int utcb_delete_slot(struct utcb_desc *desc, unsigned long address)
|
||||
{
|
||||
BUG_ON(id_del(desc->slots, (address - desc->utcb_base)
|
||||
/ UTCB_SIZE) < 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct utcb_desc *utcb_new_desc(void)
|
||||
{
|
||||
struct utcb_desc *d;
|
||||
|
||||
/* Allocate a new descriptor */
|
||||
if (!(d = kzalloc(sizeof(*d))))
|
||||
return 0;
|
||||
|
||||
link_init(&d->list);
|
||||
|
||||
/* We currently assume UTCB is smaller than PAGE_SIZE */
|
||||
BUG_ON(UTCB_SIZE > PAGE_SIZE);
|
||||
|
||||
/* Initialise utcb slots */
|
||||
d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE);
|
||||
|
||||
/* Obtain a new and unique utcb base */
|
||||
/* FIXME: Use variable size than a page */
|
||||
d->utcb_base = (unsigned long)utcb_new_address(1);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
int utcb_delete_desc(struct utcb_desc *desc)
|
||||
{
|
||||
/* Return descriptor address */
|
||||
utcb_delete_address((void *)desc->utcb_base, 1);
|
||||
|
||||
/* Free the descriptor */
|
||||
kfree(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* UTCB handling helper routines
|
||||
*
|
||||
* Copyright (C) 2009 B Labs Ltd.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/exregs.h>
|
||||
#include <errno.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <idpool.h>
|
||||
#include <utcb-common.h>
|
||||
#include <utcb.h>
|
||||
|
||||
/* Extern declarations */
|
||||
extern struct l4t_global_list l4t_global_tasks;
|
||||
|
||||
/* Function definitions */
|
||||
unsigned long get_utcb_addr(struct l4t_tcb *task)
|
||||
{
|
||||
struct utcb_desc *udesc;
|
||||
unsigned long slot;
|
||||
|
||||
/* Setting this up twice is a bug. */
|
||||
BUG_ON(task->utcb_addr);
|
||||
|
||||
/* Search for an empty utcb slot already allocated to this space. */
|
||||
list_foreach_struct(udesc, &task->utcb_head->list, list)
|
||||
if ((slot = utcb_new_slot(udesc)))
|
||||
goto found;
|
||||
|
||||
/* Allocate a new utcb memory region and return its base. */
|
||||
udesc = utcb_new_desc();
|
||||
slot = utcb_new_slot(udesc);
|
||||
list_insert(&udesc->list, &task->utcb_head->list);
|
||||
found:
|
||||
task->utcb_addr = slot;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
int delete_utcb_addr(struct l4t_tcb *task)
|
||||
{
|
||||
struct utcb_desc *udesc;
|
||||
|
||||
list_foreach_struct(udesc, &task->utcb_head->list, list) {
|
||||
/* FIXME: Use variable alignment than a page */
|
||||
/* Detect matching slot */
|
||||
if (page_align(task->utcb_addr) == udesc->utcb_base) {
|
||||
|
||||
/* Delete slot from the descriptor */
|
||||
utcb_delete_slot(udesc, task->utcb_addr);
|
||||
|
||||
/* Is the desc completely empty now? */
|
||||
if (id_is_empty(udesc->slots)) {
|
||||
/* Unlink desc from its list */
|
||||
list_remove_init(&udesc->list);
|
||||
/* Delete the descriptor */
|
||||
utcb_delete_desc(udesc);
|
||||
}
|
||||
return 0; /* Finished */
|
||||
}
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
static int set_utcb_addr(void)
|
||||
{
|
||||
struct exregs_data exregs;
|
||||
struct task_ids ids;
|
||||
struct l4t_tcb *task;
|
||||
struct utcb_desc *udesc;
|
||||
int err;
|
||||
|
||||
/* Create a task. */
|
||||
if (IS_ERR(task = l4t_tcb_alloc_init(0, 0)))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Add child to the global task list. */
|
||||
list_insert_tail(&task->list, &l4t_global_tasks.list);
|
||||
l4t_global_tasks.total++;
|
||||
|
||||
udesc = utcb_new_desc();
|
||||
task->utcb_addr = utcb_new_slot(udesc);
|
||||
list_insert(&udesc->list, &task->utcb_head->list);
|
||||
|
||||
memset(&exregs, 0, sizeof(exregs));
|
||||
exregs_set_utcb(&exregs, (unsigned long)task->utcb_addr);
|
||||
|
||||
l4_getid(&ids);
|
||||
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0) {
|
||||
printf("libl4thread: l4_exchange_registers failed with "
|
||||
"(%d).\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_utcb_params(unsigned long utcb_start, unsigned long utcb_end)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Ensure that arguments are valid. */
|
||||
// FIXME: Check if set_utcb_params is called
|
||||
/*if (IS_UTCB_SETUP()) {*/
|
||||
/*printf("libl4thread: You have already called: %s.\n",*/
|
||||
/*__FUNCTION__);*/
|
||||
/*return -EPERM;*/
|
||||
/*}*/
|
||||
if (!utcb_start || !utcb_end) {
|
||||
printf("libl4thread: Utcb address range cannot contain "
|
||||
"0x0 as a start and/or end address(es).\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Check if the start address is aligned on UTCB_SIZE. */
|
||||
if (utcb_start & !UTCB_SIZE) {
|
||||
printf("libl4thread: Utcb start address must be aligned "
|
||||
"on UTCB_SIZE(0x%x).\n", UTCB_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* The range must be a valid one. */
|
||||
if (utcb_start >= utcb_end) {
|
||||
printf("libl4thread: Utcb end address must be bigger "
|
||||
"than utcb start address.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
if ((utcb_end - utcb_start) % UTCB_SIZE) {
|
||||
printf("libl4thread: The given range size must be multiple "
|
||||
"of the utcb size(%d).\n", UTCB_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Arguments passed the validity tests. */
|
||||
|
||||
/* Init utcb virtual address pool */
|
||||
utcb_pool_init(utcb_start, utcb_end);
|
||||
|
||||
/* The very first thread's utcb address is assigned. */
|
||||
if ((err = set_utcb_addr()) < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user