Пример #1
0
/* The enclosed test relies on the current thread being able to create two
 * threads of unequal priority, both less than the caller's own priority. For
 * this we need at least 3 priority levels, assuming that the current thread is
 * running at the highest priority.
 */
static int
test_set_priority(struct env* env)
{
    helper_thread_t thread1;
    helper_thread_t thread2;
    ZF_LOGD("test_set_priority starting\n");
    create_helper_thread(env, &thread1);
    set_helper_priority(&thread1, SCHED0005_HIGHEST_PRIO);

    create_helper_thread(env, &thread2);
    set_helper_priority(&thread2, SCHED0005_HIGHEST_PRIO - 1);

    set_priority_step = 0;
    ZF_LOGD("      ");

    start_helper(env, &thread1, (helper_fn_t) set_priority_helper_1,
                 (seL4_Word) &thread1.thread.tcb.cptr,
                 (seL4_Word) &thread2.thread.tcb.cptr, 0, 0);

    start_helper(env, &thread2, (helper_fn_t) set_priority_helper_2,
                 (seL4_Word) &thread1.thread.tcb.cptr,
                 (seL4_Word) &thread2.thread.tcb.cptr, 0, 0);

    wait_for_helper(&thread1);
    wait_for_helper(&thread2);

    test_check(set_priority_step == 4);

    ZF_LOGD("\n");
    cleanup_helper(env, &thread1);
    cleanup_helper(env, &thread2);
    return sel4test_get_result();
}
Пример #2
0
static int
test_suspend(struct env* env)
{
    helper_thread_t thread1;
    helper_thread_t thread2a;
    helper_thread_t thread2b;

    ZF_LOGD("Starting test_suspend\n");

    create_helper_thread(env, &thread1);
    ZF_LOGD("Show me\n");
    create_helper_thread(env, &thread2a);

    create_helper_thread(env, &thread2b);

    /* First set all the helper threads to have unique priorities
     * and then start them in order of priority. This is so when
     * the 'start_helper' function does an IPC to the helper
     * thread, it doesn't allow one of the already started helper
     * threads to run at all */
    set_helper_priority(&thread1, 0);
    set_helper_priority(&thread2a, 1);
    set_helper_priority(&thread2b, 2);

    start_helper(env, &thread1, (helper_fn_t) suspend_test_helper_1,
                 (seL4_Word) &thread1.thread.tcb.cptr,
                 (seL4_Word) &thread2a.thread.tcb.cptr,
                 (seL4_Word) &thread2b.thread.tcb.cptr, 0);

    start_helper(env, &thread2a, (helper_fn_t) suspend_test_helper_2a,
                 (seL4_Word) &thread1.thread.tcb.cptr,
                 (seL4_Word) &thread2a.thread.tcb.cptr,
                 (seL4_Word) &thread2b.thread.tcb.cptr, 0);

    start_helper(env, &thread2b, (helper_fn_t) suspend_test_helper_2b,
                 (seL4_Word) &thread1.thread.tcb.cptr,
                 (seL4_Word) &thread2a.thread.tcb.cptr,
                 (seL4_Word) &thread2b.thread.tcb.cptr, 0);

    /* Now set their priorities to what we want */
    set_helper_priority(&thread1, 100);
    set_helper_priority(&thread2a, 101);
    set_helper_priority(&thread2b, 101);

    suspend_test_step = 0;
    ZF_LOGD("      ");

    wait_for_helper(&thread1);
    wait_for_helper(&thread2b);

    CHECK_STEP(suspend_test_step, 6);
    ZF_LOGD("\n");

    cleanup_helper(env, &thread1);
    cleanup_helper(env, &thread2a);
    cleanup_helper(env, &thread2b);

    return sel4test_get_result();
}
Пример #3
0
static int
test_ipc_prios(struct env* env)
{
    vka_t *vka = &env->vka;
    helper_thread_t thread0;
    helper_thread_t thread1;
    helper_thread_t thread2;
    helper_thread_t thread3;
    int result = 0;

    ipc_test_data_t data;
    memset(&data, 0, sizeof(data));

    data.ep0 = vka_alloc_endpoint_leaky(vka);
    data.ep1 = vka_alloc_endpoint_leaky(vka);
    data.ep2 = vka_alloc_endpoint_leaky(vka);
    data.ep3 = vka_alloc_endpoint_leaky(vka);

    create_helper_thread(env, &thread0);
    set_helper_priority(&thread0, 0);

    create_helper_thread(env, &thread1);
    set_helper_priority(&thread1, 1);

    create_helper_thread(env, &thread2);
    set_helper_priority(&thread2, 2);

    create_helper_thread(env, &thread3);
    set_helper_priority(&thread3, 3);

    data.tcb0 = thread0.thread.tcb.cptr;
    data.tcb1 = thread1.thread.tcb.cptr;
    data.tcb2 = thread2.thread.tcb.cptr;
    data.tcb3 = thread3.thread.tcb.cptr;

    ZF_LOGD("      ");
    ipc_test_step = 0;

    start_helper(env, &thread0, (helper_fn_t) ipc_test_helper_0, (seL4_Word) &data, 0, 0, 0);
    start_helper(env, &thread1, (helper_fn_t) ipc_test_helper_1, (seL4_Word) &data, 0, 0, 0);
    start_helper(env, &thread2, (helper_fn_t) ipc_test_helper_2, (seL4_Word) &data, 0, 0, 0);
    start_helper(env, &thread3, (helper_fn_t) ipc_test_helper_3, (seL4_Word) &data, 0, 0, 0);

    result |= (int)wait_for_helper(&thread1);
    result |= (int)wait_for_helper(&thread3);

    CHECK_STEP(ipc_test_step, 10);
    ZF_LOGD("\n");

    cleanup_helper(env, &thread0);
    cleanup_helper(env, &thread1);
    cleanup_helper(env, &thread2);
    cleanup_helper(env, &thread3);

    return result;
}
Пример #4
0
static int
test_full_cspace(env_t env)
{
    int error;
    seL4_CPtr cnode[CONFIG_WORD_SIZE];
    seL4_CPtr ep = vka_alloc_endpoint_leaky(&env->vka);
    seL4_Word ep_pos = 1;

    /* Create 32 or 64 cnodes, each resolving one bit. */
    for (unsigned int i = 0; i < CONFIG_WORD_SIZE; i++) {
        cnode[i] = vka_alloc_cnode_object_leaky(&env->vka, 1);
        assert(cnode[i]);
    }

    /* Copy cnode i to alternating slots in cnode i-1. */
    seL4_Word slot = 0;
    for (unsigned int i = 1; i < CONFIG_WORD_SIZE; i++) {
        error = seL4_CNode_Copy(
                    cnode[i - 1], slot, 1,
                    env->cspace_root, cnode[i], seL4_WordBits,
                    seL4_AllRights);
        test_assert(!error);
        ep_pos |= (slot << i);
        slot ^= 1;
    }
    /* In the final cnode, put an IPC endpoint in slot 1. */
    error = seL4_CNode_Copy(
                cnode[CONFIG_WORD_SIZE - 1], slot, 1,
                env->cspace_root, ep, seL4_WordBits,
                seL4_AllRights);
    test_assert(!error);

    /* Start a helper thread in our own cspace, to let it get set up. */
    helper_thread_t t;

    create_helper_thread(env, &t);
    start_helper(env, &t, ipc_caller, ep, ep_pos, CONFIG_WORD_SIZE, 0);

    /* Wait for it. */
    seL4_MessageInfo_t tag;
    seL4_Word sender_badge = 0;
    tag = seL4_Recv(ep, &sender_badge);
    test_assert(seL4_MessageInfo_get_length(tag) == 1);
    test_assert(seL4_GetMR(0) == READY_MAGIC);

    /* Now switch its cspace. */
    error = seL4_TCB_SetSpace(t.thread.tcb.cptr, t.fault_endpoint,
                              cnode[0], seL4_NilData, env->page_directory,
                              seL4_NilData);

    test_assert(!error);

    /* And now wait for it to do some tests and return to us. */
    tag = seL4_Recv(ep, &sender_badge);
    test_assert(seL4_MessageInfo_get_length(tag) == 1);
    test_assert(seL4_GetMR(0) == SUCCESS_MAGIC);

    cleanup_helper(env, &t);
    return sel4test_get_result();
}
Пример #5
0
/*
 * Test that thread suspending works when idling the system.
 * Note: This test non-deterministically fails. If you find only this test
 * try re-running the test suite.
 */
