Exemplo n.º 1
0
static void
ipc_irq_teardown(struct new_bench_test *test, int args[])
{
    int r = 0;
    L4_Word_t control;

    //L4_DeassociateInterrupt(thread_tid);
    control = 0 | (1 << 6) | (31<<27);
    L4_LoadMR(0, interrupt);
    r = L4_InterruptControl(handler_tid, control);
    if (r == 0) {
        printf("Cannot unregister interrupt\n");
    }

#if SPINNER
    /* Delete spinner */
    r = L4_ThreadControl (spinner_tid, L4_nilspace, L4_nilthread, L4_nilthread, L4_nilthread, 0, (void *) 0);
    assert (r == 1);
#endif
    /* Delete handler thread */
    r = L4_ThreadControl (handler_tid, L4_nilspace, L4_nilthread,
        L4_nilthread, L4_nilthread, 0, (void *) 0);
    assert (r == 1);

    /* Delete pager */
    r = L4_ThreadControl (pager_tid, L4_nilspace, L4_nilthread,
            L4_nilthread, L4_nilthread, 0, (void *) 0);
    assert (r == 1);
}
Exemplo n.º 2
0
static void
ipc_teardown(struct bench_test *test, int args[])
{
    int r = 0;
    if (!fault_test)
    {
        /* Kill ping thread */
        r = L4_ThreadControl (ping_tid, L4_nilspace, L4_nilthread,
                  L4_nilthread, L4_nilthread, 0, (void *) 0);
        if (r == 0) printf("thread control Error: %lx\n", L4_ErrorCode());
        assert (r == 1);
    }

    if (!pagertimer)
    {
        /* Kill pong thread */
        r = L4_ThreadControl (pong_tid, L4_nilspace, L4_nilthread,
              L4_nilthread, L4_nilthread, 0, (void *) 0);
        assert (r == 1);
    }
    /* Delete ping space */
    if (ping_space.raw != L4_nilspace.raw)
    {
         r = L4_SpaceControl(ping_space, L4_SpaceCtrl_delete, KBENCH_CLIST, L4_Nilpage, 0, NULL);
         assert (r == 1);
         okl4_kspaceid_free(spaceid_pool, ping_space);
    }
    /* Delete pong space */
    if (pong_space.raw != L4_nilspace.raw)
    {
        r = L4_SpaceControl(pong_space, L4_SpaceCtrl_delete, KBENCH_CLIST, L4_Nilpage, 0, NULL);
        assert (r == 1);
         okl4_kspaceid_free(spaceid_pool, pong_space);
    }
}
Exemplo n.º 3
0
L4_ThreadId_t thread_new(AddrSpace_t *space)
{
    assert (space != NULL);

    L4_Word_t tno;
    L4_ThreadId_t tid;
    L4_ThreadId_t space_spec;
    L4_Word_t utcb_location;
    slab_t *sb;
    list_t *li;
    thread_t *this;

    mutex_lock(&thrlock);
    tno = threadno_find_free(bitmap, MAX_TASKS);
    if (!tno) {
        mutex_unlock(&thrlock);
        return L4_nilthread;
    }

    tid = L4_GlobalId(tno, 1);
    utcb_location = UTCB_AREA_LOCATION;

    space_spec = space->tid;
    tno = threadno_find_free(space->threads, MAX_THREADS_PER_TASK);
    if (!tno) {
        mutex_unlock(&thrlock);
        return L4_nilthread;
    }
    utcb_location += tno * UTCB_SIZE;

    sb = slab_alloc(&thrpool);
    if (!sb) {
        mutex_unlock(&thrlock);
        return L4_nilthread;
    }
    
    if (FALSE == (L4_ThreadControl(tid, space_spec, tid, space->pager, (void *) utcb_location))) {
        slab_free(&thrpool, sb);
        mutex_unlock(&thrlock);
        return L4_nilthread;
    }

    li = LIST_TYPE(sb->data);
    this = (thread_t *) li->data;
    list_push(&thread_list, li);

    this->tid = tid;
    this->space = space;
    this->index = tno;
    this->creation = L4_SystemClock();

    threadno_alloc(bitmap, L4_ThreadNo(tid));
    threadno_alloc(space->threads, tno);
    mutex_unlock(&thrlock);
    return tid;
}
Exemplo n.º 4
0
void __USER_TEXT __root_thread(kip_t *kip_ptr, utcb_t *utcb_ptr)
{
	l4_thread_t myself = utcb_ptr->t_globalid;
	char *free_mem = (char *) get_free_base(kip_ptr);

	uint32_t msg[8] = { 0 };

	/* Allocate utcbs and stacks in Free memory region */
	char *utcbs[2] = {
		free_mem, free_mem + UTCB_SIZE
	};
	char *stacks[2] = {
		free_mem + 2 * UTCB_SIZE,
		free_mem + 2 * UTCB_SIZE + STACK_SIZE
	};

	threads[PING_THREAD] = L4_THREAD_NUM(PING_THREAD,
			kip_ptr->thread_info.s.user_base);	/* Ping */
	threads[PONG_THREAD] = L4_THREAD_NUM(PONG_THREAD,
			kip_ptr->thread_info.s.user_base);	/* Pong */

	L4_ThreadControl(threads[PING_THREAD], myself,
			0, myself, utcbs[PING_THREAD]);
	L4_ThreadControl(threads[PONG_THREAD], myself,
			0, myself, utcbs[PONG_THREAD]);

	L4_Map(myself, (memptr_t) stacks[PING_THREAD], STACK_SIZE);
	L4_Map(myself, (memptr_t) stacks[PONG_THREAD], STACK_SIZE);

	L4_Start(threads[PING_THREAD], ping_thread,
			stacks[PING_THREAD] + STACK_SIZE);
	L4_Start(threads[PONG_THREAD], pong_thread,
			stacks[PONG_THREAD] + STACK_SIZE);

	while (1)
		L4_Ipc(L4_NILTHREAD, L4_NILTHREAD, 0, msg);
}
Exemplo n.º 5
0
int
thread_new
(
    struct thread   * thread,
    L4_SpaceId_t    space,
    L4_ThreadId_t   scheduler,
    L4_ThreadId_t   pager,
    L4_ThreadId_t   exception
)
{
    int     rv;
    int fpu = 0;

#if defined(ARCH_IA32)
    /* Always allocate FPU resources to every thread iguana creates on IA32
     * (bug 2836)
     */
    fpu = 0x80000001;
#endif

    rv =
        L4_ThreadControl
        (
            thread->id, space, scheduler, pager, exception, fpu, (void *)thread->utcb
        );

    if (rv == 1)
    {
        L4_Word_t handle;
        L4_StoreMR(0, &handle);

        thread->handle.raw = handle;

        assert(hash_lookup(l4tid_to_thread, handle) == NULL);

        /* Guaranteed to work because hash_lookup was just performed */
        hash_insert(l4tid_to_thread, handle, thread);

        L4_Set_Priority(thread->id, 100);
    } else {
        /* Initialise the handle to an invalid valid. */
        thread->handle = L4_nilthread;
    }
    
    return rv;
}
Exemplo n.º 6
0
int thread_destroy(L4_ThreadId_t tid)
{
    list_t *li;
    AddrSpace_t *as;
    L4_Word_t tno;
   
    mutex_lock(&thrlock);

    li = list_find(thread_list, &tid, sizeof(L4_ThreadId_t));
    if (li == NULL) {
        mutex_unlock(&thrlock);
        return FALSE;
    }

    if (FALSE == L4_ThreadControl(tid, L4_nilthread, L4_nilthread, L4_nilthread, (void *) -1)) {
        mutex_unlock(&thrlock);
        return FALSE;
    }

    as = THREAD_TYPE(li->data)->space;
    tno = THREAD_TYPE(li->data)->index;

    list_remove(&thread_list, li);
    slab_free(&thrpool, SLAB_FROM_DATA(li));

    threadno_free(bitmap, L4_ThreadNo(tid));
    threadno_free(as->threads, tno);

    if (tid.raw == as->tid.raw) {
        for (li = thread_list; li; li = li->next) {
            if (THREAD_TYPE(li->data)->space == as) break;
        }
        if (li == NULL) {
            // task destroy notification should go here
            address_space_destroy(as);
        } else {
            as->tid = THREAD_TYPE(li->data)->tid;
        }
    }

    mutex_unlock(&thrlock);
    
    // thread destroy notification should go here
    return TRUE;
} 
Exemplo n.º 7
0
static L4_ThreadId_t create_local_thread(char *desc, L4_KernelInterfacePage_t *kip, int idx, threadfunc_t func, L4_Word_t stack_size)
{
    L4_Word_t utcb_size = L4_UtcbSize(kip);
    L4_Word_t my_utcb = L4_MyLocalId().raw;
    my_utcb = (my_utcb & ~(utcb_size - 1));

    L4_ThreadId_t tid = L4_GlobalId(L4_ThreadNo(L4_Myself()) + idx, 1);
    L4_Word_t utcb_location = my_utcb + idx * utcb_size;

    if (FALSE == L4_ThreadControl(tid, L4_Myself(), L4_Myself(), L4_Pager(), (void *) utcb_location)) {
        printf("panic: can't execute %s: error code %d\n", desc, (int) L4_ErrorCode());
        return L4_nilthread;
    }

    void *stack = kmalloc(stack_size);

    L4_Start_SpIp(tid, (L4_Word_t) stack + stack_size - 32, (L4_Word_t) func);
    return tid;
}
Exemplo n.º 8
0
void
thread_delete(struct thread *thread)
{
    struct pd *pd;
#if defined(CONFIG_SESSION)
    struct session_p_node *sd;
#endif
    pd = thread->owner;
    (void)L4_ThreadControl(thread->id,
                           L4_nilspace,
                           L4_nilthread, L4_nilthread, L4_nilthread, 0, NULL);
    thread_free(thread->id);

    if (
#if defined(CONFIG_EAS)
        thread->eas == NULL &&
#endif
        thread->utcb != (void *)-1UL) {
        /* free local thread no. */
        bfl_free(pd->local_threadno,
                 ((uintptr_t)thread->utcb -
                  L4_Address(pd->space.utcb_area)) >> L4_GetUtcbBits());
    }
Exemplo n.º 9
0
void task_destroy(AddrSpace_t *space)
{
    list_t *li, *next;
    AddrSpace_t *as;
    L4_Word_t tno;
    L4_ThreadId_t tid;
   
    assert(space != NULL);

    mutex_lock(&thrlock);

    next = NULL;
    for (li = thread_list; li; li = next) {
        as = THREAD_TYPE(li->data)->space;
        next = li->next;
        if (as != space) continue;

        tno = THREAD_TYPE(li->data)->index;
        tid = THREAD_TYPE(li->data)->tid;

        /* hope this succeeds */
        L4_ThreadControl(tid, L4_nilthread, L4_nilthread, L4_nilthread, (void *) -1);

        list_remove(&thread_list, li);
        slab_free(&thrpool, SLAB_FROM_DATA(li));
        threadno_free(bitmap, L4_ThreadNo(tid));

        // thread destroy notification should go here
    }

    address_space_destroy(space);

    mutex_unlock(&thrlock);
    
    // task destroy notification should go here
    return;
}
Exemplo n.º 10
0
static void
ipc_setup(struct bench_test *test, int args[])
{
    static bool setup = false;
    int r;
    L4_Word_t utcb;
    fass = (test == &bench_ipc_fass);
    pagertimer = (test == &bench_ipc_pagemap);
    pagertimer_simulated = (test == &bench_ipc_pagemap_simulated);
    inter = (test == &bench_ipc_inter);
    fass_buffer = ((test == &bench_ipc_fass_buffer) || (test == &bench_ipc_fass_buffer_vspace));
    fault_test = (test == &bench_ipc_page_faults);
    intra_open = (test == &bench_ipc_intra_open);
    intra_close = (test == &bench_ipc_intra_close);
    intra_rpc = (test == &bench_ipc_intra_rpc);
    intra_ovh = (test == &bench_ipc_intra_ovh);
    intra_async = (test == &bench_ipc_intra_async);
    intra_async_ovh = (test == &bench_ipc_intra_async_ovh);

    num_iterations = args[0];
    num_mrs = args[1];

    ping_space = pong_space = L4_nilspace;

    if (! setup) {
        /* Find smallest supported page size. There's better at least one
         * bit set. */

        /* Size for one UTCB */
        utcb_size = L4_GetUtcbSize();

        /* We need a maximum of two threads per task */
#ifdef NO_UTCB_RELOCATE
        no_utcb_alloc = 1;
        utcb_area = L4_Nilpage;
        if (fass) {
            pong_utcb_area = L4_Nilpage;
        }
#else
        no_utcb_alloc = 0;
        utcb_area = L4_Fpage((L4_Word_t) UTCB_ADDRESS,
                             L4_GetUtcbAreaSize() + 1);
        if (fass) {
            pong_utcb_area = L4_Fpage ((L4_Word_t) UTCB_ADDRESS,
                                       L4_GetUtcbAreaSize() + 1);
        }
#endif

        /* Create pager */
        master_tid.raw = KBENCH_SERVER.raw;
        pager_tid.raw = KBENCH_SERVER.raw + 1;
        ping_tid.raw  = KBENCH_SERVER.raw + 2;
        pong_tid.raw  = KBENCH_SERVER.raw + 3;

        /* VU: calculate UTCB address -- this has to be revised */
        /** @todo FIXME: Should put into arch subdir - changhua. */
#if defined(ARCH_ARM)
        L4_Word_t pager_utcb = (L4_Word_t) __L4_ARM_Utcb();
#elif defined(ARCH_IA32)
        L4_Word_t pager_utcb = (L4_Word_t) __L4_X86_Utcb();
#elif defined(ARCH_SH)
        L4_Word_t pager_utcb = (L4_Word_t) L4_GetUtcbBase();
#else
        #error "Please define arch get_Utcb()"
#endif
        pager_utcb = no_utcb_alloc ? ~0UL : (pager_utcb & ~(utcb_size - 1)) + utcb_size;
        r = L4_ThreadControl (pager_tid, KBENCH_SPACE, master_tid, master_tid, 
                      master_tid, 0, (void*)pager_utcb);
        if (r == 0) printf("Thread create Error: %lx\n", L4_ErrorCode());
        assert(r == 1);
        L4_KDB_SetThreadName(pager_tid, "pager");
        L4_Start_SpIp (pager_tid, (L4_Word_t) pager_stack + sizeof(pager_stack) - 32, START_ADDR (pager));
        /* Find some area of memory to page to */
        setup = true;
    }

    if (pagertimer) {
        /* Only create ping space and ping thread. */
        r = okl4_kspaceid_allocany(spaceid_pool, &ping_space);
        assert(r == OKL4_OK);
        r = L4_SpaceControl(ping_space, L4_SpaceCtrl_new, KBENCH_CLIST, utcb_area, 0, NULL);
        assert(r == 1);

        utcb = no_utcb_alloc ? ~0UL : UTCB(0);

        r = L4_ThreadControl(ping_tid, ping_space, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
        L4_StoreMR(0, &ping_th.raw);
        assert(r == 1);
    } else if (fault_test) {
        /* Only create pong space and pong thread. */
        r = okl4_kspaceid_allocany(spaceid_pool, &pong_space);
        assert(r == OKL4_OK);
        r = L4_SpaceControl(pong_space, L4_SpaceCtrl_new, KBENCH_CLIST, utcb_area, 0, NULL);
        assert(r == 1);

        utcb = no_utcb_alloc ? ~0UL : UTCB(0);

        r = L4_ThreadControl(pong_tid, pong_space, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
        L4_StoreMR(0, &pong_th.raw);
        assert(r == 1);
    } else if (pagertimer_simulated || inter || fass || fass_buffer) {
        /* Create both ping, pong space, and create ping, pong thread in their own space */
        L4_Word_t ctrl = 0;
        if (test == &bench_ipc_fass_buffer_vspace) {
            ctrl = (1 << 16);
        }
        r = okl4_kspaceid_allocany(spaceid_pool, &ping_space);
        assert(r == OKL4_OK);

        r = L4_SpaceControl(ping_space, L4_SpaceCtrl_new, KBENCH_CLIST, utcb_area, ctrl, NULL);
        if (r == 0) printf("Space control Error: 0x%lx\n", L4_ErrorCode());
        assert( r == 1 );
        r = okl4_kspaceid_allocany(spaceid_pool, &pong_space);
        assert(r == OKL4_OK);
        r = L4_SpaceControl(pong_space, L4_SpaceCtrl_new, KBENCH_CLIST, (fass ? pong_utcb_area : utcb_area), ctrl, NULL);
        assert( r == 1);

        utcb = no_utcb_alloc ? ~0UL : UTCB(0);

        r = L4_ThreadControl(ping_tid, ping_space, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
        L4_StoreMR(0, &ping_th.raw);
        assert( r == 1);

        utcb = no_utcb_alloc ? ~0UL : fass ? PONGUTCB(1) : UTCB(1);

        r = L4_ThreadControl(pong_tid, pong_space, master_tid, pager_tid, pager_tid, 0, (void *)utcb);
        L4_StoreMR(0, &pong_th.raw);
    } else {
        /* Only Create ping space, but create both ping, pong thread in that space. */
        r = okl4_kspaceid_allocany(spaceid_pool, &ping_space);
        assert(r == OKL4_OK);
        r = L4_SpaceControl(ping_space, L4_SpaceCtrl_new, KBENCH_CLIST, utcb_area, 0, NULL);
        assert( r == 1 );

        utcb = no_utcb_alloc ? ~0UL : UTCB(0);

        r = L4_ThreadControl(ping_tid, ping_space, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
        L4_StoreMR(0, &ping_th.raw);
        assert( r == 1);

        utcb = no_utcb_alloc ? ~0UL : UTCB(1);

        r = L4_ThreadControl(pong_tid, ping_space, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
        L4_StoreMR(0, &pong_th.raw);
        assert( r == 1);
    }

    L4_KDB_SetThreadName(ping_tid, "ping");
    if (test != &bench_ipc_pagemap) {
        L4_KDB_SetThreadName(pong_tid, "pong");
    }
}
Exemplo n.º 11
0
static int CreateMaxThreads(void)
{
    int i;
    int res = 1;
   
    // MIPS32 address space ends at 0x80000000
#if (defined(L4_ARCH_MIPS) && defined(L4_32BIT))
    unsigned long utcb_base = 0x70000000;
#else
    unsigned long utcb_base = 0xb0000000;
#endif

    void * utcb = (void *)utcb_base;
    L4_Fpage_t utcb_area = L4_Fpage(utcb_base, 0x01000000);
    int max;
    L4_Word_t result;
    L4_SpaceId_t space;

    result = okl4_kspaceid_allocany(spaceid_pool, &space);
    fail_unless(result == OKL4_OK, "Failed to allocate any space id.");

    /* Create first thread (and address space) */
#ifdef NO_UTCB_RELOCATE
    utcb_area = L4_Nilpage;
    utcb = (void*)-1ul;
#endif

    res = create_address_space(space, utcb_area);

    i = 3;  // start creating threads after controlling space

    fail_unless(res == 1, "Failed to create controlling space\n");

    /* create threads */
    do {
        if (utcb) {
            utcb = (void *)(utcb_base + i * L4_GetUtcbSize());
        }
        if (!isSystemThread(thread_offset(i))) {
            res = L4_ThreadControl(thread_offset(i), space,
                    default_thread_handler, L4_nilthread, L4_nilthread, 0, (void *)utcb);
        }
        i++;
    } while (res == 1);

    max = i-3;

    /* delete threads */
    for (; i >= 3; i--) {
        if (!isSystemThread(thread_offset(i))) {
            res = L4_ThreadControl(thread_offset(i), L4_nilspace, L4_nilthread,
                    L4_nilthread, L4_nilthread, 0, (void *)0);
        }
    }

    res = L4_SpaceControl(space, L4_SpaceCtrl_delete,
            KTEST_CLIST, L4_Nilpage, 0, NULL);
    okl4_kspaceid_free(spaceid_pool, space);

    return max;
}
Exemplo n.º 12
0
AddrSpace_t *task_new(L4_ThreadId_t pager)
{
    L4_Word_t tno;
    L4_ThreadId_t tid;
    L4_ThreadId_t space_spec;
    L4_Word_t utcb_location;
    AddrSpace_t *space = NULL;
    slab_t *sb;
    list_t *li;
    thread_t *this;

    mutex_lock(&thrlock);
    tno = threadno_find_free(bitmap, MAX_TASKS);
    if (!tno) {
        mutex_unlock(&thrlock);
        return NULL;
    }

    tid = L4_GlobalId(tno, 1);
    utcb_location = UTCB_AREA_LOCATION;

    space_spec = tid;

    sb = slab_alloc(&thrpool);
    if (!sb) {
        mutex_unlock(&thrlock);
        return NULL;
    }
    
    if (FALSE == (L4_ThreadControl(tid, space_spec, L4_Myself(), L4_nilthread, (void *) utcb_location))) {
        slab_free(&thrpool, sb);
        mutex_unlock(&thrlock);
        return NULL;
    }

    space = address_space_new(tid, pager);
    if (!space) {
        L4_ThreadControl(tid, L4_nilthread, L4_nilthread, L4_nilthread, (void *) -1);
        slab_free(&thrpool, sb);
        mutex_unlock(&thrlock);
        return NULL;
    } else {
        /* set self space, and the specified pager
         * FIXME - using myself as the scheduler */
        L4_ThreadControl(tid, tid, L4_Myself(), pager, (void *) -1);
    }

    li = LIST_TYPE(sb->data);
    this = (thread_t *) li->data;
    list_push(&thread_list, li);

    this->tid = tid;
    this->space = space;
    this->index = 0;
    this->creation = L4_SystemClock();

    threadno_alloc(bitmap, L4_ThreadNo(tid));
    threadno_alloc(space->threads, 0);
    mutex_unlock(&thrlock);
    return space;
}
Exemplo n.º 13
0
static void
ipc_irq_setup(struct new_bench_test *test, int args[])
{
    int r;
    L4_Word_t utcb;
    L4_Word_t utcb_size;
//    L4_Word_t dummy;

    num_iterations = args[0];
    handler_space = L4_nilspace;


    /* We need a maximum of two threads per task */
    utcb_size = L4_GetUtcbSize();
#ifdef NO_UTCB_RELOCATE
    utcb = ~0UL;
#else
    utcb =(L4_Word_t)L4_GetUtcbBase() + utcb_size;
#endif
    /* Create pager */
    master_tid = KBENCH_SERVER;
    pager_tid.raw = KBENCH_SERVER.raw + 1;
    handler_tid.raw = KBENCH_SERVER.raw + 2;
    interrupt = PMU_IRQ;
#if SPINNER
    spinner_tid = L4_GlobalId (L4_ThreadNo (master_tid) + 3, 2);
#endif

    r = L4_ThreadControl (pager_tid, KBENCH_SPACE, master_tid, master_tid, 
                master_tid, 0, (void*)utcb);
    if (r == 0 && (L4_ErrorCode() == 2))
    {
        r = L4_ThreadControl (pager_tid, L4_nilspace, L4_nilthread,
            L4_nilthread, L4_nilthread, 0, (void *) 0);
        assert(r == 1);
        r = L4_ThreadControl (pager_tid, KBENCH_SPACE, master_tid, master_tid, 
                master_tid, 0, (void*)utcb);
        assert(r == 1);
    }
    L4_KDB_SetThreadName(pager_tid, "pager");
    //L4_Schedule(pager_tid, -1, -1, 1, -1, -1, 0, &dummy, &dummy);
    L4_Set_Priority(pager_tid, 254);
    L4_Start_SpIp (pager_tid, (L4_Word_t) pager_stack + sizeof(pager_stack) - 32, START_ADDR (pager));

    L4_Receive(pager_tid);

#ifdef NO_UTCB_RELOCATE
    utcb = ~0UL;
#else
    utcb += utcb_size;
#endif

    r = L4_ThreadControl(handler_tid, KBENCH_SPACE, master_tid, pager_tid, pager_tid, 0, (void *) utcb);
    assert(r == 1);
    L4_KDB_SetThreadName(handler_tid, "handler");
    L4_Set_Priority(handler_tid, 100);

    // Startup notification, start handler thread
    //printf("register irq %ld, to %lx\n", interrupt, handler_tid.raw);

    L4_Word_t control = 0 | (0 << 6) | (31<<27);
    L4_LoadMR(0, interrupt);
    r = L4_InterruptControl(handler_tid, control);
    if (r == 0) {
        printf("Cannot register interrupt %lu\n", interrupt);
    }

    L4_Start_SpIp (handler_tid, (L4_Word_t) handler_stack + sizeof(handler_stack) - 32, START_ADDR(handler));

    L4_Receive(handler_tid);

#if SPINNER
    //Create spinner thread
#ifdef NO_UTCB_RELOCATE
    utcb = ~0UL;
#else
    utcb += utcb_size;
#endif
    r = L4_ThreadControl (spinner_tid, KBENCH_SPACE, master_tid, pager_tid, pager_tid, 0, (void*) utcb);
    if (r == 0) printf("create spinner failed %ld\n", L4_ErrorCode());
    assert(r == 1);
    L4_KDB_SetThreadName(spinner_tid, "spinner");
    //L4_Schedule(spinner_tid, -1, -1, 1, -1, -1, 0, &dummy, &dummy);
    //Set priority to the lowest.
    L4_Set_Priority(spinner_tid, 1);    
    L4_Start_SpIp (spinner_tid, (L4_Word_t) spinner_stack + sizeof(spinner_stack) - 32, START_ADDR (spinner));
#endif
}