1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/thread/t_smpsafe.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,263 @@
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\thread\t_smpsafe.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#define __E32TEST_EXTENSION__
1.22 +#include <e32test.h>
1.23 +#include <e32ldr.h>
1.24 +#include <e32svr.h>
1.25 +#include "u32std.h"
1.26 +#include <u32hal.h>
1.27 +#include <d_ldrtst.h>
1.28 +
1.29 +/////////////////////////////////////////////////////////////////////////////
1.30 +//
1.31 +//! @SYMTestCaseID KBASE-T_SMPSAFE-2700
1.32 +//! @SYMTestType UT
1.33 +//! @SYMPREQ PREQ2094
1.34 +//! @SYMTestCaseDesc SMP compatibility mode test
1.35 +//! @SYMTestActions
1.36 +//! @SYMTestExpectedResults All tests should pass.
1.37 +//! @SYMTestPriority Medium
1.38 +//! @SYMTestStatus Implemented
1.39 +//
1.40 +// The test attempts to prove that the SMPSAFE compatibility mode mechanism
1.41 +// works and correctly forces processes which contain any unsafe code to run
1.42 +// as if they were on a single-cpu machine. This is done by loading and
1.43 +// unloading various combinations of DLLs into the test process itself, and
1.44 +// by spawning and exiting various EXEs.
1.45 +//
1.46 +// Two things are checked for each combination:
1.47 +//
1.48 +// 1) D_LDRTST is used to retrieve the relevant process's SMP unsafe count,
1.49 +// the number of top-level binaries loaded into that process which are not
1.50 +// SMP safe. This works on all systems, including uniprocessor, even if
1.51 +// compatibility mode is not enabled, as this accounting is done
1.52 +// unconditionally.
1.53 +//
1.54 +// 2) If the system running the test has multiple processors, and one of the
1.55 +// compatibility modes is actually enabled, the test process runs a loop
1.56 +// designed to see if concurrent execution of threads actually happens.
1.57 +// (the loop is in smpsafe.cpp because it is shared between the test and
1.58 +// the small slave programs used).
1.59 +
1.60 +RTest test(_L("T_SMPSAFE"));
1.61 +RLdrTest ldd;
1.62 +
1.63 +RProcess pLoaded;
1.64 +TBool SMPPlatform;
1.65 +TBool CompatMode;
1.66 +
1.67 +extern TInt CheckAffinity();
1.68 +
1.69 +// load an exe and check that it has the expected SMP unsafe count (check 1)
1.70 +// don't resume/delete it yet.
1.71 +void DoStartExe(RProcess& p, const TDesC &aFilename, TInt aExpectedUnsafe)
1.72 + {
1.73 + test_KErrNone(p.Create(aFilename, KNullDesC));
1.74 + test_Equal(aExpectedUnsafe, ldd.ProcessSMPUnsafeCount(p.Handle()));
1.75 + }
1.76 +
1.77 +// resume the exe and if compatibility mode is available, check that the
1.78 +// expected outcome of the test loop was observed (check 2)
1.79 +// delete it afterward.
1.80 +void DoStopExe(RProcess& p, TInt aExpectedUnsafe)
1.81 + {
1.82 + TRequestStatus s;
1.83 + p.Logon(s);
1.84 + p.Resume();
1.85 + User::WaitForRequest(s);
1.86 + if (CompatMode)
1.87 + test_Equal(aExpectedUnsafe ? 1 : 0, s.Int());
1.88 + test_Equal(EExitKill, p.ExitType());
1.89 + p.NotifyDestruction(s);
1.90 + p.Close();
1.91 + User::WaitForRequest(s);
1.92 + }
1.93 +
1.94 +void StartExe(const TDesC &aFilename, TInt aExpectedUnsafe)
1.95 + {
1.96 + DoStartExe(pLoaded, aFilename, aExpectedUnsafe);
1.97 + }
1.98 +
1.99 +void StopExe(TInt aExpectedUnsafe)
1.100 + {
1.101 + DoStopExe(pLoaded, aExpectedUnsafe);
1.102 + }
1.103 +
1.104 +// start and stop an exe, doing both checks 1 and 2.
1.105 +void TryExe(const TDesC &aFilename, TInt aExpectedUnsafe)
1.106 + {
1.107 + RProcess p;
1.108 + DoStartExe(p, aFilename, aExpectedUnsafe);
1.109 + DoStopExe(p, aExpectedUnsafe);
1.110 + }
1.111 +
1.112 +// check the main test process, both checks 1 and 2.
1.113 +void CheckSelf(TInt aExpectedUnsafe)
1.114 + {
1.115 + test_Equal(aExpectedUnsafe, ldd.ProcessSMPUnsafeCount(RProcess().Handle()));
1.116 + if (CompatMode)
1.117 + test_Equal(aExpectedUnsafe ? 1 : 0, CheckAffinity());
1.118 + }
1.119 +
1.120 +GLDEF_C TInt E32Main()
1.121 + {
1.122 + RLibrary l, l2;
1.123 +
1.124 + // Turn off evil lazy dll unloading
1.125 + RLoader ldr;
1.126 + test(ldr.Connect()==KErrNone);
1.127 + test(ldr.CancelLazyDllUnload()==KErrNone);
1.128 + ldr.Close();
1.129 +
1.130 + test.Title();
1.131 + test.Start(_L("Test SMP safe binary flag"));
1.132 +
1.133 + test.Next(_L("Get number of CPUs"));
1.134 + TInt cpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
1.135 + test_Compare(cpus, >, 0);
1.136 + SMPPlatform = cpus > 1;
1.137 + if (!SMPPlatform)
1.138 + {
1.139 + CompatMode = EFalse;
1.140 + test.Printf(_L("*****************************************************\n"));
1.141 + test.Printf(_L("Uniprocessor system, not actually testing compat mode\n"));
1.142 + test.Printf(_L("*****************************************************\n"));
1.143 + }
1.144 + else
1.145 + {
1.146 + test.Next(_L("Get compatibility mode setting"));
1.147 + TInt flags = UserSvr::HalFunction(EHalGroupKernel, EKernelHalConfigFlags, 0, 0);
1.148 + test_Compare(flags, >=, 0);
1.149 + CompatMode = flags & (EKernelConfigSMPUnsafeCompat | EKernelConfigSMPUnsafeCPU0);
1.150 + if (!CompatMode)
1.151 + {
1.152 + test.Printf(_L("*************************************************\n"));
1.153 + test.Printf(_L("Compatibility mode is not enabled, not testing it\n"));
1.154 + test.Printf(_L("*************************************************\n"));
1.155 + }
1.156 + }
1.157 +
1.158 + test.Next(_L("Load test LDD"));
1.159 + TInt r = User::LoadLogicalDevice(_L("d_ldrtst.ldd"));
1.160 + test(r==KErrNone || r==KErrAlreadyExists);
1.161 + test_KErrNone(ldd.Open());
1.162 +
1.163 + test.Next(_L("Check we are safe ourselves"));
1.164 + CheckSelf(0);
1.165 +
1.166 + test.Next(_L("Check safe exe"));
1.167 + StartExe(_L("smpsafe0.exe"), 0);
1.168 + test.Next(_L("Load already loaded safe exe (self)"));
1.169 + TryExe(_L("smpsafe0.exe"), 0);
1.170 + StopExe(0);
1.171 +
1.172 + test.Next(_L("Check safe XIP exe"));
1.173 + StartExe(_L("smpsafex0.exe"), 0);
1.174 + test.Next(_L("Load already loaded safe XIP exe (self)"));
1.175 + TryExe(_L("smpsafex0.exe"), 0);
1.176 + StopExe(0);
1.177 +
1.178 + test.Next(_L("Load unsafe exe"));
1.179 + StartExe(_L("smpsafe1.exe"), 1);
1.180 + test.Next(_L("Load already loaded unsafe exe"));
1.181 + TryExe(_L("smpsafe1.exe"), 1);
1.182 + StopExe(1);
1.183 +
1.184 + test.Next(_L("Load safe exe directly linked to unsafe dll"));
1.185 + TryExe(_L("smpsafe2.exe"), 1);
1.186 +
1.187 + test.Next(_L("Dynamically load unsafe dll"));
1.188 + test_KErrNone(l.Load(_L("smpsafea.dll")));
1.189 + CheckSelf(1);
1.190 + test.Next(_L("Load safe exe directly linked to loaded unsafe dll"));
1.191 + TryExe(_L("smpsafe2.exe"), 1);
1.192 + test.Next(_L("Dynamically unload unsafe dll"));
1.193 + l.Close();
1.194 + CheckSelf(0);
1.195 +
1.196 + test.Next(_L("Load safe XIP exe directly linked to unsafe XIP dll"));
1.197 + TryExe(_L("smpsafex2.exe"), 1);
1.198 +
1.199 + test.Next(_L("Dynamically load unsafe XIP dll"));
1.200 + test_KErrNone(l.Load(_L("smpsafexa.dll")));
1.201 + CheckSelf(1);
1.202 + test.Next(_L("Load safe XIP exe directly linked to loaded unsafe XIP dll"));
1.203 + TryExe(_L("smpsafex2.exe"), 1);
1.204 + test.Next(_L("Dynamically unload unsafe XIP dll"));
1.205 + l.Close();
1.206 + CheckSelf(0);
1.207 +
1.208 + test.Next(_L("Load safe exe indirectly linked to unsafe dll"));
1.209 + TryExe(_L("smpsafe3.exe"), 1);
1.210 +
1.211 + test.Next(_L("Dynamically load unsafe dll"));
1.212 + test_KErrNone(l.Load(_L("smpsafea.dll")));
1.213 + CheckSelf(1);
1.214 + test.Next(_L("Load safe exe indirectly linked to loaded unsafe dll"));
1.215 + TryExe(_L("smpsafe3.exe"), 1);
1.216 + test.Next(_L("Dynamically unload unsafe dll"));
1.217 + l.Close();
1.218 + CheckSelf(0);
1.219 +
1.220 + test.Next(_L("Dynamically load safe dll linked to unsafe dll"));
1.221 + test_KErrNone(l.Load(_L("smpsafeb.dll")));
1.222 + CheckSelf(1);
1.223 + test.Next(_L("Load safe exe indirectly linked to unsafe dll, inbetween loaded"));
1.224 + TryExe(_L("smpsafe3.exe"), 1);
1.225 + test.Next(_L("Dynamically load unsafe dll as well"));
1.226 + test_KErrNone(l2.Load(_L("smpsafea.dll")));
1.227 + CheckSelf(2);
1.228 + test.Next(_L("Dynamically unload safe dll linked to unsafe dll"));
1.229 + l.Close();
1.230 + CheckSelf(1);
1.231 + test.Next(_L("Dynamically unload unsafe dll as well"));
1.232 + l2.Close();
1.233 + CheckSelf(0);
1.234 +
1.235 + test.Next(_L("Load safe exe directly linked to unsafe XIP dll"));
1.236 + TryExe(_L("smpsafe4.exe"), 1);
1.237 +
1.238 + test.Next(_L("Dynamically load unsafe XIP dll"));
1.239 + test_KErrNone(l.Load(_L("smpsafexa.dll")));
1.240 + CheckSelf(1);
1.241 + test.Next(_L("Load safe exe directly linked to loaded unsafe XIP dll"));
1.242 + TryExe(_L("smpsafe4.exe"), 1);
1.243 + test.Next(_L("Dynamically unload unsafe XIP dll"));
1.244 + l.Close();
1.245 + CheckSelf(0);
1.246 +
1.247 + test.Next(_L("Dynamically load figure-eight dll cycle"));
1.248 + test_KErrNone(l.Load(_L("smpsafec.dll")));
1.249 + CheckSelf(1);
1.250 + test.Next(_L("Load figure-eight from a different point"));
1.251 + test_KErrNone(l2.Load(_L("smpsafed.dll")));
1.252 + CheckSelf(2);
1.253 + test.Next(_L("Unload original point"));
1.254 + l.Close();
1.255 + CheckSelf(1);
1.256 + test.Next(_L("Unload second point"));
1.257 + l2.Close();
1.258 + CheckSelf(0);
1.259 +
1.260 + test.Next(_L("Close test LDD"));
1.261 + ldd.Close();
1.262 + test_KErrNone(User::FreeLogicalDevice(KLdrTestLddName));
1.263 +
1.264 + test.End();
1.265 + return KErrNone;
1.266 + }