static int
test_thread_suspend(env_t env)
{
    helper_thread_t t1;
    volatile seL4_Word counter;
    ZF_LOGD("test_thread_suspend\n");
    create_helper_thread(env, &t1);

    set_helper_priority(&t1, 100);
    start_helper(env, &t1, (helper_fn_t) counter_func, (seL4_Word) &counter, 0, 0, 0);

    timer_periodic(env->timer->timer, 10 * NS_IN_MS);
    timer_start(env->timer->timer);
    sel4_timer_handle_single_irq(env->timer);

    seL4_Word old_counter;

    /* Let the counter thread run. We might have a pending interrupt, so
     * wait twice. */
    wait_for_timer_interrupt(env);
    wait_for_timer_interrupt(env);

    old_counter = counter;

    /* Let it run again. */
    wait_for_timer_interrupt(env);

    /* Now, counter should have moved. */
    test_check(counter != old_counter);
    old_counter = counter;

    /* Suspend the thread, and wait again. */
    seL4_TCB_Suspend(t1.thread.tcb.cptr);
    wait_for_timer_interrupt(env);

    /* Counter should not have moved. */
    test_check(counter == old_counter);
    old_counter = counter;

    /* Check once more for good measure. */
    wait_for_timer_interrupt(env);

    /* Counter should not have moved. */
    test_check(counter == old_counter);
    old_counter = counter;

    /* Resume the thread and check it does move. */
    seL4_TCB_Resume(t1.thread.tcb.cptr);
    wait_for_timer_interrupt(env);
    test_check(counter != old_counter);

    /* Done. */
    timer_stop(env->timer->timer);
    sel4_timer_handle_single_irq(env->timer);
    cleanup_helper(env, &t1);

    return sel4test_get_result();
}
Пример #6
0
/*
 * Free all used resources in the tree
 */
