os/kernelhwsrv/kerneltest/e32test/thread/t_smpsafe.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\thread\t_smpsafe.cpp
    15 // 
    16 //
    17 
    18 #define __E32TEST_EXTENSION__
    19 #include <e32test.h>
    20 #include <e32ldr.h>
    21 #include <e32svr.h>
    22 #include "u32std.h"
    23 #include <u32hal.h>
    24 #include <d_ldrtst.h>
    25 
    26 /////////////////////////////////////////////////////////////////////////////
    27 //
    28 //! @SYMTestCaseID			KBASE-T_SMPSAFE-2700
    29 //! @SYMTestType			UT
    30 //! @SYMPREQ				PREQ2094
    31 //! @SYMTestCaseDesc		SMP compatibility mode test
    32 //! @SYMTestActions			
    33 //! @SYMTestExpectedResults All tests should pass.
    34 //! @SYMTestPriority        Medium
    35 //! @SYMTestStatus          Implemented
    36 //
    37 // The test attempts to prove that the SMPSAFE compatibility mode mechanism
    38 // works and correctly forces processes which contain any unsafe code to run
    39 // as if they were on a single-cpu machine. This is done by loading and
    40 // unloading various combinations of DLLs into the test process itself, and
    41 // by spawning and exiting various EXEs.
    42 //
    43 // Two things are checked for each combination:
    44 //
    45 // 1) D_LDRTST is used to retrieve the relevant process's SMP unsafe count,
    46 //    the number of top-level binaries loaded into that process which are not
    47 //    SMP safe. This works on all systems, including uniprocessor, even if
    48 //    compatibility mode is not enabled, as this accounting is done
    49 //    unconditionally.
    50 //
    51 // 2) If the system running the test has multiple processors, and one of the
    52 //    compatibility modes is actually enabled, the test process runs a loop
    53 //    designed to see if concurrent execution of threads actually happens.
    54 //    (the loop is in smpsafe.cpp because it is shared between the test and
    55 //    the small slave programs used).
    56 
    57 RTest test(_L("T_SMPSAFE"));
    58 RLdrTest ldd;
    59 
    60 RProcess pLoaded;
    61 TBool SMPPlatform;
    62 TBool CompatMode;
    63 
    64 extern TInt CheckAffinity();
    65 
    66 // load an exe and check that it has the expected SMP unsafe count (check 1)
    67 // don't resume/delete it yet.
    68 void DoStartExe(RProcess& p, const TDesC &aFilename, TInt aExpectedUnsafe)
    69 	{
    70 	test_KErrNone(p.Create(aFilename, KNullDesC));
    71 	test_Equal(aExpectedUnsafe, ldd.ProcessSMPUnsafeCount(p.Handle()));
    72 	}
    73 
    74 // resume the exe and if compatibility mode is available, check that the
    75 // expected outcome of the test loop was observed (check 2)
    76 // delete it afterward.
    77 void DoStopExe(RProcess& p, TInt aExpectedUnsafe)
    78 	{
    79 	TRequestStatus s;
    80 	p.Logon(s);
    81 	p.Resume();
    82 	User::WaitForRequest(s);
    83 	if (CompatMode)
    84 		test_Equal(aExpectedUnsafe ? 1 : 0, s.Int());
    85 	test_Equal(EExitKill, p.ExitType());
    86 	p.NotifyDestruction(s);
    87 	p.Close();
    88 	User::WaitForRequest(s);
    89 	}
    90 
    91 void StartExe(const TDesC &aFilename, TInt aExpectedUnsafe)
    92 	{
    93 	DoStartExe(pLoaded, aFilename, aExpectedUnsafe);
    94 	}
    95 
    96 void StopExe(TInt aExpectedUnsafe)
    97 	{
    98 	DoStopExe(pLoaded, aExpectedUnsafe);
    99 	}
   100 
   101 // start and stop an exe, doing both checks 1 and 2.
   102 void TryExe(const TDesC &aFilename, TInt aExpectedUnsafe)
   103 	{
   104 	RProcess p;
   105 	DoStartExe(p, aFilename, aExpectedUnsafe);
   106 	DoStopExe(p, aExpectedUnsafe);
   107 	}
   108 
   109 // check the main test process, both checks 1 and 2.
   110 void CheckSelf(TInt aExpectedUnsafe)
   111 	{
   112 	test_Equal(aExpectedUnsafe, ldd.ProcessSMPUnsafeCount(RProcess().Handle()));
   113 	if (CompatMode)
   114 		test_Equal(aExpectedUnsafe ? 1 : 0, CheckAffinity());
   115 	}
   116 
   117 GLDEF_C TInt E32Main()
   118 	{
   119 	RLibrary l, l2;
   120 
   121 	// Turn off evil lazy dll unloading
   122 	RLoader ldr;
   123 	test(ldr.Connect()==KErrNone);
   124 	test(ldr.CancelLazyDllUnload()==KErrNone);
   125 	ldr.Close();
   126 
   127 	test.Title();
   128 	test.Start(_L("Test SMP safe binary flag"));
   129 
   130 	test.Next(_L("Get number of CPUs"));
   131 	TInt cpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
   132 	test_Compare(cpus, >, 0);
   133 	SMPPlatform = cpus > 1;
   134 	if (!SMPPlatform)
   135 		{
   136 		CompatMode = EFalse;
   137 		test.Printf(_L("*****************************************************\n"));
   138 		test.Printf(_L("Uniprocessor system, not actually testing compat mode\n"));
   139 		test.Printf(_L("*****************************************************\n"));
   140 		}
   141 	else
   142 		{
   143 		test.Next(_L("Get compatibility mode setting"));
   144 		TInt flags = UserSvr::HalFunction(EHalGroupKernel, EKernelHalConfigFlags, 0, 0);
   145 		test_Compare(flags, >=, 0);
   146 		CompatMode = flags & (EKernelConfigSMPUnsafeCompat | EKernelConfigSMPUnsafeCPU0);
   147 		if (!CompatMode)
   148 			{
   149 			test.Printf(_L("*************************************************\n"));
   150 			test.Printf(_L("Compatibility mode is not enabled, not testing it\n"));
   151 			test.Printf(_L("*************************************************\n"));
   152 			}
   153 		}
   154 
   155 	test.Next(_L("Load test LDD"));
   156 	TInt r = User::LoadLogicalDevice(_L("d_ldrtst.ldd"));
   157 	test(r==KErrNone || r==KErrAlreadyExists);
   158 	test_KErrNone(ldd.Open());
   159 
   160 	test.Next(_L("Check we are safe ourselves"));
   161 	CheckSelf(0);
   162 
   163 	test.Next(_L("Check safe exe"));
   164 	StartExe(_L("smpsafe0.exe"), 0);
   165 	test.Next(_L("Load already loaded safe exe (self)"));
   166 	TryExe(_L("smpsafe0.exe"), 0);
   167 	StopExe(0);
   168 
   169 	test.Next(_L("Check safe XIP exe"));
   170 	StartExe(_L("smpsafex0.exe"), 0);
   171 	test.Next(_L("Load already loaded safe XIP exe (self)"));
   172 	TryExe(_L("smpsafex0.exe"), 0);
   173 	StopExe(0);
   174 
   175 	test.Next(_L("Load unsafe exe"));
   176 	StartExe(_L("smpsafe1.exe"), 1);
   177 	test.Next(_L("Load already loaded unsafe exe"));
   178 	TryExe(_L("smpsafe1.exe"), 1);
   179 	StopExe(1);
   180 
   181 	test.Next(_L("Load safe exe directly linked to unsafe dll"));
   182 	TryExe(_L("smpsafe2.exe"), 1);
   183 
   184 	test.Next(_L("Dynamically load unsafe dll"));
   185 	test_KErrNone(l.Load(_L("smpsafea.dll")));
   186 	CheckSelf(1);
   187 	test.Next(_L("Load safe exe directly linked to loaded unsafe dll"));
   188 	TryExe(_L("smpsafe2.exe"), 1);
   189 	test.Next(_L("Dynamically unload unsafe dll"));
   190 	l.Close();
   191 	CheckSelf(0);
   192 
   193 	test.Next(_L("Load safe XIP exe directly linked to unsafe XIP dll"));
   194 	TryExe(_L("smpsafex2.exe"), 1);
   195 
   196 	test.Next(_L("Dynamically load unsafe XIP dll"));
   197 	test_KErrNone(l.Load(_L("smpsafexa.dll")));
   198 	CheckSelf(1);
   199 	test.Next(_L("Load safe XIP exe directly linked to loaded unsafe XIP dll"));
   200 	TryExe(_L("smpsafex2.exe"), 1);
   201 	test.Next(_L("Dynamically unload unsafe XIP dll"));
   202 	l.Close();
   203 	CheckSelf(0);
   204 
   205 	test.Next(_L("Load safe exe indirectly linked to unsafe dll"));
   206 	TryExe(_L("smpsafe3.exe"), 1);
   207 
   208 	test.Next(_L("Dynamically load unsafe dll"));
   209 	test_KErrNone(l.Load(_L("smpsafea.dll")));
   210 	CheckSelf(1);
   211 	test.Next(_L("Load safe exe indirectly linked to loaded unsafe dll"));
   212 	TryExe(_L("smpsafe3.exe"), 1);
   213 	test.Next(_L("Dynamically unload unsafe dll"));
   214 	l.Close();
   215 	CheckSelf(0);
   216 
   217 	test.Next(_L("Dynamically load safe dll linked to unsafe dll"));
   218 	test_KErrNone(l.Load(_L("smpsafeb.dll")));
   219 	CheckSelf(1);
   220 	test.Next(_L("Load safe exe indirectly linked to unsafe dll, inbetween loaded"));
   221 	TryExe(_L("smpsafe3.exe"), 1);
   222 	test.Next(_L("Dynamically load unsafe dll as well"));
   223 	test_KErrNone(l2.Load(_L("smpsafea.dll")));
   224 	CheckSelf(2);
   225 	test.Next(_L("Dynamically unload safe dll linked to unsafe dll"));
   226 	l.Close();
   227 	CheckSelf(1);
   228 	test.Next(_L("Dynamically unload unsafe dll as well"));
   229 	l2.Close();
   230 	CheckSelf(0);
   231 
   232 	test.Next(_L("Load safe exe directly linked to unsafe XIP dll"));
   233 	TryExe(_L("smpsafe4.exe"), 1);
   234 
   235 	test.Next(_L("Dynamically load unsafe XIP dll"));
   236 	test_KErrNone(l.Load(_L("smpsafexa.dll")));
   237 	CheckSelf(1);
   238 	test.Next(_L("Load safe exe directly linked to loaded unsafe XIP dll"));
   239 	TryExe(_L("smpsafe4.exe"), 1);
   240 	test.Next(_L("Dynamically unload unsafe XIP dll"));
   241 	l.Close();
   242 	CheckSelf(0);
   243 
   244 	test.Next(_L("Dynamically load figure-eight dll cycle"));
   245 	test_KErrNone(l.Load(_L("smpsafec.dll")));
   246 	CheckSelf(1);
   247 	test.Next(_L("Load figure-eight from a different point"));
   248 	test_KErrNone(l2.Load(_L("smpsafed.dll")));
   249 	CheckSelf(2);
   250 	test.Next(_L("Unload original point"));
   251 	l.Close();
   252 	CheckSelf(1);
   253 	test.Next(_L("Unload second point"));
   254 	l2.Close();
   255 	CheckSelf(0);
   256 
   257 	test.Next(_L("Close test LDD"));
   258 	ldd.Close();
   259 	test_KErrNone(User::FreeLogicalDevice(KLdrTestLddName));
   260 
   261 	test.End();
   262 	return KErrNone;
   263 	}