mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
1
conts/libl4thread/src/arch
Symbolic link
1
conts/libl4thread/src/arch
Symbolic link
@@ -0,0 +1 @@
|
||||
arch-arm/
|
||||
11
conts/libl4thread/src/arch-arm/new_thread.S
Normal file
11
conts/libl4thread/src/arch-arm/new_thread.S
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <l4lib/arch/asm.h>
|
||||
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,11 +1,126 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This is for testing utcb port from POSIX
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <utcb.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user