sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\nkernsa\benchmark.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: sl@0: typedef void (*PFV)(void); sl@0: sl@0: #ifdef __MARM__ sl@0: extern "C" TUint32 __get_static_data(); sl@0: extern "C" TUint32 __get_rwno_tid(); sl@0: extern "C" TUint32 __cpu_id(); sl@0: extern "C" TUint32 __trace_cpu_num(); sl@0: #ifdef __SMP__ sl@0: extern "C" TUint32 __get_local_timer_address(); sl@0: extern "C" TUint32 __get_local_timer_count(); sl@0: extern "C" TUint32 __set_local_timer_count(); sl@0: extern "C" TUint32 __swp_local_timer_count(); sl@0: sl@0: void DoWatchdogTimerTest(); sl@0: #endif sl@0: #endif sl@0: sl@0: TUint32 Threshold; sl@0: TUint32 PsPerTick; sl@0: sl@0: TUint32 Counter; sl@0: #ifdef __SMP__ sl@0: TSpinLock SL1(TSpinLock::EOrderGenericIrqLow0); sl@0: TSpinLock SL2(TSpinLock::EOrderGenericPreLow0); sl@0: #endif sl@0: sl@0: NThread* PingPongThread; sl@0: NFastSemaphore PingPongExitSem; sl@0: void PingPong(TAny* aPtr) sl@0: { sl@0: NThread* t = (NThread*)aPtr; sl@0: FOREVER sl@0: { sl@0: NKern::WaitForAnyRequest(); sl@0: if (t) sl@0: NKern::ThreadRequestSignal(t); sl@0: } sl@0: } sl@0: sl@0: void SetupPingPongThread(TInt aPri, TInt aCpu, TBool aReply=TRUE) sl@0: { sl@0: NThread* t = NKern::CurrentThread(); sl@0: NKern::FSSetOwner(&PingPongExitSem, t); sl@0: PingPongThread = CreateThreadSignalOnExit("PingPong", &PingPong, aPri, aReply?t:0, 0, -1, &PingPongExitSem, aCpu); sl@0: } sl@0: sl@0: void DestroyPingPongThread() sl@0: { sl@0: NKern::ThreadKill(PingPongThread); sl@0: NKern::FSWait(&PingPongExitSem); sl@0: } sl@0: sl@0: extern "C" void dummy() sl@0: { sl@0: } sl@0: sl@0: extern "C" void sleep1() sl@0: { sl@0: NKern::Sleep(1); sl@0: } sl@0: sl@0: extern "C" void do_atomic_add_rlx32() sl@0: { sl@0: __e32_atomic_add_rlx32(&Counter, 1); sl@0: } sl@0: sl@0: extern "C" void do_atomic_add_rel32() sl@0: { sl@0: __e32_atomic_add_rel32(&Counter, 1); sl@0: } sl@0: sl@0: extern "C" void do_atomic_add_acq32() sl@0: { sl@0: __e32_atomic_add_acq32(&Counter, 1); sl@0: } sl@0: sl@0: extern "C" void do_atomic_add_ord32() sl@0: { sl@0: __e32_atomic_add_ord32(&Counter, 1); sl@0: } sl@0: sl@0: extern "C" void dis_ena_int() sl@0: { sl@0: TInt irq = NKern::DisableAllInterrupts(); sl@0: NKern::RestoreInterrupts(irq); sl@0: } sl@0: sl@0: extern "C" void dis_ena_preempt() sl@0: { sl@0: NKern::Lock(); sl@0: NKern::Unlock(); sl@0: } sl@0: sl@0: #ifdef __SMP__ sl@0: extern "C" void sl1_lock_unlock_irq() sl@0: { sl@0: SL1.LockIrq(); sl@0: SL1.UnlockIrq(); sl@0: } sl@0: sl@0: extern "C" void sl1_lock_unlock_irq_save() sl@0: { sl@0: TInt irq = SL1.LockIrqSave(); sl@0: SL1.UnlockIrqRestore(irq); sl@0: } sl@0: sl@0: extern "C" void sl1_lock_unlock_only() sl@0: { sl@0: TInt irq = NKern::DisableAllInterrupts(); sl@0: SL1.LockOnly(); sl@0: SL1.UnlockOnly(); sl@0: NKern::RestoreInterrupts(irq); sl@0: } sl@0: sl@0: extern "C" void sl2_lock_unlock_only() sl@0: { sl@0: NKern::Lock(); sl@0: SL2.LockOnly(); sl@0: SL2.UnlockOnly(); sl@0: NKern::Unlock(); sl@0: } sl@0: #endif sl@0: sl@0: extern "C" void lock_unlock_system() sl@0: { sl@0: NKern::LockSystem(); sl@0: NKern::UnlockSystem(); sl@0: } sl@0: sl@0: extern "C" void enter_leave_cs() sl@0: { sl@0: NKern::ThreadEnterCS(); sl@0: NKern::ThreadLeaveCS(); sl@0: } sl@0: sl@0: extern "C" void resched_to_same() sl@0: { sl@0: NKern::Lock(); sl@0: RescheduleNeeded(); sl@0: NKern::Unlock(); sl@0: } sl@0: sl@0: #ifdef __SMP__ sl@0: extern "C" void get_timestamp() sl@0: { sl@0: NKern::Timestamp(); sl@0: } sl@0: #endif sl@0: sl@0: NFastSemaphore Sem; sl@0: sl@0: extern "C" void sem_signal() sl@0: { sl@0: NKern::FSSignal(&Sem); sl@0: } sl@0: sl@0: extern "C" void sem_signal_wait() sl@0: { sl@0: NKern::FSSignal(&Sem); sl@0: NKern::FSWait(&Sem); sl@0: } sl@0: sl@0: TDfcQue* DfcQ; sl@0: TDfc* Dfc; sl@0: sl@0: void BenchmarkDfcFn(TAny* aPtr) sl@0: { sl@0: NThread* t = (NThread*)aPtr; sl@0: if (t) sl@0: NKern::ThreadRequestSignal(t); sl@0: } sl@0: sl@0: void BenchmarkIDfcFn(TAny* aPtr) sl@0: { sl@0: NThread* t = (NThread*)aPtr; sl@0: if (t) sl@0: t->RequestSignal(); sl@0: } sl@0: sl@0: void SetupBenchmarkDfcQ(TInt aPri, TInt aCpu, TBool aReply=TRUE) sl@0: { sl@0: NThread* t = NKern::CurrentThread(); sl@0: if (aPri>=0) sl@0: { sl@0: DfcQ = CreateDfcQ("Benchmark", aPri, (TUint32)aCpu); sl@0: Dfc = new TDfc(&BenchmarkDfcFn, aReply?t:0, DfcQ, 1); sl@0: } sl@0: else sl@0: Dfc = new TDfc(&BenchmarkIDfcFn, aReply?t:0); sl@0: } sl@0: sl@0: void DestroyBenchmarkDfcQ() sl@0: { sl@0: Dfc->Cancel(); sl@0: delete Dfc; sl@0: if (DfcQ) sl@0: DestroyDfcQ(DfcQ); sl@0: Dfc = 0; sl@0: DfcQ = 0; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: TUint32 Ps(TUint64 x) sl@0: { sl@0: x*=PsPerTick; sl@0: if (x>>32) sl@0: return KMaxTUint32; sl@0: return (TUint32)x; sl@0: } sl@0: sl@0: TUint64 Iterate(PFV f, TUint32 aCount) sl@0: { sl@0: TUint64 initial = fast_counter(); sl@0: do { sl@0: (*f)(); sl@0: --aCount; sl@0: } while(aCount); sl@0: TUint64 final = fast_counter(); sl@0: return final - initial; sl@0: } sl@0: sl@0: TUint32 Measure(PFV f) sl@0: { sl@0: TUint32 n = 1; sl@0: TUint64 time; sl@0: do { sl@0: n<<=1; sl@0: time = Iterate(f, n); sl@0: } while(time < Threshold); sl@0: time *= PsPerTick; sl@0: time /= n; sl@0: if (time >> 32) sl@0: return KMaxTUint32; sl@0: return (TUint32)time; sl@0: } sl@0: sl@0: void ping_pong_threads() sl@0: { sl@0: NKern::ThreadRequestSignal(PingPongThread); sl@0: NKern::WaitForAnyRequest(); sl@0: } sl@0: sl@0: void ping_pong_threads_nr() sl@0: { sl@0: NKern::ThreadRequestSignal(PingPongThread); sl@0: } sl@0: sl@0: TUint32 DoPingPongTest(TInt aPri, TInt aCpu, TBool aReply=TRUE) sl@0: { sl@0: SetupPingPongThread(aPri, aCpu, aReply); sl@0: TUint32 x; sl@0: if (aReply) sl@0: x = Measure(&ping_pong_threads); sl@0: else sl@0: x = Measure(&ping_pong_threads_nr); sl@0: DestroyPingPongThread(); sl@0: TEST_PRINT4("PingPong: Pri %2d Cpu %2d Reply %1d -> %ups", aPri, aCpu, aReply, x); sl@0: return x; sl@0: } sl@0: sl@0: void do_dfc_test() sl@0: { sl@0: Dfc->Enque(); sl@0: NKern::WaitForAnyRequest(); sl@0: } sl@0: sl@0: void do_dfc_test_nr() sl@0: { sl@0: Dfc->Enque(); sl@0: } sl@0: sl@0: void do_idfc_test() sl@0: { sl@0: NKern::Lock(); sl@0: Dfc->Add(); sl@0: NKern::Unlock(); sl@0: NKern::WaitForAnyRequest(); sl@0: } sl@0: sl@0: void do_idfc_test_nr() sl@0: { sl@0: NKern::Lock(); sl@0: Dfc->Add(); sl@0: NKern::Unlock(); sl@0: } sl@0: sl@0: TUint32 DoDfcTest(TInt aPri, TInt aCpu, TBool aReply=TRUE) sl@0: { sl@0: SetupBenchmarkDfcQ(aPri, aCpu, aReply); sl@0: TUint32 x; sl@0: PFV f = aReply ? (aPri<0 ? &do_idfc_test : &do_dfc_test) : (aPri<0 ? &do_idfc_test_nr : &do_dfc_test_nr); sl@0: x = Measure(f); sl@0: DestroyBenchmarkDfcQ(); sl@0: TEST_PRINT4("Dfc: Pri %2d Cpu %2d Reply %1d -> %ups", aPri, aCpu, aReply, x); sl@0: return x; sl@0: } sl@0: sl@0: void BenchmarkTests() sl@0: { sl@0: TUint64 fcf = fast_counter_freq(); sl@0: Threshold = (TUint32)fcf; sl@0: if (Threshold > 10000000u) sl@0: Threshold /= 10u; sl@0: else if (Threshold > 1000000u) sl@0: Threshold = 1000000u; sl@0: TUint64 ps_per_tick = UI64LIT(1000000000000); sl@0: ps_per_tick /= fcf; sl@0: PsPerTick = (TUint32)ps_per_tick; sl@0: TEST_PRINT1("Threshold %u", Threshold); sl@0: TEST_PRINT1("PsPerTick %u", PsPerTick); sl@0: sl@0: TUint32 dummy_time = Measure(&dummy); sl@0: TEST_PRINT1("Dummy %ups", dummy_time); sl@0: sl@0: TUint32 dmb_time = Measure(&__e32_memory_barrier); sl@0: TEST_PRINT1("DMB loop %ups", dmb_time); sl@0: dmb_time -= dummy_time; sl@0: TEST_PRINT1("DMB %ups", dmb_time); sl@0: sl@0: TUint32 dsb_time = Measure(&__e32_io_completion_barrier); sl@0: TEST_PRINT1("DSB loop %ups", dsb_time); sl@0: dsb_time -= dummy_time; sl@0: TEST_PRINT1("DSB %ups", dsb_time); sl@0: sl@0: #ifdef __SMP__ sl@0: TUint32 timestamp_time = Measure(&get_timestamp) - dummy_time; sl@0: TEST_PRINT1("NKern::Timestamp() %ups", timestamp_time); sl@0: #endif sl@0: sl@0: TUint32 ps; sl@0: ps = Measure(&sleep1); sl@0: TEST_PRINT1("Sleep(1) %ups", ps-dummy_time); sl@0: ps = Measure(&do_atomic_add_rlx32); sl@0: TEST_PRINT1("atomic_add_rlx32 %ups", ps-dummy_time); sl@0: ps = Measure(&do_atomic_add_acq32); sl@0: TEST_PRINT1("atomic_add_acq32 %ups", ps-dummy_time); sl@0: ps = Measure(&do_atomic_add_rel32); sl@0: TEST_PRINT1("atomic_add_rel32 %ups", ps-dummy_time); sl@0: ps = Measure(&do_atomic_add_ord32); sl@0: TEST_PRINT1("atomic_add_ord32 %ups", ps-dummy_time); sl@0: sl@0: TUint32 dis_ena_int_time = Measure(&dis_ena_int) - dummy_time; sl@0: TEST_PRINT1("dis_ena_int %ups", dis_ena_int_time); sl@0: sl@0: TUint32 dis_ena_preempt_time = Measure(&dis_ena_preempt) - dummy_time; sl@0: TEST_PRINT1("dis_ena_preempt %ups", dis_ena_preempt_time); sl@0: sl@0: #ifdef __SMP__ sl@0: TUint32 sl1_irq_time = Measure(&sl1_lock_unlock_irq) - dummy_time; sl@0: TEST_PRINT1("sl1_irq_time %ups", sl1_irq_time); sl@0: sl@0: TUint32 sl1_irqsave_time = Measure(&sl1_lock_unlock_irq_save) - dummy_time; sl@0: TEST_PRINT1("sl1_irqsave_time %ups", sl1_irqsave_time); sl@0: sl@0: TUint32 sl1_only_time = Measure(&sl1_lock_unlock_only) - dis_ena_int_time - dummy_time; sl@0: TEST_PRINT1("sl1_only_time %ups", sl1_only_time); sl@0: sl@0: TUint32 sl2_only_time = Measure(&sl2_lock_unlock_only) - dis_ena_preempt_time - dummy_time; sl@0: TEST_PRINT1("sl2_only_time %ups", sl2_only_time); sl@0: #endif sl@0: sl@0: TUint32 lock_unlock_system_time = Measure(&lock_unlock_system) - dummy_time; sl@0: TEST_PRINT1("lock_unlock_system_time %ups", lock_unlock_system_time); sl@0: sl@0: TUint32 enter_leave_cs_time = Measure(&enter_leave_cs) - dummy_time; sl@0: TEST_PRINT1("enter_leave_cs_time %ups", enter_leave_cs_time); sl@0: sl@0: TUint32 resched_to_same_time = Measure(&resched_to_same) - dummy_time; sl@0: TEST_PRINT1("resched_to_same_time %ups", resched_to_same_time); sl@0: sl@0: #ifdef __MARM__ sl@0: TUint32 get_static_data_time = Measure((PFV)&__get_static_data) - dummy_time; sl@0: TEST_PRINT1("get_static_data_time %ups", get_static_data_time); sl@0: sl@0: TUint32 get_sp_time = Measure((PFV)&__stack_pointer) - dummy_time; sl@0: TEST_PRINT1("get_sp_time %ups", get_sp_time); sl@0: sl@0: TUint32 get_cpsr_time = Measure((PFV)&__cpu_status_reg) - dummy_time; sl@0: TEST_PRINT1("get_cpsr_time %ups", get_cpsr_time); sl@0: sl@0: #ifdef __SMP__ sl@0: TUint32 get_cpu_id_time = Measure((PFV)&__cpu_id) - dummy_time; sl@0: TEST_PRINT1("get_cpu_id_time %ups", get_cpu_id_time); sl@0: sl@0: TUint32 trace_cpu_num_time = Measure((PFV)&__trace_cpu_num) - dummy_time; sl@0: TEST_PRINT1("trace_cpu_num_time %ups", trace_cpu_num_time); sl@0: sl@0: TUint32 get_rwno_tid_time = Measure((PFV)&__get_rwno_tid) - dummy_time; sl@0: TEST_PRINT1("get_rwno_tid_time %ups", get_rwno_tid_time); sl@0: sl@0: TUint32 get_lta_time = Measure((PFV)&__get_local_timer_address) - dummy_time; sl@0: TEST_PRINT1("get_local_timer_address %ups", get_lta_time); sl@0: sl@0: TUint32 get_ltc_time = Measure((PFV)&__get_local_timer_count) - dummy_time; sl@0: TEST_PRINT1("get_local_timer_count %ups", get_ltc_time); sl@0: sl@0: TUint32 set_ltc_time = Measure((PFV)&__set_local_timer_count) - dummy_time; sl@0: TEST_PRINT1("set_local_timer_count %ups", set_ltc_time); sl@0: sl@0: TUint32 swp_ltc_time = Measure((PFV)&__swp_local_timer_count) - dummy_time; sl@0: TEST_PRINT1("swp_local_timer_count %ups", swp_ltc_time); sl@0: #endif sl@0: sl@0: TUint32 get_current_thread_time = Measure((PFV)&NKern::CurrentThread) - dummy_time; sl@0: TEST_PRINT1("get_current_thread_time %ups", get_current_thread_time); sl@0: sl@0: #ifdef __SMP__ sl@0: TUint32 get_current_threadL_time = Measure((PFV)&NCurrentThreadL) - dummy_time; sl@0: TEST_PRINT1("get_current_threadL_time %ups", get_current_threadL_time); sl@0: #endif sl@0: #endif sl@0: sl@0: NThread* t = NKern::CurrentThread(); sl@0: NKern::FSSetOwner(&Sem, t); sl@0: sl@0: TUint32 sem_signal_time = Measure(&sem_signal) - dummy_time; sl@0: TEST_PRINT1("sem_signal_time %ups", sem_signal_time); sl@0: sl@0: new (&Sem) NFastSemaphore(t); sl@0: sl@0: TUint32 sem_signal_wait_time = Measure(&sem_signal_wait) - dummy_time; sl@0: TEST_PRINT1("sem_signal_wait_time %ups", sem_signal_wait_time); sl@0: sl@0: DoPingPongTest(31, 0); sl@0: DoPingPongTest(11, 0); sl@0: DoPingPongTest(31, 1); sl@0: DoPingPongTest(11, 1); sl@0: DoPingPongTest(31, -1); sl@0: DoPingPongTest(11, -1); sl@0: DoPingPongTest(31, 0, FALSE); sl@0: sl@0: DoDfcTest(31, 0); sl@0: DoDfcTest(11, 0); sl@0: DoDfcTest(31, 1); sl@0: DoDfcTest(11, 1); sl@0: DoDfcTest(31, -1); sl@0: DoDfcTest(11, -1); sl@0: DoDfcTest(31, 0, FALSE); sl@0: DoDfcTest(-1, 0, TRUE); sl@0: DoDfcTest(-1, 0, FALSE); sl@0: #if defined(__MARM__) && defined(__SMP__) sl@0: DoWatchdogTimerTest(); sl@0: #endif sl@0: }