END_TEST /* \begin{test}{SIGRAPH0401} \TestDescription{Schedule inheritance graph: mutex release test} \TestImplementationProcess{ Thread 3 (main thread) releases mutex1, effective priority of main thread should be 7. } \TestPassStatus{pass} \TestImplementationStatus{Implemented} \TestRegressionStatus{In regression test suite} \end{test} */ START_TEST(SIGRAPH0401) { L4_MsgTag_t tag; setup_graph(); L4_Receive(main_thread); tag = L4_Make_MsgTag(0x3, 0); L4_Set_MsgTag(tag); L4_Send(main_thread); L4_Receive(main_thread); L4_LoadMR(0, 0); L4_Send(main_thread); measure_effective_prio(7); delete_all(); }
static void zone0150_thread1_routine(void) { L4_MsgTag_t result; L4_ThreadId_t thread0_tid; okl4_init_thread(); while (zone0150_children_can_run == 0) { /* spin */ } thread0_tid.raw = thread0_cap.raw; result = L4_Receive(thread0_tid); fail_unless(L4_IpcSucceeded(result) != 0, "thread1 L4_Receive() failed."); result = L4_Send(thread0_tid); fail_unless(L4_IpcSucceeded(result) != 0, "thread1 L4_Send() failed."); result = L4_Call(thread0_tid); fail_unless(L4_IpcSucceeded(result) != 0, "thread1 L4_Call() failed."); zone0150_child_thread_run++; L4_WaitForever(); }
static void waiting_notify_thread(void *arg) { L4_Word_t notifybits; L4_MsgTag_t tag; L4_Word_t mask; tag = L4_Receive(main_tid); notifybits = L4_Label(tag); L4_Set_NotifyMask(notifybits); L4_Accept(L4_NotifyMsgAcceptor); L4_LoadMR(0, 0); L4_Send(main_tid); tag = L4_WaitNotify(&mask); if (L4_IpcFailed(tag)) { FAILED(); return; } L4_Set_Label(&tag, notifybits); L4_Set_MsgTag(tag); L4_Call(main_tid); while (1) { } }
static void lock_mutex_thread(void) { L4_MsgTag_t tag; L4_Word_t label; L4_Word_t res; tag = L4_Receive(main_thread); while (1) { label = L4_Label(tag); if (label == 0xa) { res = L4_Lock(m); fail_unless(res == 1, "L4_Lock() failed"); L4_Unlock(m); } if (label == 0xb) { res = L4_TryLock(m); fail_unless(res == 0, "L4_TryLock() did not fail"); fail_unless(L4_ErrorCode() == L4_ErrMutexBusy, "Wrong error code"); } tag = L4_Call(main_thread); } L4_WaitForever(); }
static void ipc_test_fault(struct bench_test *test, int args[]) { /* Send empty message to notify pager to startup both threads */ L4_LoadMR (0, 0); L4_Send (pager_tid); L4_Receive (pager_tid); }
static void ipc_irq_test(struct new_bench_test *test, int args[], volatile uint64_t *count) { results = count; /* Send empty message to notify pager to startup test thread */ L4_LoadMR (0, 0); L4_Send (handler_tid); L4_Receive (handler_tid); }
void thread_block(void) { L4_Msg_t msg; L4_MsgClear(&msg); L4_MsgTag_t tag = L4_Receive(L4_Myself()); if (L4_IpcFailed(tag)) { printf("!!! thread_block: failed, tag=%lx\n", tag.raw); } }
// Block a thread forever static void thread_block(void) { L4_Msg_t msg; L4_MsgClear(&msg); L4_MsgTag_t tag = L4_Receive(L4_Myself()); if (L4_IpcFailed(tag)) { printf("blocking thread failed: %lx\n", tag.raw); *(char *) 0 = 0; } }
/* * The medium thread tries to acquire a mutex, releases it once acquired and then * receives from highest priority thread in scenario 1. It increments 2 counters * on success, one for each operation. * It acquires a mutex at initialisation time and waits for any thread before * releasing the mutex in scenario 2. It increments 2 counters on success, * one for each operation. */ void mixed_pi_medium(int argc, char **argv) { L4_ThreadId_t any_thread, tid; L4_MsgTag_t tag; int counter = 10000; while (!libs_ready) ; while (L4_IsNilThread(medium1_prio_thread)) ; tid = medium1_prio_thread; //printf("Middle thread %lx/%lx starts PI test\n", me, pi_main.raw); while (1) { // Initialisation if (scenario2) { //printf("Middle thread %lx/%lx acquires mutex for resource\n", me, pi_main.raw); okl4_libmutex_count_lock(resource_mutex); cnt_m1++; } //printf("(Initialisation) Medium thread %lx/%lx blocks open receiving\n", me, pi_main.raw); L4_Wait(&any_thread); //printf("(Initialisation) Medium thread %lx/%lx received from 0x%lx\n", me, pi_main.raw, any_thread.raw); L4_LoadMR(0, 0); L4_Send(tid); L4_Yield(); /*** Start test ***/ while (stop_spinning) ; wait_a_bit(counter); if (scenario1) { okl4_libmutex_count_lock(resource_mutex); cnt_m1++; wait_a_bit(counter); } else if (scenario2) { //printf("Middle thread %lx/%lx blocks open receiving\n", me, pi_main.raw); tag = L4_Wait(&any_thread); if (L4_IpcSucceeded(tag) && (any_thread.raw == low_prio_thread.raw)) cnt_m2++; wait_a_bit(counter); } okl4_libmutex_count_unlock(resource_mutex); if (!flag1 && (counter < LIMIT)) { counter *= 2; } if (scenario1) { cnt_m2++; tag = L4_Receive(high_prio_thread); if (L4_IpcFailed(tag)) cnt_m2--; } L4_Yield(); tid = pi_main; } }
thread_ref_t create_thread(pd_ref_t pd, void (*start)(void), int priority, int wait) { uintptr_t stack_base; int r; memsection_ref_t stack; thread_ref_t thread; L4_ThreadId_t tid; thread = pd_create_thread_with_priority(pd, priority, &tid); if (thread == 0 || thread == -1) { printf("Failed to create thread.\n"); return -1; } stack = pd_create_memsection(pd, SIZE, &stack_base); if (stack == 0 || stack == -1) { printf("Failed to create stack.\n"); return -1; } r = pd_attach(pd, stack, L4_ReadWriteOnly); if (r != 0) { printf("Failed to attach stack.\n"); return -1; } thread_start(thread, (uintptr_t)start, stack_base + SIZE); /* * Block on the mutex if waiting. The other thread will unlock just * before faulting. */ if (wait) { L4_Receive(thread_l4tid(thread)); okl4_libmutex_lock(serialise_mutex); okl4_libmutex_unlock(serialise_mutex); /* * Wait a little longer for iguana server to print out the * page fault details. */ for (r = 0; r < 1000; r++) L4_Yield(); } return thread; }
static void ping_thread_ovh (void) { /* Wait for pong thread to come up */ L4_Receive (pong_tid); for (int i=0; i < num_iterations; i++) { pingpong_ipc_ovh (pong_tid, num_mrs); } /* Tell master that we're finished */ L4_Set_MsgTag (L4_Niltag); L4_Send (master_tid); for (;;) L4_WaitForever(); /* NOTREACHED */ }
static void setup_extended_graph(void) { setup_graph(); prio8_thread = createThread(other_sending_thread); L4_KDB_SetThreadName(prio8_thread, "prio8_thread"); L4_Set_Priority(prio8_thread, 201); L4_Set_Priority(prio8_thread, 8); prio6bis_thread = createThread(other_sending_thread); L4_KDB_SetThreadName(prio6bis_thread, "prio6bis_thread"); L4_Set_Priority(prio6bis_thread, 201); L4_Set_Priority(prio6bis_thread, 6); L4_Receive(main_thread); L4_LoadMR(0, 0); L4_Send(main_thread); }
/* * The highest priority thread blocks sending to medium thread in the * first scenario. It increments a counter on success. * It tries to acquire a mutex in the second scenario. It increments a counter on success. */ void mixed_pi_high(int argc, char **argv) { L4_MsgTag_t tag; while (!libs_ready) ; L4_Receive(pi_main); //printf("High thread %lx/%lx starts PI test\n", me, pi_main.raw); while (1) { while (stop_spinning) ; if (scenario1) { L4_LoadMR(0, 0); tag = L4_Send(medium2_prio_thread); if (L4_IpcSucceeded(tag)) cnt_h++; } else if (scenario2) { //printf("High thread %lx/%lx acquiring mutex for resource, current holder: 0x%lx\n", me, pi_main.raw, resource_mutex->holder); okl4_libmutex_count_lock(resource_mutex); //printf("High thread %lx/%lx acquired mutex for resource\n", me, pi_main.raw); cnt_h++; } // If intermediate threads have run, then increment respective counter. if (flag1) cnt_i1++; if (flag3) cnt_i2++; if (scenario2) okl4_libmutex_count_unlock(resource_mutex); // Tell main thread iteration is done. L4_LoadMR(0, 0); L4_Call(pi_main); // Re-initialise. if (flag1) { L4_Receive_Nonblocking(medium1_prio_thread); flag1 = 0; } if (flag3) { L4_Receive_Nonblocking(medium3_prio_thread); flag3 = 0; } } }
static void runnable_main_thread(void) { L4_Word_t result, label; L4_MsgTag_t tag; label = 0; result = L4_Lock(mutex1); fail_unless(result == 1, "L4_Lock() failed"); while (1) { if (label == 0x3) { L4_Unlock(mutex1); } tag = L4_Make_MsgTag(0x1, 0); L4_Set_MsgTag(tag); L4_Send(setup_thread); tag = L4_Receive(setup_thread); label = L4_Label(tag); } }
static void setup_graph(void) { main_thread = createThread(runnable_main_thread); L4_KDB_SetThreadName(main_thread, "main_thread"); L4_Set_Priority(main_thread, 3); L4_Receive(main_thread); prio6_thread = createThread(sending_thread); L4_KDB_SetThreadName(prio6_thread, "prio6_thread"); L4_Set_UserDefinedHandleOf(prio6_thread, 0); L4_Set_Priority(prio6_thread, 201); L4_Set_Priority(prio6_thread, 6); prio1_thread = createThread(sending_thread); L4_KDB_SetThreadName(prio1_thread, "prio1_thread"); L4_Set_UserDefinedHandleOf(prio1_thread, 1); L4_Set_Priority(prio1_thread, 201); L4_Set_Priority(prio1_thread, 1); prio2_thread = createThread(locking_m1_thread); L4_KDB_SetThreadName(prio2_thread, "prio2_thread"); L4_Set_Priority(prio2_thread, 201); L4_Set_Priority(prio2_thread, 2); prio5_thread = createThread(locking_m1_thread); L4_KDB_SetThreadName(prio5_thread, "prio5_thread"); L4_Set_Priority(prio5_thread, 201); L4_Set_Priority(prio5_thread, 5); prio4_thread = createThread(locking_m2_thread); L4_KDB_SetThreadName(prio4_thread, "prio4_thread"); L4_Set_Priority(prio4_thread, 201); L4_Set_Priority(prio4_thread, 4); prio7_thread = createThread(locking_m2_thread); L4_KDB_SetThreadName(prio7_thread, "prio7_thread"); L4_Set_Priority(prio7_thread, 201); L4_Set_Priority(prio7_thread, 7); L4_LoadMR(0, 0); L4_Send(main_thread); measure_thread = createThread(measure_effective_prio_thread); L4_KDB_SetThreadName(measure_thread, "measure_thread"); L4_Set_Priority(measure_thread, 9); }
static void sending_thread(void) { L4_Word_t result; L4_MsgTag_t tag; if (L4_UserDefinedHandle()) { result = L4_Lock(mutex2); fail_unless(result == 1, "L4_Lock() failed"); } L4_LoadMR(0, 0); L4_Send(main_thread); tag = L4_Receive(setup_thread); if (L4_Label(tag) == 0x3) { L4_Unlock(mutex2); L4_LoadMR(0, 0); L4_Send(main_thread); } L4_WaitForever(); while(1) ; }
static void ping_thread_buffer (void) { volatile L4_Word_t x; /* Wait for pong thread to come up */ L4_Receive (pong_tid); for (int i=0; i < num_iterations; i++) { pingpong_ipc (pong_tid, num_mrs); x = fault_area[0]; } /* Tell master that we're finished */ L4_Set_MsgTag (L4_Niltag); L4_Send (master_tid); for (;;) L4_WaitForever(); /* NOTREACHED */ }
static void create_delete_mutex_thread(void) { L4_MsgTag_t tag; L4_Word_t label; L4_Word_t res; tag = L4_Receive(main_thread); label = L4_Label(tag); if (label == 0xc) { res = L4_CreateMutex(m); fail_unless(res == 0, "L4_CreateMutex() did not fail"); fail_unless(L4_ErrorCode() == L4_ErrInvalidSpace, "Wrong error code on create"); } if (label == 0xd) { res = L4_DeleteMutex(m); fail_unless(res == 0, "L4_DeleteMutex() did not fail"); fail_unless(L4_ErrorCode() == L4_ErrInvalidSpace, "Wrong error code on delete"); } L4_Call(main_thread); L4_WaitForever(); }
int main(int argc, char **argv) { struct okl4_libmutex rm; L4_ThreadId_t tid; int i, max_iteration, eg_num, server_on; L4_Word_t me; L4_MsgTag_t tag = L4_Niltag; /*** Initialisation ***/ pi_main = thread_l4tid(env_thread(iguana_getenv("MAIN"))); me = pi_main.raw; eg_num = max_iteration = server_on = 0; if (argc == 3) { eg_num = atoi(argv[0]); max_iteration = atoi(argv[1]); server_on = atoi(argv[2]); } else { printf("(%s 0x%lx) Error: Argument(s) missing!\n", test_name, me); return 1; } resource_mutex = &rm; okl4_libmutex_init(resource_mutex); high_prio_thread = medium1_prio_thread = medium2_prio_thread = medium3_prio_thread = low_prio_thread = L4_nilthread; high_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_HIGH"))); medium3_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_INTERMEDIATE_2"))); medium2_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_MEDIUM"))); medium1_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_INTERMEDIATE_1"))); low_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_LOW"))); // Tell other threads that it is safe to use libraries libs_ready = 1; if (!server_on) printf("Start %s test #%d(0x%lx)\n", test_name, eg_num, me); /*** Start test ***/ scenario1 = 1; for (i = 0; i < 2 * max_iteration; i++) { // Wait for threads to be ready tag = L4_Wait(&tid); // If one thread had a problem while initialisation, then stop the test and notify // server that the test is dead. if (L4_Label(tag) == 0xdead) { rtos_init(); test_died(test_name, eg_num); rtos_cleanup(); return 1; } // Tell high prio thread to start the next iteration. L4_LoadMR(0, 0); tag = L4_Send(high_prio_thread); stop_spinning = 0; // Wait for the iteration to finish. L4_Receive(high_prio_thread); stop_spinning = 1; // If end of iterations for scenario1, then report results to RTOS server if server is on. if (i == (max_iteration - 1)) { if (server_on) { rtos_init(); mixed_priority_inversion_results(eg_num, 1, max_iteration, cnt_h, cnt_m1, cnt_m2, cnt_l, cnt_i1, cnt_i2); } else print_metrics(max_iteration); // Start scenario2 cnt_h = cnt_m1 = cnt_m2 = cnt_l = cnt_i1 = cnt_i2 = 0; scenario1 = 0; scenario2 = 1; } } /*** Test finished ***/ thread_delete(medium1_prio_thread); thread_delete(medium3_prio_thread); thread_delete(high_prio_thread); thread_delete(medium2_prio_thread); thread_delete(low_prio_thread); /* Clean up allocated mutexes. */ okl4_libmutex_free(resource_mutex); // If RTOS server is on, report results to it. if (server_on) { mixed_priority_inversion_results(eg_num, 2, max_iteration, cnt_h, cnt_m1, cnt_m2, cnt_l, cnt_i1, cnt_i2); rtos_cleanup(); } else { print_metrics(max_iteration); printf("%s test #%d(0x%lx) finished\n", test_name, eg_num, me); } return 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 }