bool syn_tree::cleanup(void) {
	bool res;

	// clear all other attributes
	res = cleanup_helper(&root);
	if(res)
		cur = NULL;
	return res;
}
Пример #7
0
/*
 * Remove the current token (moves current token to parent token)
 */
bool syn_tree::remove(void) {
	token *parent = NULL;

	// check that current token exists
	if(!cur)
		return false;

	// remove current token and move to parent token
	if(!cur->get_parent()) {
		cleanup_helper(&cur);
		root = cur;
	} else {
		parent = cur->get_parent();
		for(unsigned int pos = 0; pos < parent->size(); pos++)
			if(parent->get_child(pos) == cur) {
				parent->remove_child(pos);
				break;
			}
		cleanup_helper(&cur);
		cur = parent;
	}
	return true;
}
Пример #8
0
int test_tcb_null_cspace_setspace(env_t env)
{
    helper_thread_t thread;
    int error;

    create_helper_thread(env, &thread);

    /* This should fail because we're passing an invalid CSpace cap. */
    error = seL4_TCB_SetSpace(thread.thread.tcb.cptr, 0, seL4_CapNull,
                              seL4_CapData_Guard_new(0, 0), env->page_directory,
                              seL4_CapData_Guard_new(0, 0));

    cleanup_helper(env, &thread);

    return error ? sel4test_get_result() : FAILURE;
}
Пример #9
0
static int
test_all_priorities(struct env* env)
{
    int i;

    helper_thread_t **threads = (helper_thread_t **) malloc(sizeof(helper_thread_t*) * NUM_PRIOS);
    assert(threads != NULL);

    for (i = 0; i < NUM_PRIOS; i++) {
        threads[i] = (helper_thread_t*) malloc(sizeof(helper_thread_t));
        assert(threads[i]);
    }

    vka_t *vka = &env->vka;
    ZF_LOGD("Testing all thread priorities");
    volatile seL4_Word last_prio = MAX_PRIO + 1;

    seL4_CPtr ep = vka_alloc_endpoint_leaky(vka);

    for (int prio = MIN_PRIO; prio <= MAX_PRIO; prio++) {
        int idx = prio - MIN_PRIO;
        test_check(idx >= 0 && idx < NUM_PRIOS);
        create_helper_thread(env, threads[idx]);
        set_helper_priority(threads[idx], prio);

        start_helper(env, threads[idx], (helper_fn_t) prio_test_func,
                     prio, (seL4_Word) &last_prio, ep, 0);
    }

    /* Now block. */
    seL4_Word sender_badge = 0;
    seL4_Recv(ep, &sender_badge);

    /* When we get woken up, last_prio should be MIN_PRIO. */
    test_check(last_prio == MIN_PRIO);

    for (int prio = MIN_PRIO; prio <= MAX_PRIO; prio++) {
        int idx = prio - MIN_PRIO;
        cleanup_helper(env, threads[idx]);
        free(threads[idx]);
    }
    free(threads);

    return sel4test_get_result();
}
Пример #10
0
/*
 * Removes a child node (recursively) from the current token
 */
