L4Re - L4 Runtime Environment
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
examples/sys/start-with-exc/main.c

This example shows how to start a newly created thread with a defined set of CPU registers.

/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Björn Döbel <doebel@os.inf.tu-dresden.de>,
* Frank Mehnert <fm3@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* Start a thread with an exception reply. This example does only work on
* the x86-32 architecture.
*/
#include <l4/sys/thread.h>
#include <l4/sys/factory.h>
#include <l4/sys/ipc.h>
#include <l4/sys/utcb.h>
#include <l4/util/util.h>
#include <l4/re/env.h>
#include <l4/re/c/util/cap_alloc.h>
#include <stdlib.h>
#include <stdio.h>
/* Stack for the thread to be created. 8kB are enough. */
static char thread_stack[8 << 10];
/* The thread to be created. For illustration it will print out its
* register set.
*/
static void L4_STICKY(thread_func(l4_umword_t *d))
{
while (1)
{
printf("hey, I'm a thread\n");
printf("got register values: %ld %ld %ld %ld %ld %ld %ld\n",
d[7], d[6], d[5], d[4], d[2], d[1], d[0]);
l4_sleep(800);
}
}
/* Startup trick for this example. Put all the CPU registers on the stack so
* that the C function above can get it on the stack. */
asm(
".global thread \n\t"
"thread: \n\t"
" pusha \n\t"
" push %esp \n\t"
" call thread_func \n\t"
);
extern void thread(void);
/* Our main function */
int main(void)
{
/* Get a capability slot for our new thread. */
l4_exc_regs_t *e = l4_utcb_exc_u(u);
int err;
extern char _start[], _end[], _etext[];
return 1;
/* Prevent pagefaults of our new thread because we do not want to
* implement a pager as well. */
l4_touch_ro(_start, _end - _start + 1);
l4_touch_rw(_etext, _end - _etext);
/* Create the thread using our default factory */
tag = l4_factory_create_thread(l4re_env()->factory, t1);
return 1;
/* Setup the thread by setting the pager and task. */
l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb,
L4RE_THIS_TASK_CAP);
return 2;
/* Start the thread by finally setting instruction and stack pointer */
(l4_umword_t)thread,
(l4_umword_t)thread_stack + sizeof(thread_stack),
return 3;
/* Receive initial exception from just started thread */
if ((err = l4_ipc_error(tag, u)))
{
printf("Umm, ipc error: %x\n", err);
return 1;
}
/* We expect an exception IPC */
{
printf("PF?: %lx %lx (not prepared to handle this) %ld\n",
l4_utcb_mr_u(u)->mr[0], l4_utcb_mr_u(u)->mr[1], l4_msgtag_label(tag));
return 1;
}
/* Fill out the complete register set of the new thread */
e->ip = (l4_umword_t)thread;
e->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack));
e->eax = 1;
e->ebx = 4;
e->ecx = 2;
e->edx = 3;
e->esi = 6;
e->edi = 7;
e->ebp = 5;
/* Send a complete exception */
/* Send reply and start the thread with the defined CPU register set */
tag = l4_ipc_send(t1, u, tag, L4_IPC_NEVER);
if ((err = l4_ipc_error(tag, u)))
printf("Error sending IPC: %x\n", err);
/* Idle around */
while (1)
l4_sleep(10000);
return 0;
}
L4Re - L4 Runtime Environment