Loading...
Searching...
No Matches
examples/sys/start-with-exc/main.c

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

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 and ARM architectures.
*/
#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"
"thread: \n"
#ifdef ARCH_x86
" pusha \n"
" push %esp \n"
" call thread_func \n"
#endif
#ifdef ARCH_arm
" push {r0-r7} \n"
" mov r0, sp \n"
" bl thread_func \n"
#endif
#ifdef ARCH_arm64
" stp x0, x1, [sp, #0]! \n"
" stp x2, x3, [sp, #0]! \n"
" stp x4, x5, [sp, #0]! \n"
" stp x6, x7, [sp, #0]! \n"
" mov x0, sp \n"
" bl thread_func \n"
#endif
);
extern void thread(void);
/* Our main function */
int main(void)
{
/* Get a capability slot for our new thread. */
l4_cap_idx_t t1 = l4re_util_cap_alloc();
l4_utcb_t *u = l4_utcb();
l4_exc_regs_t *e = l4_utcb_exc_u(u);
l4_msgtag_t tag;
int err;
printf("Example showing how to start a thread with an exception.\n");
/* We do not want to implement a pager here, take the shortcut. */
printf("Make sure to start this program with ldr-flags=eager_map\n");
if (l4_is_invalid_cap(t1))
return 1;
/* Create the thread using our default factory */
tag = l4_factory_create_thread(l4re_env()->factory, t1);
if (l4_error(tag))
return 1;
/* Setup the thread by setting the pager and task. */
l4_thread_control_start();
l4_thread_control_pager(l4re_env()->main_thread);
l4_thread_control_exc_handler(l4re_env()->main_thread);
l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb,
L4RE_THIS_TASK_CAP);
tag = l4_thread_control_commit(t1);
if (l4_error(tag))
return 2;
/* Start the thread by finally setting instruction and stack pointer */
tag = l4_thread_ex_regs(t1,
(l4_umword_t)thread,
(l4_umword_t)thread_stack + sizeof(thread_stack),
L4_THREAD_EX_REGS_TRIGGER_EXCEPTION);
if (l4_error(tag))
return 3;
l4_sched_param_t sp = l4_sched_param(1, 0);
tag = l4_scheduler_run_thread(l4re_env()->scheduler, t1, &sp);
if (l4_error(tag))
return 4;
/* Receive initial exception from just started thread */
tag = l4_ipc_receive(t1, u, L4_IPC_NEVER);
if ((err = l4_ipc_error(tag, u)))
{
printf("Umm, ipc error: %x\n", err);
return 1;
}
/* We expect an exception IPC */
if (!l4_msgtag_is_exception(tag))
{
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->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack));
#ifdef ARCH_x86
e->ip = (l4_umword_t)thread;
e->edi = 0;
e->esi = 1;
e->ebp = 2;
e->ebx = 4;
e->edx = 5;
e->ecx = 6;
e->eax = 7;
#endif
#ifdef ARCH_arm
e->pc = (l4_umword_t)thread;
e->r[0] = 0;
e->r[1] = 1;
e->r[2] = 2;
e->r[3] = 3;
e->r[4] = 4;
e->r[5] = 5;
e->r[6] = 6;
e->r[7] = 7;
#endif
#ifdef ARCH_arm64
e->pc = (l4_umword_t)thread;
e->r[0] = 0;
e->r[1] = 1;
e->r[2] = 2;
e->r[3] = 3;
e->r[4] = 4;
e->r[5] = 5;
e->r[6] = 6;
e->r[7] = 7;
#endif
/* Send a complete exception */
tag = l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0);
/* 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;
}
cap_alloc.h
Capability allocator C interface.
env.h
Environment interface.
factory.h
Common factory related definitions.
l4re_util_cap_alloc
L4_BEGIN_DECLS l4_cap_idx_t l4re_util_cap_alloc(void) L4_NOTHROW
Get free capability index at capability allocator.
l4re_env
l4re_env_t * l4re_env(void) L4_NOTHROW
Get L4Re initial environment.
Definition env.h:181
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_cap_idx_t
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:336
l4_is_invalid_cap
unsigned l4_is_invalid_cap(l4_cap_idx_t c) L4_NOTHROW
Test if a capability selector is the invalid capability.
Definition types.h:389
l4_factory_create_thread
l4_msgtag_t l4_factory_create_thread(l4_cap_idx_t factory, l4_cap_idx_t target_cap) L4_NOTHROW
Create a new thread.
Definition factory.h:538
l4_ipc_receive
l4_msgtag_t l4_ipc_receive(l4_cap_idx_t object, l4_utcb_t *utcb, l4_timeout_t timeout) L4_NOTHROW
Wait for a message from a specific source.
Definition ipc.h:602
l4_ipc_send
l4_msgtag_t l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout) L4_NOTHROW
Send a message to an object (do not wait for a reply).
Definition ipc.h:586
l4_error
long l4_error(l4_msgtag_t tag) L4_NOTHROW
Get IPC error code if any or message tag label otherwise for an IPC call.
Definition ipc.h:646
l4_ipc_error
l4_umword_t l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
Get the IPC error code for an IPC operation.
Definition ipc.h:629
l4_msgtag_is_exception
unsigned l4_msgtag_is_exception(l4_msgtag_t t) L4_NOTHROW
Test for exception protocol.
Definition types.h:448
l4_msgtag
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
Definition types.h:405
l4_msgtag_label
long l4_msgtag_label(l4_msgtag_t t) L4_NOTHROW
Get the protocol of tag.
Definition types.h:417
l4_scheduler_run_thread
l4_msgtag_t l4_scheduler_run_thread(l4_cap_idx_t scheduler, l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW)
Run a thread on a Scheduler.
Definition scheduler.h:396
l4_sched_param
l4_sched_param_t l4_sched_param(unsigned prio, l4_umword_t quantum=0) L4_NOTHROW
Construct scheduler parameter.
Definition scheduler.h:289
l4_thread_ex_regs
l4_msgtag_t l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp, l4_umword_t flags) L4_NOTHROW
Exchange basic thread registers.
Definition thread.h:942
L4_THREAD_EX_REGS_TRIGGER_EXCEPTION
@ L4_THREAD_EX_REGS_TRIGGER_EXCEPTION
Trigger artificial exception in thread.
Definition thread.h:800
l4_thread_control_bind
void l4_thread_control_bind(l4_utcb_t *thread_utcb, l4_cap_idx_t task) L4_NOTHROW
Bind the thread to a task.
Definition thread.h:975
l4_thread_control_commit
l4_msgtag_t l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW
Commit the thread control parameters.
Definition thread.h:987
l4_thread_control_exc_handler
void l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW
Set the exception handler.
Definition thread.h:968
l4_thread_control_start
void l4_thread_control_start(void) L4_NOTHROW
Start a thread control API sequence.
Definition thread.h:956
l4_thread_control_pager
void l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW
Set the pager.
Definition thread.h:962
L4_IPC_NEVER
#define L4_IPC_NEVER
never timeout
Definition __timeout.h:76
l4_utcb_t
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
l4_utcb
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition utcb.h:346
L4_STICKY
#define L4_STICKY(x)
Mark symbol sticky (even not there).
Definition compiler.h:288
l4_sleep
void l4_sleep(l4_uint32_t ms) L4_NOTHROW
Suspend thread for a period of ms milliseconds.
l4_exc_regs_t
UTCB structure for exceptions.
Definition utcb.h:28
l4_exc_regs_t::r
l4_umword_t r[13]
registers
Definition utcb.h:32
l4_exc_regs_t::sp
l4_umword_t sp
stack pointer
Definition utcb.h:33
l4_exc_regs_t::ip
l4_umword_t ip
instruction pointer
Definition utcb.h:36
l4_exc_regs_t::edx
l4_umword_t edx
edx register
Definition utcb.h:73
l4_exc_regs_t::pc
l4_umword_t pc
pc
Definition utcb.h:36
l4_exc_regs_t::esi
l4_umword_t esi
esi register
Definition utcb.h:69
l4_exc_regs_t::ebp
l4_umword_t ebp
ebp register
Definition utcb.h:70
l4_exc_regs_t::eax
l4_umword_t eax
eax register
Definition utcb.h:75
l4_exc_regs_t::ecx
l4_umword_t ecx
ecx register
Definition utcb.h:74
l4_exc_regs_t::ebx
l4_umword_t ebx
ebx register
Definition utcb.h:72
l4_exc_regs_t::edi
l4_umword_t edi
edi register
Definition utcb.h:68
l4_msgtag_t
Message tag data structure.
Definition types.h:154
l4_sched_param_t
Scheduler parameter set.
Definition scheduler.h:174