bool syn_tree::remove_child(unsigned int index) {

	// check that current token exists
	if(!cur)
		return false;

	// check that index is with-in-bounds
	if(!get_size()
			|| index >= get_size())
		return false;


	// cleanup
	token *child = cur->get_child(index);
	cur->remove_child(index);
	cleanup_helper(&child);
	return true;
}
Пример #11
0
/*
 * Release resources used by tree
 */
bool syn_tree::cleanup_helper(token **root) {
	unsigned int children;

	// check that root token exists
	if(!(*root))
		return 0;

	children = (*root)->size();

	// remove all children of current token
	for(unsigned int i = 0; i < children; i++) {
		token *child = (*root)->get_child(i);
		if(!cleanup_helper(&child))
			return false;
	}

	// remove child tokens
	(*root)->remove_children();

	// remove root token
	delete (*root);
	(*root) = NULL;
	return true;
}
Пример #12
0
static int
test_ep_recycle(env_t env)
{
    seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0);
    struct {
        helper_thread_t thread;
        seL4_CPtr badged_ep;
        seL4_CPtr derived_badged_ep;
        volatile seL4_Word done;
    } senders[NUM_BADGED_CLIENTS];
    helper_thread_t bouncer;
    seL4_CPtr bounce_ep;
    UNUSED int error;
    seL4_CPtr ep;

    /* Create the master endpoint. */
    ep = vka_alloc_endpoint_leaky(&env->vka);

    /* Create N badged endpoints, and derive each of them. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        senders[i].badged_ep = get_free_slot(env);
        assert(senders[i].badged_ep != 0);

        senders[i].derived_badged_ep = get_free_slot(env);
        assert(senders[i].derived_badged_ep != 0);

        seL4_CapData_t cap_data;
        cap_data = seL4_CapData_Badge_new (i + 200);
        error = cnode_mint(env, ep, senders[i].badged_ep, seL4_AllRights, cap_data);
        assert(!error);

        error = cnode_copy(env, senders[i].badged_ep, senders[i].derived_badged_ep, seL4_AllRights);
        assert(!error);

        create_helper_thread(env, &senders[i].thread);
        set_helper_priority(&senders[i].thread, 100);

        senders[i].done = -1;
    }
    /* Create a bounce thread so we can get lower prio threads to run. */
    bounce_ep = vka_alloc_endpoint_leaky(&env->vka);
    create_helper_thread(env, &bouncer);
    set_helper_priority(&bouncer, 0);
    start_helper(env, &bouncer, bouncer_func, bounce_ep, 0, 0, 0);

    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        start_helper(env, &senders[i].thread, (helper_fn_t) call_func,
                     senders[i].derived_badged_ep, i + 100, (seL4_Word) &senders[i].done, 0);
    }

    /* Let the sender threads run. */
    seL4_Call(bounce_ep, tag);
    /* Receive a message from each endpoint and check the badge. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        seL4_Word sender_badge;
        seL4_MessageInfo_ptr_set_length(&tag, 1);
        tag = seL4_Recv(ep, &sender_badge);
        assert(seL4_MessageInfo_get_length(tag) == 1);
        assert(seL4_GetMR(0) == sender_badge - 100);
        seL4_SetMR(0, ~seL4_GetMR(0));
        seL4_Reply(tag);
    }
    /* Let the sender threads run. */
    seL4_Call(bounce_ep, tag);
    /* Check none of the threads have failed yet. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        assert(senders[i].done == 0);
    }
    /* Recycle each endpoint. */
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        error = cnode_recycle(env, senders[i].badged_ep);
        assert(!error);

        /* Let thread run. */
        seL4_Call(bounce_ep, tag);
        /* Check that only the intended threads have now aborted. */
        for (int j = 0; j < NUM_BADGED_CLIENTS; j++) {
            if (j <= i) {
                assert(senders[j].done == 1);
            } else {
                assert(senders[j].done == 0);
            }
        }
    }
    seL4_Call(bounce_ep, tag);
    for (int i = 0; i < NUM_BADGED_CLIENTS; i++) {
        cleanup_helper(env, &senders[i].thread);
    }
    cleanup_helper(env, &bouncer);

    return sel4test_get_result();
}