mirror of
https://github.com/drasko/codezero.git
synced 2026-04-17 17:29:04 +02:00
Kernel updates since December 2009
This commit is contained in:
@@ -18,7 +18,7 @@ from configure import *
|
||||
config = configuration_retrieve()
|
||||
arch = config.arch
|
||||
platform = config.platform
|
||||
gcc_cpu_flag = config.gcc_cpu_flag
|
||||
gcc_arch_flag = config.gcc_arch_flag
|
||||
|
||||
# Wrapper library for system calls
|
||||
LIBL4_RELDIR = 'conts/libl4'
|
||||
@@ -37,20 +37,18 @@ LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \
|
||||
LIBDEV_RELDIR = 'conts/libdev'
|
||||
LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR)
|
||||
LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace')
|
||||
LIBDEV_INCLUDE = [join(LIBDEV_DIR, 'uart/include'),
|
||||
join(LIBDEV_DIR, 'timer/sp804/include')]
|
||||
LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper()
|
||||
LIBDEV_INCLUDE = join(LIBDEV_DIR, 'include')
|
||||
|
||||
LIBMEM_RELDIR = 'conts/libmem'
|
||||
LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR)
|
||||
LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR)
|
||||
LIBMEM_INCLUDE = LIBMEM_DIR
|
||||
|
||||
env = Environment(CC = config.user_toolchain + 'gcc',
|
||||
env = Environment(CC = config.toolchain + 'gcc',
|
||||
# We don't use -nostdinc because sometimes we need standard headers,
|
||||
# such as stdarg.h e.g. for variable args, as in printk().
|
||||
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \
|
||||
'-Werror', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS], \
|
||||
'-Werror', '-march=' + gcc_arch_flag], \
|
||||
LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\
|
||||
ASFLAGS = ['-D__ASSEMBLY__'], \
|
||||
PROGSUFFIX = '.elf', # The suffix to use for final executable
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#ifndef __THREAD_H__
|
||||
#define __THREAD_H__
|
||||
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/macros.h>
|
||||
#include L4LIB_INC_ARCH(syslib.h)
|
||||
#include L4LIB_INC_ARCH(syscalls.h)
|
||||
#include <l4lib/exregs.h>
|
||||
#include <l4/api/thread.h>
|
||||
|
||||
|
||||
@@ -8,15 +8,76 @@
|
||||
#include <l4/lib/list.h>
|
||||
#include <l4lib/types.h>
|
||||
|
||||
/* Structure representing the sleeping tasks */
|
||||
struct sleeper_task {
|
||||
struct link list;
|
||||
l4id_t tid; /* tid of sleeping task */
|
||||
int retval; /* return value on wakeup */
|
||||
};
|
||||
|
||||
/* list of tasks to be woken up */
|
||||
struct wake_task_list {
|
||||
struct link head;
|
||||
struct link *end; /* optimization */
|
||||
struct l4_mutex lock; /* lock for sanity of head */
|
||||
};
|
||||
|
||||
#define BUCKET_BASE_LEVEL_BITS 8
|
||||
#define BUCKET_HIGHER_LEVEL_BITS 6
|
||||
|
||||
#define BUCKET_BASE_LEVEL_SIZE (1 << BUCKET_BASE_LEVEL_BITS)
|
||||
#define BUCKET_HIGHER_LEVEL_SIZE (1 << BUCKET_HIGHER_LEVEL_BITS)
|
||||
|
||||
#define BUCKET_BASE_LEVEL_MASK 0xFF
|
||||
#define BUCKET_HIGHER_LEVEL_MASK 0x3F
|
||||
|
||||
/*
|
||||
* Web of sleeping tasks
|
||||
* based on timer wheel base algorithm
|
||||
*/
|
||||
struct sleeper_task_bucket {
|
||||
struct link bucket_level0[BUCKET_BASE_LEVEL_SIZE];
|
||||
struct link bucket_level1[BUCKET_HIGHER_LEVEL_SIZE];
|
||||
struct link bucket_level2[BUCKET_HIGHER_LEVEL_SIZE];
|
||||
struct link bucket_level3[BUCKET_HIGHER_LEVEL_SIZE];
|
||||
struct link bucket_level4[BUCKET_HIGHER_LEVEL_SIZE];
|
||||
};
|
||||
|
||||
/* Macros to extract bucket levels */
|
||||
#define GET_BUCKET_LEVEL4(x) \
|
||||
((x >> (BUCKET_BASE_LEVEL_BITS + (3 * BUCKET_HIGHER_LEVEL_BITS))) & \
|
||||
BUCKET_HIGHER_LEVEL_MASK)
|
||||
#define GET_BUCKET_LEVEL3(x) \
|
||||
((x >> (BUCKET_BASE_LEVEL_BITS + (2 * BUCKET_HIGHER_LEVEL_BITS))) & \
|
||||
BUCKET_HIGHER_LEVEL_MASK)
|
||||
#define GET_BUCKET_LEVEL2(x) \
|
||||
((x >> (BUCKET_BASE_LEVEL_BITS + (1 * BUCKET_HIGHER_LEVEL_BITS))) & \
|
||||
BUCKET_HIGHER_LEVEL_MASK)
|
||||
#define GET_BUCKET_LEVEL1(x) \
|
||||
((x >> BUCKET_BASE_LEVEL_BITS) & BUCKET_HIGHER_LEVEL_MASK)
|
||||
#define GET_BUCKET_LEVEL0(x) (x & BUCKET_BASE_LEVEL_MASK)
|
||||
|
||||
/* Macros to find bucket level */
|
||||
#define IS_IN_LEVEL0_BUCKET(x) \
|
||||
(x < (1 << BUCKET_BASE_LEVEL_BITS))
|
||||
#define IS_IN_LEVEL1_BUCKET(x) \
|
||||
(x < (1 << (BUCKET_BASE_LEVEL_BITS + BUCKET_HIGHER_LEVEL_BITS)))
|
||||
#define IS_IN_LEVEL2_BUCKET(x) \
|
||||
(x < (1 << (BUCKET_BASE_LEVEL_BITS + (2 * BUCKET_HIGHER_LEVEL_BITS))))
|
||||
#define IS_IN_LEVEL3_BUCKET(x) \
|
||||
(x < (1 << (BUCKET_BASE_LEVEL_BITS + (3 * BUCKET_HIGHER_LEVEL_BITS))))
|
||||
|
||||
/*
|
||||
* Timer structure
|
||||
* TODO: Keep timer 32 bit for time being,
|
||||
* we will make it 64 in future
|
||||
*/
|
||||
struct timer {
|
||||
int slot; /* Notify slot on utcb */
|
||||
unsigned int base; /* Virtual base address */
|
||||
u64 count; /* Counter */
|
||||
struct link task_list; /* List of sleepers */
|
||||
struct l4_mutex lock; /* Lock for structure */
|
||||
unsigned long base; /* Virtual base address */
|
||||
unsigned int count; /* Counter/jiffies */
|
||||
struct sleeper_task_bucket task_list; /* List of sleeping tasks */
|
||||
struct l4_mutex lock; /* Lock for sleeper_task_bucket */
|
||||
struct capability cap; /* Capability describing timer */
|
||||
};
|
||||
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
/*
|
||||
* Timer service for userspace
|
||||
*/
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/addr.h>
|
||||
#include <l4lib/exregs.h>
|
||||
#include <l4lib/lib/addr.h>
|
||||
#include <l4lib/irq.h>
|
||||
#include <l4lib/ipcdefs.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <l4/api/irq.h>
|
||||
|
||||
#include <l4/api/capability.h>
|
||||
#include <l4/generic/cap-types.h>
|
||||
#include <l4/api/space.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <l4lib/capability/cap_print.h>
|
||||
#include <container.h>
|
||||
#include "sp804_timer.h"
|
||||
#include <linker.h>
|
||||
#include <timer.h>
|
||||
#include <thread.h>
|
||||
#include <libdev/timer.h>
|
||||
|
||||
/* Frequency of timer in MHz */
|
||||
#define TIMER_FREQUENCY 1
|
||||
|
||||
#define TIMERS_TOTAL 1
|
||||
|
||||
/* Capabilities of this service */
|
||||
static struct capability caparray[32];
|
||||
static int total_caps = 0;
|
||||
|
||||
/* Total number of timer chips being handled by us */
|
||||
#define TIMERS_TOTAL 1
|
||||
static struct timer timer[TIMERS_TOTAL];
|
||||
|
||||
/* Deafult timer to be used for sleep/wake etc purposes */
|
||||
#define SLEEP_WAKE_TIMER 0
|
||||
|
||||
/* tasks whose sleep time has finished */
|
||||
struct wake_task_list wake_tasks;
|
||||
|
||||
/* tid of handle_request thread */
|
||||
l4id_t tid_ipc_handler;
|
||||
|
||||
int cap_read_all()
|
||||
{
|
||||
int ncaps;
|
||||
@@ -52,7 +56,6 @@ int cap_read_all()
|
||||
"complete CAP_CONTROL_READ_CAPS request.\n");
|
||||
BUG();
|
||||
}
|
||||
cap_array_print(total_caps, caparray);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -74,6 +77,89 @@ int cap_share_all_with_space()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize timer devices
|
||||
*/
|
||||
void timer_struct_init(struct timer* timer, unsigned long base)
|
||||
{
|
||||
timer->base = base;
|
||||
timer->count = 0;
|
||||
timer->slot = 0;
|
||||
l4_mutex_init(&timer->lock);
|
||||
|
||||
for (int i = 0; i < BUCKET_BASE_LEVEL_SIZE ; ++i) {
|
||||
link_init(&timer->task_list.bucket_level0[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BUCKET_HIGHER_LEVEL_SIZE ; ++i) {
|
||||
link_init(&timer->task_list.bucket_level1[i]);
|
||||
link_init(&timer->task_list.bucket_level2[i]);
|
||||
link_init(&timer->task_list.bucket_level3[i]);
|
||||
link_init(&timer->task_list.bucket_level4[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize wake list head structure
|
||||
*/
|
||||
void wake_task_list_init(void)
|
||||
{
|
||||
link_init(&wake_tasks.head);
|
||||
wake_tasks.end = &wake_tasks.head;
|
||||
l4_mutex_init(&wake_tasks.lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate new sleeper task struct
|
||||
*/
|
||||
struct sleeper_task *new_sleeper_task(l4id_t tid, int ret)
|
||||
{
|
||||
struct sleeper_task *task;
|
||||
|
||||
/* May be we can prepare a cache for timer_task structs */
|
||||
task = (struct sleeper_task *)kzalloc(sizeof(struct sleeper_task));
|
||||
|
||||
link_init(&task->list);
|
||||
task->tid = tid;
|
||||
task->retval = ret;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void free_sleeper_task(struct sleeper_task *task)
|
||||
{
|
||||
kfree(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the bucket list correspongding to seconds value
|
||||
*/
|
||||
struct link* find_bucket_list(unsigned long seconds)
|
||||
{
|
||||
struct link *vector;
|
||||
struct sleeper_task_bucket *bucket;
|
||||
|
||||
bucket = &timer[SLEEP_WAKE_TIMER].task_list;
|
||||
|
||||
/*
|
||||
* TODO: Check if we have already surpassed seconds
|
||||
*/
|
||||
if (IS_IN_LEVEL0_BUCKET(seconds)) {
|
||||
vector = &bucket->bucket_level0[GET_BUCKET_LEVEL0(seconds)];
|
||||
} else if (IS_IN_LEVEL1_BUCKET(seconds)) {
|
||||
vector = &bucket->bucket_level1[GET_BUCKET_LEVEL1(seconds)];
|
||||
} else if (IS_IN_LEVEL2_BUCKET(seconds)) {
|
||||
vector = &bucket->bucket_level2[GET_BUCKET_LEVEL2(seconds)];
|
||||
} else if (IS_IN_LEVEL3_BUCKET(seconds)) {
|
||||
vector = &bucket->bucket_level3[GET_BUCKET_LEVEL3(seconds)];
|
||||
} else {
|
||||
vector = &bucket->bucket_level4[GET_BUCKET_LEVEL4(seconds)];
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scans for up to TIMERS_TOTAL timer devices in capabilities.
|
||||
*/
|
||||
@@ -100,16 +186,18 @@ int timer_probe_devices(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Irq handler for timer interrupts
|
||||
*/
|
||||
int timer_irq_handler(void *arg)
|
||||
{
|
||||
int err;
|
||||
struct timer *timer = (struct timer *)arg;
|
||||
struct link *vector;
|
||||
const int slot = 0;
|
||||
|
||||
/* Initialise timer */
|
||||
sp804_init(timer->base, SP804_TIMER_RUNMODE_PERIODIC,
|
||||
SP804_TIMER_WRAPMODE_WRAPPING,
|
||||
SP804_TIMER_WIDTH32BIT, SP804_TIMER_IRQENABLE);
|
||||
timer_init(timer->base);
|
||||
|
||||
/* Register self for timer irq, using notify slot 0 */
|
||||
if ((err = l4_irq_control(IRQ_CONTROL_REGISTER, slot,
|
||||
@@ -120,40 +208,105 @@ int timer_irq_handler(void *arg)
|
||||
}
|
||||
|
||||
/* Enable Timer */
|
||||
sp804_enable(timer->base, 1);
|
||||
timer_start(timer->base);
|
||||
|
||||
/* Handle irqs forever */
|
||||
while (1) {
|
||||
int count;
|
||||
struct link *task_list;
|
||||
|
||||
/* Block on irq */
|
||||
count = l4_irq_wait(slot, timer->cap.irq);
|
||||
if((count = l4_irq_wait(slot, timer->cap.irq)) < 0) {
|
||||
printf("l4_irq_wait() returned with negative value\n");
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Update timer count */
|
||||
//printf("Got irq(count 0x%x)\n", timer->count);
|
||||
/*
|
||||
* Update timer count
|
||||
* TODO: Overflow check, we have 1 interrupt/sec from timer
|
||||
* with 32bit count it will take 9years to overflow
|
||||
*/
|
||||
timer->count += count;
|
||||
|
||||
/* Print both counter and number of updates on count */
|
||||
printf("Timer count: %lld, current update: %d\n",
|
||||
timer->count, count);
|
||||
/* find bucket list of taks to be woken for current count */
|
||||
vector = find_bucket_list(timer->count);
|
||||
|
||||
if (!list_empty(vector)) {
|
||||
/* Removing tasks from sleeper list */
|
||||
l4_mutex_lock(&timer[SLEEP_WAKE_TIMER].lock);
|
||||
task_list = list_detach(vector);
|
||||
l4_mutex_unlock(&timer[SLEEP_WAKE_TIMER].lock);
|
||||
|
||||
/* Add tasks to wake_task_list */
|
||||
l4_mutex_lock(&wake_tasks.lock);
|
||||
list_attach(task_list,
|
||||
&wake_tasks.head, wake_tasks.end);
|
||||
l4_mutex_unlock(&wake_tasks.lock);
|
||||
|
||||
/*
|
||||
* Send ipc to handle_request
|
||||
* thread to send wake signals
|
||||
*/
|
||||
printf("sending ipc %d to thread %d\n", L4_IPC_TAG_TIMER_WAKE_THREADS, tid_ipc_handler);
|
||||
l4_send(tid_ipc_handler,L4_IPC_TAG_TIMER_WAKE_THREADS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routine to wake tasks from wake list
|
||||
*/
|
||||
void task_wake(void)
|
||||
{
|
||||
struct sleeper_task *struct_ptr, *temp_ptr;
|
||||
int ret;
|
||||
|
||||
if (!list_empty(&wake_tasks.head)) {
|
||||
list_foreach_removable_struct(struct_ptr, temp_ptr,
|
||||
&wake_tasks.head, list) {
|
||||
/* Remove task from wake list */
|
||||
l4_mutex_lock(&wake_tasks.lock);
|
||||
list_remove(&struct_ptr->list);
|
||||
l4_mutex_unlock(&wake_tasks.lock);
|
||||
|
||||
/* Set sender correctly */
|
||||
l4_set_sender(struct_ptr->tid);
|
||||
|
||||
#if 0
|
||||
printf("waking thread at time %x\n",
|
||||
(unsigned int)timer[SLEEP_WAKE_TIMER].count);
|
||||
#endif
|
||||
/* send wake ipc */
|
||||
if ((ret = l4_ipc_return(struct_ptr->retval)) < 0) {
|
||||
printf("%s: IPC return error: %d.\n",
|
||||
__FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* free allocated sleeper task struct */
|
||||
free_sleeper_task(struct_ptr);
|
||||
}
|
||||
}
|
||||
/* If wake list is empty set end = start */
|
||||
if (list_empty(&wake_tasks.head))
|
||||
wake_tasks.end = &wake_tasks.head;
|
||||
|
||||
}
|
||||
|
||||
int timer_setup_devices(void)
|
||||
{
|
||||
struct task_ids irq_tids;
|
||||
int err;
|
||||
|
||||
for (int i = 0; i < TIMERS_TOTAL; i++) {
|
||||
/* Get one page from address pool */
|
||||
timer[i].base = (unsigned long)l4_new_virtual(1);
|
||||
timer[i].count = 0;
|
||||
link_init(&timer[i].task_list);
|
||||
l4_mutex_init(&timer[i].lock);
|
||||
/* initialize timer */
|
||||
timer_struct_init(&timer[i],(unsigned long)l4_new_virtual(1) );
|
||||
|
||||
/* Map timer to a virtual address region */
|
||||
if (IS_ERR(l4_map((void *)__pfn_to_addr(timer[i].cap.start),
|
||||
(void *)timer[i].base, timer[i].cap.size,
|
||||
MAP_USR_IO_FLAGS,
|
||||
MAP_USR_IO,
|
||||
self_tid()))) {
|
||||
printf("%s: FATAL: Failed to map TIMER device "
|
||||
"%d to a virtual address\n",
|
||||
@@ -181,7 +334,16 @@ int timer_setup_devices(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Declare a statically allocated char buffer
|
||||
* with enough bitmap size to cover given size
|
||||
*/
|
||||
#define DECLARE_IDPOOL(name, size) \
|
||||
char name[(sizeof(struct id_pool) + ((size >> 12) >> 3))]
|
||||
|
||||
#define PAGE_POOL_SIZE SZ_1MB
|
||||
static struct address_pool device_vaddr_pool;
|
||||
DECLARE_IDPOOL(device_id_pool, PAGE_POOL_SIZE);
|
||||
|
||||
/*
|
||||
* Initialize a virtual address pool
|
||||
@@ -210,9 +372,9 @@ void init_vaddr_pool(void)
|
||||
* addresses from this pool.
|
||||
*/
|
||||
address_pool_init(&device_vaddr_pool,
|
||||
page_align_up(__end),
|
||||
__pfn_to_addr(caparray[i].end),
|
||||
TIMERS_TOTAL);
|
||||
(struct id_pool *)&device_id_pool,
|
||||
page_align_up(__end),
|
||||
__pfn_to_addr(caparray[i].end));
|
||||
return;
|
||||
} else
|
||||
goto out_err;
|
||||
@@ -231,68 +393,25 @@ void *l4_new_virtual(int npages)
|
||||
return address_new(&device_vaddr_pool, npages, PAGE_SIZE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct timer_task *get_timer_task(l4id_t tgid)
|
||||
/*
|
||||
* Got request for sleep for seconds,
|
||||
* right now max sleep allowed is 2^32 sec
|
||||
*/
|
||||
void task_sleep(l4id_t tid, unsigned long seconds, int ret)
|
||||
{
|
||||
/* May be we can prepare a cache for timer_task structs */
|
||||
struct timer_task *task = (struct timer_task *)kzalloc(sizeof(struct timer_task));
|
||||
struct sleeper_task *task = new_sleeper_task(tid, ret);
|
||||
struct link *vector;
|
||||
|
||||
link_init(&task->list);
|
||||
task->tgid = tgid;
|
||||
task->wait_count = timer[0].count;
|
||||
/* can overflow happen here?, timer is in 32bit mode */
|
||||
seconds += timer[SLEEP_WAKE_TIMER].count;
|
||||
|
||||
return task;
|
||||
vector = find_bucket_list(seconds);
|
||||
|
||||
l4_mutex_lock(&timer[SLEEP_WAKE_TIMER].lock);
|
||||
list_insert(&task->list, vector);
|
||||
l4_mutex_unlock(&timer[SLEEP_WAKE_TIMER].lock);
|
||||
}
|
||||
|
||||
void free_timer_task(struct timer_task *task)
|
||||
{
|
||||
kfree(task);
|
||||
}
|
||||
|
||||
void timer_irq_handler(void)
|
||||
{
|
||||
struct timer_task *struct_ptr, *temp_ptr;
|
||||
|
||||
timer[0].count += 1;
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* Traverse through the sleeping process list and
|
||||
* wake any process if required, we need to put this part in bottom half
|
||||
*/
|
||||
list_foreach_removable_struct(struct_ptr, temp_ptr, &timer[0].tasklist, list)
|
||||
if (struct_ptr->wait_count == timer[0].count) {
|
||||
|
||||
/* Remove task from list */
|
||||
l4_mutex_lock(&timer[0].lock);
|
||||
list_remove(&struct_ptr->list);
|
||||
l4_mutex_unlock(&timer[0].lock);
|
||||
|
||||
/* wake the sleeping process, send wake ipc */
|
||||
|
||||
free_timer_task(struct_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
int timer_gettime(void)
|
||||
{
|
||||
return timer[0].count;
|
||||
}
|
||||
|
||||
void timer_sleep(l4id_t tgid, int sec)
|
||||
{
|
||||
struct timer_task *task = get_timer_task(tgid);
|
||||
|
||||
/* Check for overflow */
|
||||
task->wait_count += (sec * 1000000);
|
||||
|
||||
l4_mutex_lock(&timer[0].lock);
|
||||
list_insert_tail(&task->list, &timer[0].tasklist);
|
||||
l4_mutex_unlock(&timer[0].lock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void handle_requests(void)
|
||||
{
|
||||
u32 mr[MR_UNUSED_TOTAL];
|
||||
@@ -300,10 +419,9 @@ void handle_requests(void)
|
||||
u32 tag;
|
||||
int ret;
|
||||
|
||||
printf("%s: Initiating ipc.\n", __CONTAINER__);
|
||||
if ((ret = l4_receive(L4_ANYTHREAD)) < 0) {
|
||||
printf("%s: %s: IPC Error: %d. Quitting...\n", __CONTAINER__,
|
||||
__FUNCTION__, ret);
|
||||
printf("%s: %s: IPC Error: %d. Quitting...\n",
|
||||
__CONTAINER__, __FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
|
||||
@@ -327,13 +445,35 @@ void handle_requests(void)
|
||||
* inside the current container
|
||||
*/
|
||||
switch (tag) {
|
||||
/* Return time in seconds, since the timer was started */
|
||||
case L4_IPC_TAG_TIMER_GETTIME:
|
||||
//mr[0] = timer_gettime();
|
||||
mr[0] = timer[SLEEP_WAKE_TIMER].count;
|
||||
|
||||
/* Reply */
|
||||
if ((ret = l4_ipc_return(ret)) < 0) {
|
||||
printf("%s: IPC return error: %d.\n", __FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_TIMER_SLEEP:
|
||||
//timer_sleep(senderid, mr[0]);
|
||||
/* TODO: Halt the caller for mr[0] seconds */
|
||||
printf("%s: Got sleep request from thread 0x%x, duration %d\n", __CONTAINER_NAME__,
|
||||
senderid, mr[0]);
|
||||
if (mr[0] > 0) {
|
||||
task_sleep(senderid, mr[0], ret);
|
||||
}
|
||||
else {
|
||||
if ((ret = l4_ipc_return(ret)) < 0) {
|
||||
printf("%s: IPC return error: %d.\n",
|
||||
__FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Intra container ipc by irq_thread */
|
||||
case L4_IPC_TAG_TIMER_WAKE_THREADS:
|
||||
task_wake();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -342,12 +482,6 @@ void handle_requests(void)
|
||||
"0x%x\n", __CONTAINER__, senderid,
|
||||
__cid(senderid), tag);
|
||||
}
|
||||
|
||||
/* Reply */
|
||||
if ((ret = l4_ipc_return(ret)) < 0) {
|
||||
printf("%s: IPC return error: %d.\n", __FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -408,12 +542,17 @@ void main(void)
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* initialise timed_out_task list */
|
||||
wake_task_list_init();
|
||||
|
||||
/* Map and initialize timer devices */
|
||||
timer_setup_devices();
|
||||
|
||||
/* Set the tid of ipc handler */
|
||||
tid_ipc_handler = self_tid();
|
||||
|
||||
/* Listen for timer requests */
|
||||
while (1)
|
||||
handle_requests();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <l4lib/arch/asm.h>
|
||||
|
||||
#include <l4lib/macros.h>
|
||||
#include L4LIB_INC_ARCH(asm.h)
|
||||
|
||||
BEGIN_PROC(local_setup_new_thread)
|
||||
ldr r0, [sp, #-4]! @ Load first argument.
|
||||
|
||||
@@ -10,6 +10,7 @@ char stack[THREADS_TOTAL][STACK_SIZE] ALIGN(8);
|
||||
char *__stack_ptr = &stack[1][0];
|
||||
|
||||
char utcb[THREADS_TOTAL][UTCB_SIZE] ALIGN(8);
|
||||
//char utcb[THREADS_TOTAL][0x1000] ALIGN(0x1000);
|
||||
char *__utcb_ptr = &utcb[1][0];
|
||||
|
||||
extern void local_setup_new_thread(void);
|
||||
@@ -25,7 +26,7 @@ int thread_create(int (*func)(void *), void *args, unsigned int flags,
|
||||
|
||||
/* Shared space only */
|
||||
if (!(TC_SHARE_SPACE & flags)) {
|
||||
printf("%s: This function allows only "
|
||||
printf("%s: Warning - This function allows only "
|
||||
"shared space thread creation.\n",
|
||||
__FUNCTION__);
|
||||
return -EINVAL;
|
||||
@@ -61,6 +62,7 @@ int thread_create(int (*func)(void *), void *args, unsigned int flags,
|
||||
/* Update utcb, stack pointers */
|
||||
__stack_ptr += STACK_SIZE;
|
||||
__utcb_ptr += UTCB_SIZE;
|
||||
//__utcb_ptr += 0x1000;
|
||||
|
||||
/* Start the new thread */
|
||||
if ((err = l4_thread_control(THREAD_RUN, &ids)) < 0)
|
||||
|
||||
Reference in New Issue
Block a user