1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/nkernsa/benchmark.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,465 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\nkernsa\benchmark.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <nktest/nkutils.h>
1.22 +
1.23 +typedef void (*PFV)(void);
1.24 +
1.25 +#ifdef __MARM__
1.26 +extern "C" TUint32 __get_static_data();
1.27 +extern "C" TUint32 __get_rwno_tid();
1.28 +extern "C" TUint32 __cpu_id();
1.29 +extern "C" TUint32 __trace_cpu_num();
1.30 +#ifdef __SMP__
1.31 +extern "C" TUint32 __get_local_timer_address();
1.32 +extern "C" TUint32 __get_local_timer_count();
1.33 +extern "C" TUint32 __set_local_timer_count();
1.34 +extern "C" TUint32 __swp_local_timer_count();
1.35 +
1.36 +void DoWatchdogTimerTest();
1.37 +#endif
1.38 +#endif
1.39 +
1.40 +TUint32 Threshold;
1.41 +TUint32 PsPerTick;
1.42 +
1.43 +TUint32 Counter;
1.44 +#ifdef __SMP__
1.45 +TSpinLock SL1(TSpinLock::EOrderGenericIrqLow0);
1.46 +TSpinLock SL2(TSpinLock::EOrderGenericPreLow0);
1.47 +#endif
1.48 +
1.49 +NThread* PingPongThread;
1.50 +NFastSemaphore PingPongExitSem;
1.51 +void PingPong(TAny* aPtr)
1.52 + {
1.53 + NThread* t = (NThread*)aPtr;
1.54 + FOREVER
1.55 + {
1.56 + NKern::WaitForAnyRequest();
1.57 + if (t)
1.58 + NKern::ThreadRequestSignal(t);
1.59 + }
1.60 + }
1.61 +
1.62 +void SetupPingPongThread(TInt aPri, TInt aCpu, TBool aReply=TRUE)
1.63 + {
1.64 + NThread* t = NKern::CurrentThread();
1.65 + NKern::FSSetOwner(&PingPongExitSem, t);
1.66 + PingPongThread = CreateThreadSignalOnExit("PingPong", &PingPong, aPri, aReply?t:0, 0, -1, &PingPongExitSem, aCpu);
1.67 + }
1.68 +
1.69 +void DestroyPingPongThread()
1.70 + {
1.71 + NKern::ThreadKill(PingPongThread);
1.72 + NKern::FSWait(&PingPongExitSem);
1.73 + }
1.74 +
1.75 +extern "C" void dummy()
1.76 + {
1.77 + }
1.78 +
1.79 +extern "C" void sleep1()
1.80 + {
1.81 + NKern::Sleep(1);
1.82 + }
1.83 +
1.84 +extern "C" void do_atomic_add_rlx32()
1.85 + {
1.86 + __e32_atomic_add_rlx32(&Counter, 1);
1.87 + }
1.88 +
1.89 +extern "C" void do_atomic_add_rel32()
1.90 + {
1.91 + __e32_atomic_add_rel32(&Counter, 1);
1.92 + }
1.93 +
1.94 +extern "C" void do_atomic_add_acq32()
1.95 + {
1.96 + __e32_atomic_add_acq32(&Counter, 1);
1.97 + }
1.98 +
1.99 +extern "C" void do_atomic_add_ord32()
1.100 + {
1.101 + __e32_atomic_add_ord32(&Counter, 1);
1.102 + }
1.103 +
1.104 +extern "C" void dis_ena_int()
1.105 + {
1.106 + TInt irq = NKern::DisableAllInterrupts();
1.107 + NKern::RestoreInterrupts(irq);
1.108 + }
1.109 +
1.110 +extern "C" void dis_ena_preempt()
1.111 + {
1.112 + NKern::Lock();
1.113 + NKern::Unlock();
1.114 + }
1.115 +
1.116 +#ifdef __SMP__
1.117 +extern "C" void sl1_lock_unlock_irq()
1.118 + {
1.119 + SL1.LockIrq();
1.120 + SL1.UnlockIrq();
1.121 + }
1.122 +
1.123 +extern "C" void sl1_lock_unlock_irq_save()
1.124 + {
1.125 + TInt irq = SL1.LockIrqSave();
1.126 + SL1.UnlockIrqRestore(irq);
1.127 + }
1.128 +
1.129 +extern "C" void sl1_lock_unlock_only()
1.130 + {
1.131 + TInt irq = NKern::DisableAllInterrupts();
1.132 + SL1.LockOnly();
1.133 + SL1.UnlockOnly();
1.134 + NKern::RestoreInterrupts(irq);
1.135 + }
1.136 +
1.137 +extern "C" void sl2_lock_unlock_only()
1.138 + {
1.139 + NKern::Lock();
1.140 + SL2.LockOnly();
1.141 + SL2.UnlockOnly();
1.142 + NKern::Unlock();
1.143 + }
1.144 +#endif
1.145 +
1.146 +extern "C" void lock_unlock_system()
1.147 + {
1.148 + NKern::LockSystem();
1.149 + NKern::UnlockSystem();
1.150 + }
1.151 +
1.152 +extern "C" void enter_leave_cs()
1.153 + {
1.154 + NKern::ThreadEnterCS();
1.155 + NKern::ThreadLeaveCS();
1.156 + }
1.157 +
1.158 +extern "C" void resched_to_same()
1.159 + {
1.160 + NKern::Lock();
1.161 + RescheduleNeeded();
1.162 + NKern::Unlock();
1.163 + }
1.164 +
1.165 +#ifdef __SMP__
1.166 +extern "C" void get_timestamp()
1.167 + {
1.168 + NKern::Timestamp();
1.169 + }
1.170 +#endif
1.171 +
1.172 +NFastSemaphore Sem;
1.173 +
1.174 +extern "C" void sem_signal()
1.175 + {
1.176 + NKern::FSSignal(&Sem);
1.177 + }
1.178 +
1.179 +extern "C" void sem_signal_wait()
1.180 + {
1.181 + NKern::FSSignal(&Sem);
1.182 + NKern::FSWait(&Sem);
1.183 + }
1.184 +
1.185 +TDfcQue* DfcQ;
1.186 +TDfc* Dfc;
1.187 +
1.188 +void BenchmarkDfcFn(TAny* aPtr)
1.189 + {
1.190 + NThread* t = (NThread*)aPtr;
1.191 + if (t)
1.192 + NKern::ThreadRequestSignal(t);
1.193 + }
1.194 +
1.195 +void BenchmarkIDfcFn(TAny* aPtr)
1.196 + {
1.197 + NThread* t = (NThread*)aPtr;
1.198 + if (t)
1.199 + t->RequestSignal();
1.200 + }
1.201 +
1.202 +void SetupBenchmarkDfcQ(TInt aPri, TInt aCpu, TBool aReply=TRUE)
1.203 + {
1.204 + NThread* t = NKern::CurrentThread();
1.205 + if (aPri>=0)
1.206 + {
1.207 + DfcQ = CreateDfcQ("Benchmark", aPri, (TUint32)aCpu);
1.208 + Dfc = new TDfc(&BenchmarkDfcFn, aReply?t:0, DfcQ, 1);
1.209 + }
1.210 + else
1.211 + Dfc = new TDfc(&BenchmarkIDfcFn, aReply?t:0);
1.212 + }
1.213 +
1.214 +void DestroyBenchmarkDfcQ()
1.215 + {
1.216 + Dfc->Cancel();
1.217 + delete Dfc;
1.218 + if (DfcQ)
1.219 + DestroyDfcQ(DfcQ);
1.220 + Dfc = 0;
1.221 + DfcQ = 0;
1.222 + }
1.223 +
1.224 +
1.225 +
1.226 +
1.227 +TUint32 Ps(TUint64 x)
1.228 + {
1.229 + x*=PsPerTick;
1.230 + if (x>>32)
1.231 + return KMaxTUint32;
1.232 + return (TUint32)x;
1.233 + }
1.234 +
1.235 +TUint64 Iterate(PFV f, TUint32 aCount)
1.236 + {
1.237 + TUint64 initial = fast_counter();
1.238 + do {
1.239 + (*f)();
1.240 + --aCount;
1.241 + } while(aCount);
1.242 + TUint64 final = fast_counter();
1.243 + return final - initial;
1.244 + }
1.245 +
1.246 +TUint32 Measure(PFV f)
1.247 + {
1.248 + TUint32 n = 1;
1.249 + TUint64 time;
1.250 + do {
1.251 + n<<=1;
1.252 + time = Iterate(f, n);
1.253 + } while(time < Threshold);
1.254 + time *= PsPerTick;
1.255 + time /= n;
1.256 + if (time >> 32)
1.257 + return KMaxTUint32;
1.258 + return (TUint32)time;
1.259 + }
1.260 +
1.261 +void ping_pong_threads()
1.262 + {
1.263 + NKern::ThreadRequestSignal(PingPongThread);
1.264 + NKern::WaitForAnyRequest();
1.265 + }
1.266 +
1.267 +void ping_pong_threads_nr()
1.268 + {
1.269 + NKern::ThreadRequestSignal(PingPongThread);
1.270 + }
1.271 +
1.272 +TUint32 DoPingPongTest(TInt aPri, TInt aCpu, TBool aReply=TRUE)
1.273 + {
1.274 + SetupPingPongThread(aPri, aCpu, aReply);
1.275 + TUint32 x;
1.276 + if (aReply)
1.277 + x = Measure(&ping_pong_threads);
1.278 + else
1.279 + x = Measure(&ping_pong_threads_nr);
1.280 + DestroyPingPongThread();
1.281 + TEST_PRINT4("PingPong: Pri %2d Cpu %2d Reply %1d -> %ups", aPri, aCpu, aReply, x);
1.282 + return x;
1.283 + }
1.284 +
1.285 +void do_dfc_test()
1.286 + {
1.287 + Dfc->Enque();
1.288 + NKern::WaitForAnyRequest();
1.289 + }
1.290 +
1.291 +void do_dfc_test_nr()
1.292 + {
1.293 + Dfc->Enque();
1.294 + }
1.295 +
1.296 +void do_idfc_test()
1.297 + {
1.298 + NKern::Lock();
1.299 + Dfc->Add();
1.300 + NKern::Unlock();
1.301 + NKern::WaitForAnyRequest();
1.302 + }
1.303 +
1.304 +void do_idfc_test_nr()
1.305 + {
1.306 + NKern::Lock();
1.307 + Dfc->Add();
1.308 + NKern::Unlock();
1.309 + }
1.310 +
1.311 +TUint32 DoDfcTest(TInt aPri, TInt aCpu, TBool aReply=TRUE)
1.312 + {
1.313 + SetupBenchmarkDfcQ(aPri, aCpu, aReply);
1.314 + TUint32 x;
1.315 + PFV f = aReply ? (aPri<0 ? &do_idfc_test : &do_dfc_test) : (aPri<0 ? &do_idfc_test_nr : &do_dfc_test_nr);
1.316 + x = Measure(f);
1.317 + DestroyBenchmarkDfcQ();
1.318 + TEST_PRINT4("Dfc: Pri %2d Cpu %2d Reply %1d -> %ups", aPri, aCpu, aReply, x);
1.319 + return x;
1.320 + }
1.321 +
1.322 +void BenchmarkTests()
1.323 + {
1.324 + TUint64 fcf = fast_counter_freq();
1.325 + Threshold = (TUint32)fcf;
1.326 + if (Threshold > 10000000u)
1.327 + Threshold /= 10u;
1.328 + else if (Threshold > 1000000u)
1.329 + Threshold = 1000000u;
1.330 + TUint64 ps_per_tick = UI64LIT(1000000000000);
1.331 + ps_per_tick /= fcf;
1.332 + PsPerTick = (TUint32)ps_per_tick;
1.333 + TEST_PRINT1("Threshold %u", Threshold);
1.334 + TEST_PRINT1("PsPerTick %u", PsPerTick);
1.335 +
1.336 + TUint32 dummy_time = Measure(&dummy);
1.337 + TEST_PRINT1("Dummy %ups", dummy_time);
1.338 +
1.339 + TUint32 dmb_time = Measure(&__e32_memory_barrier);
1.340 + TEST_PRINT1("DMB loop %ups", dmb_time);
1.341 + dmb_time -= dummy_time;
1.342 + TEST_PRINT1("DMB %ups", dmb_time);
1.343 +
1.344 + TUint32 dsb_time = Measure(&__e32_io_completion_barrier);
1.345 + TEST_PRINT1("DSB loop %ups", dsb_time);
1.346 + dsb_time -= dummy_time;
1.347 + TEST_PRINT1("DSB %ups", dsb_time);
1.348 +
1.349 +#ifdef __SMP__
1.350 + TUint32 timestamp_time = Measure(&get_timestamp) - dummy_time;
1.351 + TEST_PRINT1("NKern::Timestamp() %ups", timestamp_time);
1.352 +#endif
1.353 +
1.354 + TUint32 ps;
1.355 + ps = Measure(&sleep1);
1.356 + TEST_PRINT1("Sleep(1) %ups", ps-dummy_time);
1.357 + ps = Measure(&do_atomic_add_rlx32);
1.358 + TEST_PRINT1("atomic_add_rlx32 %ups", ps-dummy_time);
1.359 + ps = Measure(&do_atomic_add_acq32);
1.360 + TEST_PRINT1("atomic_add_acq32 %ups", ps-dummy_time);
1.361 + ps = Measure(&do_atomic_add_rel32);
1.362 + TEST_PRINT1("atomic_add_rel32 %ups", ps-dummy_time);
1.363 + ps = Measure(&do_atomic_add_ord32);
1.364 + TEST_PRINT1("atomic_add_ord32 %ups", ps-dummy_time);
1.365 +
1.366 + TUint32 dis_ena_int_time = Measure(&dis_ena_int) - dummy_time;
1.367 + TEST_PRINT1("dis_ena_int %ups", dis_ena_int_time);
1.368 +
1.369 + TUint32 dis_ena_preempt_time = Measure(&dis_ena_preempt) - dummy_time;
1.370 + TEST_PRINT1("dis_ena_preempt %ups", dis_ena_preempt_time);
1.371 +
1.372 +#ifdef __SMP__
1.373 + TUint32 sl1_irq_time = Measure(&sl1_lock_unlock_irq) - dummy_time;
1.374 + TEST_PRINT1("sl1_irq_time %ups", sl1_irq_time);
1.375 +
1.376 + TUint32 sl1_irqsave_time = Measure(&sl1_lock_unlock_irq_save) - dummy_time;
1.377 + TEST_PRINT1("sl1_irqsave_time %ups", sl1_irqsave_time);
1.378 +
1.379 + TUint32 sl1_only_time = Measure(&sl1_lock_unlock_only) - dis_ena_int_time - dummy_time;
1.380 + TEST_PRINT1("sl1_only_time %ups", sl1_only_time);
1.381 +
1.382 + TUint32 sl2_only_time = Measure(&sl2_lock_unlock_only) - dis_ena_preempt_time - dummy_time;
1.383 + TEST_PRINT1("sl2_only_time %ups", sl2_only_time);
1.384 +#endif
1.385 +
1.386 + TUint32 lock_unlock_system_time = Measure(&lock_unlock_system) - dummy_time;
1.387 + TEST_PRINT1("lock_unlock_system_time %ups", lock_unlock_system_time);
1.388 +
1.389 + TUint32 enter_leave_cs_time = Measure(&enter_leave_cs) - dummy_time;
1.390 + TEST_PRINT1("enter_leave_cs_time %ups", enter_leave_cs_time);
1.391 +
1.392 + TUint32 resched_to_same_time = Measure(&resched_to_same) - dummy_time;
1.393 + TEST_PRINT1("resched_to_same_time %ups", resched_to_same_time);
1.394 +
1.395 +#ifdef __MARM__
1.396 + TUint32 get_static_data_time = Measure((PFV)&__get_static_data) - dummy_time;
1.397 + TEST_PRINT1("get_static_data_time %ups", get_static_data_time);
1.398 +
1.399 + TUint32 get_sp_time = Measure((PFV)&__stack_pointer) - dummy_time;
1.400 + TEST_PRINT1("get_sp_time %ups", get_sp_time);
1.401 +
1.402 + TUint32 get_cpsr_time = Measure((PFV)&__cpu_status_reg) - dummy_time;
1.403 + TEST_PRINT1("get_cpsr_time %ups", get_cpsr_time);
1.404 +
1.405 +#ifdef __SMP__
1.406 + TUint32 get_cpu_id_time = Measure((PFV)&__cpu_id) - dummy_time;
1.407 + TEST_PRINT1("get_cpu_id_time %ups", get_cpu_id_time);
1.408 +
1.409 + TUint32 trace_cpu_num_time = Measure((PFV)&__trace_cpu_num) - dummy_time;
1.410 + TEST_PRINT1("trace_cpu_num_time %ups", trace_cpu_num_time);
1.411 +
1.412 + TUint32 get_rwno_tid_time = Measure((PFV)&__get_rwno_tid) - dummy_time;
1.413 + TEST_PRINT1("get_rwno_tid_time %ups", get_rwno_tid_time);
1.414 +
1.415 + TUint32 get_lta_time = Measure((PFV)&__get_local_timer_address) - dummy_time;
1.416 + TEST_PRINT1("get_local_timer_address %ups", get_lta_time);
1.417 +
1.418 + TUint32 get_ltc_time = Measure((PFV)&__get_local_timer_count) - dummy_time;
1.419 + TEST_PRINT1("get_local_timer_count %ups", get_ltc_time);
1.420 +
1.421 + TUint32 set_ltc_time = Measure((PFV)&__set_local_timer_count) - dummy_time;
1.422 + TEST_PRINT1("set_local_timer_count %ups", set_ltc_time);
1.423 +
1.424 + TUint32 swp_ltc_time = Measure((PFV)&__swp_local_timer_count) - dummy_time;
1.425 + TEST_PRINT1("swp_local_timer_count %ups", swp_ltc_time);
1.426 +#endif
1.427 +
1.428 + TUint32 get_current_thread_time = Measure((PFV)&NKern::CurrentThread) - dummy_time;
1.429 + TEST_PRINT1("get_current_thread_time %ups", get_current_thread_time);
1.430 +
1.431 +#ifdef __SMP__
1.432 + TUint32 get_current_threadL_time = Measure((PFV)&NCurrentThreadL) - dummy_time;
1.433 + TEST_PRINT1("get_current_threadL_time %ups", get_current_threadL_time);
1.434 +#endif
1.435 +#endif
1.436 +
1.437 + NThread* t = NKern::CurrentThread();
1.438 + NKern::FSSetOwner(&Sem, t);
1.439 +
1.440 + TUint32 sem_signal_time = Measure(&sem_signal) - dummy_time;
1.441 + TEST_PRINT1("sem_signal_time %ups", sem_signal_time);
1.442 +
1.443 + new (&Sem) NFastSemaphore(t);
1.444 +
1.445 + TUint32 sem_signal_wait_time = Measure(&sem_signal_wait) - dummy_time;
1.446 + TEST_PRINT1("sem_signal_wait_time %ups", sem_signal_wait_time);
1.447 +
1.448 + DoPingPongTest(31, 0);
1.449 + DoPingPongTest(11, 0);
1.450 + DoPingPongTest(31, 1);
1.451 + DoPingPongTest(11, 1);
1.452 + DoPingPongTest(31, -1);
1.453 + DoPingPongTest(11, -1);
1.454 + DoPingPongTest(31, 0, FALSE);
1.455 +
1.456 + DoDfcTest(31, 0);
1.457 + DoDfcTest(11, 0);
1.458 + DoDfcTest(31, 1);
1.459 + DoDfcTest(11, 1);
1.460 + DoDfcTest(31, -1);
1.461 + DoDfcTest(11, -1);
1.462 + DoDfcTest(31, 0, FALSE);
1.463 + DoDfcTest(-1, 0, TRUE);
1.464 + DoDfcTest(-1, 0, FALSE);
1.465 +#if defined(__MARM__) && defined(__SMP__)
1.466 + DoWatchdogTimerTest();
1.467 +#endif
1.468 + }