END_TEST /* \begin{test}{SMT0302} \TestDescription{Thread creation and deletion of ping pong threads} \TestFunctionalityTested{Global scheduler, thread creation and deletion} \TestImplementationProcess{ The following process is repeated: \begin{enumerate} \item Create two threads running IPC ping pong. Each thread is constrained to run on separate unused hardware threads. \item The threads are deleted. \end{enumerate} The main threads are constrained to running on hardware thread 0. } \TestImplementationStatus{Implemented} \TestIsFullyAutomated{Yes} \TestRegressionStatus{In regression test suite} \TestNotes{Hardware constraint specification is only used on supported architectures. For others, the threads will execute round robin.} \TestSeeAlso{See document \emph{L4 SMT Support} 10020:2005} \end{test} */ START_TEST(SMT0302) { int j; L4_ThreadId_t rthread[5]; pingpong_cleanup = 0; for (j=0;j<TEST3_MAJOR_ITERATIONS;j++) { changeThreadCreationSMTBitmask(2); rthread[0] = createThreadInSpace(L4_nilthread, (void *)synch_pong); changeThreadCreationSMTBitmask(4); rthread[1] = createThreadInSpace(L4_nilthread, (void *)synch_ping); /* Give threads time to start up or our pager may complain * about us going away. */ L4_ThreadSwitch(main_thread); sleep_a_bit(); L4_ThreadSwitch(main_thread); /* alternate deleting threads first */ deleteThread(rthread[(j+1)%2]); deleteThread(rthread[j%2]); } }
END_TEST /* \begin{test}{SMT0301} \TestDescription{Thread creation and deletion of receiving thread} \TestFunctionalityTested{Global scheduler, thread creation and deletion} \TestImplementationProcess{ The following process is repeated: \begin{enumerate} \item Five receiving threads are created. All threads are scheduled across all available hardware threads. \item The threads are then deleted. \end{enumerate} The main threads are constrained to running on hardware thread 0. } \TestImplementationStatus{Implemented} \TestIsFullyAutomated{Yes} \TestRegressionStatus{In regression test suite} \TestNotes{Hardware constraint specification is only used on supported architectures. For others, the threads will execute round robin.} \TestSeeAlso{See document \emph{L4 SMT Support} 10020:2005} \end{test} */ START_TEST(SMT0301) { int i, j; L4_ThreadId_t rthread[5]; pingpong_cleanup = 0; changeThreadCreationSMTBitmask(63); for (j=0;j<TEST3_MAJOR_ITERATIONS;j++) { for (i=0;i<5;i++) rthread[i] = createThreadInSpace(L4_nilthread, (void *)synch_recv); /* Give threads time to start up or our pager may complain * about us going away. */ L4_ThreadSwitch(main_thread); sleep_a_bit(); L4_ThreadSwitch(main_thread); for (i=0;i<5;i++) deleteThread(rthread[i]); } }
END_TEST START_TEST(SMT0304) { int j, i; L4_ThreadId_t rthread[6]; // smt0303 but with deletes in reverse order pingpong_cleanup = 0; pingpong_counter = 0; for (j=0;j<TEST3_MAJOR_ITERATIONS;j++) { changeThreadCreationSMTBitmask(2); rthread[0] = createThreadInSpace(L4_nilthread, (void *)synch_pong); changeThreadCreationSMTBitmask(63); for(i=0;i<TEST303_MINOR;i++) { rthread[i+1] = createThreadInSpace(L4_nilthread, (void *)synch_ping); } /* Give threads time to start up or our pager may complain * about us going away. */ L4_ThreadSwitch(main_thread); sleep_a_bit(); sleep_a_bit(); for(i=0; i<TEST303_MINOR; i++) deleteThread(rthread[i+1]); deleteThread(rthread[0]); // delete pong } }
void mutex_lock(mutex_t *m) { L4_Word_t me = L4_Myself().raw; while (!try_lock(m, me)) { L4_ThreadSwitch(L4_nilthread); } }
END_TEST /* \begin{test}{MUTEX0407} \TestDescription{Delete thread about to acquire a mutex.} \TestFunctionalityTested{\Func{L4\_Lock} and \Func{L4\_ThreadControl}} \TestImplementationProcess{ \begin{enumerate} \item Create a mutex. \item Lock the created mutex. \item Create a second thread that attempts to lock the mutex. \item Release the mutex. \item Delete that thread. \end{enumerate} } \TestPassStatus{pass} \TestImplementationStatus{Implemented} \TestRegressionStatus{In regression test suite} \end{test} */ START_TEST(MUTEX0407) { L4_Word_t res; L4_ThreadId_t child; res = okl4_kmutexid_allocany(mutexid_pool, &m); fail_unless(res == OKL4_OK, "Failed to allocate any mutex id."); /* Create a mutex. */ res = L4_CreateMutex(m); fail_unless(res == 1, "L4_CreateMutex() failed"); /* Lock the mutex. */ res = L4_Lock(m); fail_unless(res == 1, "L4_Lock() failed"); /* Get our child to lock the mutex. */ child = createThread(mutex0406_child_thread); L4_Set_Priority(child, 255); L4_ThreadSwitch(child); /* Restore the priority to below us. */ L4_Set_Priority(child, 1); /* Release the mutex. */ res = L4_Unlock(m); /* Delete our child. */ deleteThread(child); /* Ensure we can still acquire/release the lock. */ res = L4_Lock(m); fail_unless(res == 1, "L4_Lock() failed"); res = L4_Unlock(m); fail_unless(res == 1, "L4_Unlock() failed"); res = L4_DeleteMutex(m); fail_unless(res == 1, "L4_DeleteMutex() failed"); okl4_kmutexid_free(mutexid_pool, m); }
void okl4_mutex_lock(okl4_mutex_t m) { L4_Word_t me = L4_Myself().raw; L4_ThreadId_t holder; holder.raw = m->holder; while (!try_lock(m, me)) { L4_ThreadSwitch(holder); } }
END_TEST /* \begin{test}{SMT0200} \TestDescription{Verify scheduling of unconstrained threads in a single scheduling domain } \TestFunctionalityTested{Global Scheduler, Constraints} \TestImplementationProcess{ Five spinning threads are created. All threads are scheduled across all available hardware threads. The main threads are constrained to running on hardware thread 0. } \TestImplementationStatus{Implemented} \TestIsFullyAutomated{Yes} \TestRegressionStatus{In regression test suite} \TestNotes{Hardware constraint specification is only used on supported architectures. For others, the threads will execute round robin.} \TestSeeAlso{See document \emph{L4 SMT Support} 10020:2005} \end{test} */ START_TEST(SMT0200) { uint64_t diff; L4_ThreadId_t rthread[5]; thread_simple_spinner_cleanup = 0; thread_simple_spinner_start = 0; /* FIXME: Restrict to a single processor */ changeThreadCreationSMTBitmask(63); rthread[0] = createThreadInSpace(L4_nilthread, (void *)thread_simple_spinner); rthread[1] = createThreadInSpace(L4_nilthread, (void *)thread_simple_spinner); rthread[2] = createThreadInSpace(L4_nilthread, (void *)thread_simple_spinner); rthread[3] = createThreadInSpace(L4_nilthread, (void *)thread_simple_spinner); rthread[4] = createThreadInSpace(L4_nilthread, (void *)thread_simple_spinner_main); while(thread_simple_spinner_cleanup == 0) L4_ThreadSwitch(main_thread); diff = counter_var(0, 5); if (diff > 15) { fail_unless(0, "It appears there was a scheduling error\n" "We expect each thread to get an equal share, but\n" "one thread, ran more or less often than expected.\n" "(Specifically, it had greater than 15% difference to the average\n"); } }
PUBLIC IX_STATUS ixOsalFastMutexUnlock(IxOsalFastMutex *mutex) { VALID_HANDLE(mutex); struct mutex *mtx = (struct mutex *) *mutex; mtx->fHolder = 0; if (mtx->fNeeded) { mtx->fNeeded = 0; L4_ThreadSwitch(L4_nilthread); } return IX_SUCCESS; }
END_TEST /* \begin{test}{SMT0500} \TestDescription{IPC Ping pong constrained to same hardware thread} \TestFunctionalityTested{Global scheduler, IPC} \TestImplementationProcess{ Two threads are created and constrained to the same hardware thread. This test passes if progress is made. } \TestImplementationStatus{Implemented} \TestIsFullyAutomated{Yes} \TestRegressionStatus{In regression test suite} \TestImplementationStatus{Implemented} \TestIsFullyAutomated{Yes} \TestRegressionStatus{In regression test suite} \TestNotes{Hardware constraint specification is only used on supported architectures. For others, the threads will execute round robin.} \TestSeeAlso{See document \emph{L4 SMT Support} 10020:2005} \end{test} */ START_TEST(SMT0500) { L4_ThreadId_t rthread[2]; pingpong_cleanup = 0; pingpong_counter = 0; changeThreadCreationSMTBitmask(8); rthread[0] = createThreadInSpace(L4_nilthread, (void *)synch_pong); rthread[1] = createThreadInSpace(L4_nilthread, (void *)synch_ping); L4_ThreadSwitch(main_thread); sleep_a_bit(); sleep_a_bit(); sleep_a_bit(); sleep_a_bit(); sleep_a_bit(); printf("ppc %d\n", pingpong_counter); deleteThread(rthread[0]); deleteThread(rthread[1]); fail_unless(pingpong_counter > 10, "poor smt ping pong result\n"); }
static void pager (void) { L4_ThreadId_t tid; L4_MsgTag_t tag; L4_Msg_t msg; int count = 0; for (;;) { tag = L4_Wait(&tid); for (;;) { L4_Word_t faddr, fip; L4_MsgStore(tag, &msg); if (L4_Label(tag) == START_LABEL) { // Startup notification, start ping and pong thread void (*start_addr)(void); void (*pong_start_addr)(void); L4_Word_t *pong_stack_addr = pong_stack; if (pagertimer) { start_addr = ping_thread_pager; } else if (pagertimer_simulated) { start_addr = ping_thread_simulated; } else if (fass_buffer) { start_addr = ping_thread_buffer; } else if (fault_test) { count = 0; start_addr = NULL; } else if (intra_close) { start_addr = ping_thread_close; } else if (intra_open) { start_addr = ping_thread_open; } else if (intra_rpc) { start_addr = ping_thread_rpc_server; } else if (intra_ovh) { start_addr = ping_thread_ovh; } else if (intra_async) { start_addr = ping_thread_async; } else if (intra_async_ovh) { start_addr = ping_thread_async_ovh; } else { start_addr = ping_thread; } if (start_addr != NULL) { /*printf("ping_start_addr: %lx ping_stack_addr: %lx\n", START_ADDR (start_addr), (L4_Word_t) ping_stack);*/ send_startup_ipc (ping_tid, START_ADDR(start_addr), (L4_Word_t) ping_stack + sizeof (ping_stack) - 32); L4_ThreadSwitch(ping_tid); } if (fass_buffer) { pong_start_addr = pong_thread_buffer; pong_stack_addr = pong_stack_fass; } else if (fass) { pong_start_addr = pong_thread_fass; pong_stack_addr = pong_stack_fass; } else if (fault_test) { pong_stack_addr = pong_stack_fass; pong_start_addr = pong_thread_faulter; } else if (intra_close) { pong_start_addr = pong_thread_close; } else if (intra_open) { pong_start_addr = pong_thread_open; } else if (intra_rpc) { pong_start_addr = pong_thread_close; } else if (intra_ovh) { pong_start_addr = pong_thread_ovh; } else if (intra_async) { pong_start_addr = pong_thread_async; } else if (intra_async_ovh) { pong_start_addr = pong_thread_async_ovh; } else { pong_start_addr = pong_thread; } if (!pagertimer) { /*printf("pong_start_addr: %lx pong_stack_addr: %lx\n", START_ADDR (pong_start_addr), (L4_Word_t) pong_stack_addr);*/ L4_Set_Priority(ping_tid, 100); L4_Set_Priority(pong_tid, 99); send_startup_ipc (pong_tid, START_ADDR (pong_start_addr), (L4_Word_t) pong_stack_addr + sizeof (ping_stack) - 32); } break; } if (L4_UntypedWords (tag) != 2 || !L4_IpcSucceeded (tag)) { printf ("pingpong: malformed pagefault IPC from %p (tag=%p)\n", (void *) tid.raw, (void *) tag.raw); L4_KDB_Enter ("malformed pf"); break; } faddr = L4_MsgWord(&msg, 0); fip = L4_MsgWord (&msg, 1); L4_MsgClear(&msg); if (fault_test && (faddr == (uintptr_t) fault_area)) { if (count < num_iterations) { count++; } else { /* Tell master that we're finished */ L4_Set_MsgTag (L4_Niltag); L4_Send (master_tid); break; } } else { L4_MapItem_t map; L4_SpaceId_t space; L4_Word_t seg, offset, cache, rwx, size; int r; seg = get_seg(KBENCH_SPACE, faddr, &offset, &cache, &rwx); //if can not find mapping, must be page fault test, //just map any valid address, since fault address is dummy. if (seg == ~0UL) seg = get_seg(KBENCH_SPACE, (L4_Word_t) fault_area, &offset, &cache, &rwx); if (tid.raw == ping_th.raw) space = ping_space; else if (tid.raw == pong_th.raw) { if (pong_space.raw != L4_nilspace.raw) space = pong_space; else //pong_space is not created, only ping_space is used. space = ping_space; } else space = KBENCH_SPACE; size = L4_GetMinPageBits(); faddr &= ~((1ul << size)-1); offset &= ~((1ul << size)-1); L4_MapItem_Map(&map, seg, offset, faddr, size, cache, rwx); r = L4_ProcessMapItem(space, map); assert(r == 1); } L4_MsgLoad(&msg); tag = L4_ReplyWait (tid, &tid); } } }
int sched_yield(void) { L4_ThreadSwitch(L4_nilthread); return 0; }