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