1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/demandpaging/t_wdpsoak.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,643 @@
1.4 +// Copyright (c) 2005-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\mmu\t_wdpsoak.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#define __E32TEST_EXTENSION__
1.22 +#include <e32test.h>
1.23 +#include <dptest.h>
1.24 +#include <hal.h>
1.25 +#include "../mmu/mmudetect.h"
1.26 +#include "../mmu/freeram.h"
1.27 +
1.28 +#define MAX_CHUNKS 10
1.29 +#define PRINT(string) if (!gQuiet) test.Printf(string)
1.30 +#define PRINT1(string,param) if (!gQuiet) test.Printf(string,param)
1.31 +#define TESTNEXT(string) if (!gQuiet) test.Next(string)
1.32 +
1.33 +//------------globals---------------------
1.34 +LOCAL_D RTest test(_L("T_WDPSOAK"));
1.35 +LOCAL_D TInt gPageSize = 0;
1.36 +LOCAL_D TUint gChunkSize = 0; // default chunk size
1.37 +LOCAL_D RChunk gChunk[MAX_CHUNKS];
1.38 +LOCAL_D TUint gNextChunk = 0;
1.39 +LOCAL_D TBool gQuiet = EFalse;
1.40 +LOCAL_D TUint gPeriod = 0;
1.41 +LOCAL_D TUint gMin = 0;
1.42 +LOCAL_D TUint gMax = 0;
1.43 +LOCAL_D TUint gMemScheme = 0;
1.44 +
1.45 +const TUint32 KFlushQuietLimit = 100000;
1.46 +
1.47 +TUint64 SwapFree()
1.48 + {
1.49 + SVMSwapInfo swapInfo;
1.50 + test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalGetSwapInfo, &swapInfo, 0));
1.51 +
1.52 + return swapInfo.iSwapFree;
1.53 + }
1.54 +
1.55 +TUint64 SwapSize()
1.56 + {
1.57 + SVMSwapInfo swapInfo;
1.58 + test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalGetSwapInfo, &swapInfo, 0));
1.59 +
1.60 + return swapInfo.iSwapSize;
1.61 + }
1.62 +
1.63 +void CacheSize(TUint aMin, TUint aMax)
1.64 + {
1.65 + SVMCacheInfo info;
1.66 + if (UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&info,0) != KErrNone)
1.67 + {
1.68 + return;
1.69 + }
1.70 +
1.71 + if (aMin > 0 || aMax > 0)
1.72 + {
1.73 + if (aMin > 0)
1.74 + {
1.75 + info.iMinSize = aMin;
1.76 + }
1.77 + if (aMax > 0)
1.78 + {
1.79 + info.iMaxSize = aMax;
1.80 + }
1.81 + UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)info.iMinSize,(TAny*)info.iMaxSize);
1.82 + if (UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&info,0) != KErrNone)
1.83 + {
1.84 + return;
1.85 + }
1.86 + }
1.87 +
1.88 + PRINT1(_L("Paging Cache min size %d"),info.iMinSize);
1.89 + PRINT1(_L(" max size %d"),info.iMaxSize);
1.90 + PRINT1(_L(" current size %d\n"),info.iCurrentSize);
1.91 + }
1.92 +
1.93 +void ShowMemoryUse()
1.94 + {
1.95 + PRINT1(_L("RAM free 0x%08X bytes"),FreeRam());
1.96 + PRINT1(_L(" Swap free 0x%08X bytes\n"),SwapFree());
1.97 +
1.98 + TPckgBuf<DPTest::TEventInfo> infoBuf;
1.99 + TInt r = UserSvr::HalFunction(EHalGroupVM,EVMHalGetEventInfo,&infoBuf,0);
1.100 + if (r!=KErrNone)
1.101 + {
1.102 + return;
1.103 + }
1.104 + PRINT1(_L("Page fault count %d"),infoBuf().iPageFaultCount);
1.105 + PRINT1(_L(" Page IN count %d\n"),infoBuf().iPageInReadCount);
1.106 +
1.107 + return;
1.108 + }
1.109 +
1.110 +void ShowHelp()
1.111 + {
1.112 + PRINT(_L("***************************************\n"));
1.113 + PRINT(_L("The following are immediate commands\n"));
1.114 + PRINT(_L("F flush the paging cache\n"));
1.115 + PRINT(_L("I show memory information\n"));
1.116 + PRINT(_L("? show this help\n"));
1.117 + PRINT(_L("Rn read all pages of chunk n\n"));
1.118 + PRINT(_L("Wn write all pages of chunk n\n"));
1.119 + PRINT(_L("Mn periodic memory scheme n\n"));
1.120 + PRINT(_L("The following require a <CR> termination\n"));
1.121 + PRINT(_L("C=nnnn create a chunnk of size nnnn\n"));
1.122 + PRINT(_L("L=nnnn paging cache min size nnnn\n"));
1.123 + PRINT(_L("H=nnnn paging cache max size nnnn\n"));
1.124 + PRINT(_L("P=nnnn periodic flush/memory scheme nnnn microseconds\n"));
1.125 + PRINT(_L("Esc to exit\n"));
1.126 + PRINT(_L("***************************************\n"));
1.127 + }
1.128 +
1.129 +void CreateChunk(RChunk * aChunk, TUint aSize)
1.130 + {
1.131 + TESTNEXT(_L("Creating a paged chunk"));
1.132 + TChunkCreateInfo createInfo;
1.133 + PRINT1(_L("Creating chunk size 0x%08X bytes "),aSize);
1.134 + PRINT1(_L("at index %d\n"),gNextChunk);
1.135 + createInfo.SetPaging(TChunkCreateInfo::EPaged);
1.136 + createInfo.SetNormal(aSize,aSize);
1.137 + test_KErrNone(aChunk->Create(createInfo));
1.138 + }
1.139 +
1.140 +void ReadChunk(RChunk * aChunk)
1.141 + {
1.142 + TESTNEXT(_L("Reading from each page of chunk"));
1.143 + TUint8* chunkBase = aChunk->Base();
1.144 +
1.145 + TUint8 chunkVal = 0;
1.146 + for (TInt i = 0; i < aChunk->Size(); i += gPageSize)
1.147 + {
1.148 + chunkVal = * (chunkBase + i);
1.149 + }
1.150 +
1.151 + // only needed to remove compiler warning on unused variable
1.152 + if (chunkVal)
1.153 + chunkVal = 0;
1.154 +
1.155 + return;
1.156 + }
1.157 +
1.158 +void WriteChunk(RChunk * aChunk, TUint8 aValue = 0)
1.159 + {
1.160 + static TUint8 lastWriteValue = 1;
1.161 + TESTNEXT(_L("Writing to each page of chunk"));
1.162 + TUint8* chunkBase = aChunk->Base();
1.163 +
1.164 + lastWriteValue = (TUint8)(aValue == 0 ? lastWriteValue + 1 : aValue);
1.165 + for (TInt i = 0; i < aChunk->Size(); i += gPageSize)
1.166 + {
1.167 + * (chunkBase + i) = lastWriteValue;
1.168 + }
1.169 +
1.170 + return;
1.171 + }
1.172 +
1.173 +void ParseCommandLine ()
1.174 + {
1.175 + TBuf<64> c;
1.176 +
1.177 + User::CommandLine(c);
1.178 + c.LowerCase();
1.179 +
1.180 + if (c != KNullDesC)
1.181 + {
1.182 + TLex lex(c);
1.183 + TPtrC token;
1.184 +
1.185 + while (token.Set(lex.NextToken()), token != KNullDesC)
1.186 + {
1.187 + if (token.Mid(0) == _L("quiet"))
1.188 + {
1.189 + gQuiet = ETrue;
1.190 + continue;
1.191 + }
1.192 +
1.193 + if (token.Mid(0) == _L("verbose"))
1.194 + {
1.195 + gQuiet = EFalse;
1.196 + continue;
1.197 + }
1.198 +
1.199 + if (token.Left(5) == _L("chunk"))
1.200 + {
1.201 + TInt equalPos;
1.202 + equalPos = token.Locate('=');
1.203 + if (equalPos > 0 && (equalPos+1) < token.Length())
1.204 + {
1.205 + TLex lexNum(token.Mid(equalPos+1));
1.206 + lexNum.Val(gChunkSize,EDecimal);
1.207 + }
1.208 + continue;
1.209 + }
1.210 +
1.211 + if (token.Left(3) == _L("low"))
1.212 + {
1.213 + TInt equalPos;
1.214 + equalPos = token.Locate('=');
1.215 + if (equalPos > 0 && (equalPos+1) < token.Length())
1.216 + {
1.217 + TLex lexNum(token.Mid(equalPos+1));
1.218 + lexNum.Val(gMin,EDecimal);
1.219 + }
1.220 + continue;
1.221 + }
1.222 +
1.223 + if (token.Left(5) == _L("high"))
1.224 + {
1.225 + TInt equalPos;
1.226 + equalPos = token.Locate('=');
1.227 + if (equalPos > 0 && (equalPos+1) < token.Length())
1.228 + {
1.229 + TLex lexNum(token.Mid(equalPos+1));
1.230 + lexNum.Val(gMax,EDecimal);
1.231 + }
1.232 + continue;
1.233 + }
1.234 +
1.235 + if (token.Left(6) == _L("period"))
1.236 + {
1.237 + TInt equalPos;
1.238 + equalPos = token.Locate('=');
1.239 + if (equalPos > 0 && (equalPos+1) < token.Length())
1.240 + {
1.241 + TLex lexNum(token.Mid(equalPos+1));
1.242 + lexNum.Val(gPeriod,EDecimal);
1.243 + }
1.244 + continue;
1.245 + }
1.246 +
1.247 + if (token.Left(3) == _L("mem"))
1.248 + {
1.249 + TInt equalPos;
1.250 + equalPos = token.Locate('=');
1.251 + if (equalPos > 0 && (equalPos+1) < token.Length())
1.252 + {
1.253 + TLex lexNum(token.Mid(equalPos+1));
1.254 + lexNum.Val(gMemScheme,EDecimal);
1.255 + }
1.256 + continue;
1.257 + }
1.258 +
1.259 + }
1.260 + }
1.261 + }
1.262 +
1.263 +enum TimerActions
1.264 + {
1.265 + ENoaction = 0,
1.266 + EFlush = 1,
1.267 + EFlushQuiet = 2,
1.268 + EMemScheme1 = 1 << 4,
1.269 + EMemScheme2 = 2 << 4,
1.270 + EMemScheme3 = 3 << 4,
1.271 + EMemScheme4 = 4 << 4,
1.272 + };
1.273 +
1.274 +// CActive class to monitor KeyStrokes from User
1.275 +class CActiveConsole : public CActive
1.276 + {
1.277 +public:
1.278 + CActiveConsole();
1.279 + ~CActiveConsole();
1.280 + void GetCharacter();
1.281 + static TInt Callback(TAny* aCtrl);
1.282 +
1.283 +private:
1.284 + CPeriodic* iTimer;
1.285 + TChar iCmdGetValue;
1.286 + TBool iGetHexValue;
1.287 + TBool iPrompt;
1.288 + TChar iLastChar;
1.289 + TUint iValue;
1.290 + TUint16 iActions;
1.291 + TUint32 iPeriod;
1.292 +
1.293 + // Defined as pure virtual by CActive;
1.294 + // implementation provided by this class.
1.295 + virtual void DoCancel();
1.296 + // Defined as pure virtual by CActive;
1.297 + // implementation provided by this class,
1.298 + virtual void RunL();
1.299 + void ProcessKeyPressL(TChar aChar);
1.300 + void ProcessValue();
1.301 + };
1.302 +
1.303 +// Class CActiveConsole
1.304 +CActiveConsole::CActiveConsole()
1.305 + : CActive(EPriorityHigh)
1.306 + {
1.307 + CActiveScheduler::Add(this);
1.308 +
1.309 + iTimer = CPeriodic::NewL(EPriorityNormal);
1.310 + iActions = ENoaction;
1.311 + iPrompt = ETrue;
1.312 + iPeriod = 0;
1.313 + if (gPeriod > 0)
1.314 + {
1.315 + if (gMemScheme > 0)
1.316 + {
1.317 + iActions = (TUint16)(gMemScheme << 4);
1.318 + }
1.319 + else
1.320 + {
1.321 + iActions = (TUint16)(gPeriod < KFlushQuietLimit ? EFlushQuiet : EFlush);
1.322 + }
1.323 + iPeriod = gPeriod;
1.324 + iTimer->Start(0,gPeriod,TCallBack(Callback,this));
1.325 + }
1.326 + }
1.327 +
1.328 +CActiveConsole::~CActiveConsole()
1.329 + {
1.330 + iTimer->Cancel();
1.331 + delete iTimer;
1.332 +
1.333 + Cancel();
1.334 + }
1.335 +
1.336 +// Callback function for timer expiry
1.337 +TInt CActiveConsole::Callback(TAny* aControl)
1.338 + {
1.339 + switch (((CActiveConsole*)aControl)->iActions & 0x0F)
1.340 + {
1.341 + case ENoaction :
1.342 + break;
1.343 +
1.344 + case EFlush :
1.345 + PRINT(_L("Flush\n"));
1.346 + // drop through to quiet
1.347 +
1.348 + case EFlushQuiet :
1.349 + test_KErrNone(DPTest::FlushCache());
1.350 + break;
1.351 +
1.352 + default :
1.353 + break;
1.354 + }
1.355 +
1.356 + switch (((CActiveConsole*)aControl)->iActions & 0xF0)
1.357 + {
1.358 + TUint i;
1.359 + case EMemScheme1 :
1.360 + for (i = 0; i < gNextChunk; i++)
1.361 + ReadChunk (&gChunk[i]);
1.362 + break;
1.363 +
1.364 + case EMemScheme2 :
1.365 + for (i = 0; i < gNextChunk; i++)
1.366 + WriteChunk (&gChunk[i]);
1.367 + break;
1.368 +
1.369 + default :
1.370 + break;
1.371 + }
1.372 +
1.373 + return KErrNone;
1.374 + }
1.375 +
1.376 +void CActiveConsole::GetCharacter()
1.377 + {
1.378 + if (iPrompt)
1.379 + {
1.380 + PRINT(_L("***Command (F,I,Q,V,?,Rn,Wn,Mn,C=nnnnn,H=nnnn,L=nnnn,P=nnnn) or Esc to exit ***\n"));
1.381 + iPrompt = EFalse;
1.382 + }
1.383 + test.Console()->Read(iStatus);
1.384 + SetActive();
1.385 + }
1.386 +
1.387 +void CActiveConsole::DoCancel()
1.388 + {
1.389 + PRINT(_L("CActiveConsole::DoCancel\n"));
1.390 + test.Console()->ReadCancel();
1.391 + }
1.392 +
1.393 +void CActiveConsole::ProcessKeyPressL(TChar aChar)
1.394 + {
1.395 + if (aChar == EKeyEscape)
1.396 + {
1.397 + PRINT(_L("CActiveConsole: ESC key pressed -> stopping active scheduler...\n"));
1.398 + CActiveScheduler::Stop();
1.399 + return;
1.400 + }
1.401 + aChar.UpperCase();
1.402 + if (iCmdGetValue != 0 && aChar == '\r')
1.403 + {
1.404 + if (iLastChar == 'K')
1.405 + {
1.406 + iValue *= iGetHexValue ? 0x400 : 1000;
1.407 + }
1.408 + if (iLastChar == 'M')
1.409 + {
1.410 + iValue *= iGetHexValue ? 0x10000 : 1000000;
1.411 + }
1.412 + PRINT1(_L("CActiveConsole: Value %d\n"),iValue);
1.413 + ProcessValue();
1.414 + }
1.415 + if (iCmdGetValue != 0 )
1.416 + {
1.417 + if (iGetHexValue)
1.418 + {
1.419 + if (aChar.IsDigit())
1.420 + {
1.421 + iValue = iValue * 16 + aChar.GetNumericValue();
1.422 + }
1.423 + else
1.424 + {
1.425 + if (aChar.IsHexDigit())
1.426 + {
1.427 + iValue = iValue * 16 + (TUint)aChar - 'A' + 10;
1.428 + }
1.429 + else
1.430 + {
1.431 + if (aChar != 'K' && aChar != 'M')
1.432 + {
1.433 + PRINT(_L("Illegal hexadecimal character - Enter command\n"));
1.434 + iCmdGetValue = 0;
1.435 + }
1.436 + }
1.437 + }
1.438 + }
1.439 + else
1.440 + {
1.441 + if (aChar.IsDigit())
1.442 + {
1.443 + iValue = iValue * 10 + aChar.GetNumericValue();
1.444 + }
1.445 + else
1.446 + {
1.447 + if ((aChar == 'X') && (iLastChar == '0') && (iValue == 0))
1.448 + iGetHexValue = ETrue;
1.449 + else
1.450 + {
1.451 + if (aChar != 'K' && aChar != 'M')
1.452 + {
1.453 + test.Printf(_L("Illegal decimal character - Enter command\n"));
1.454 + iCmdGetValue = 0;
1.455 + }
1.456 + }
1.457 + }
1.458 + }
1.459 + }
1.460 + else
1.461 + {
1.462 + switch (aChar)
1.463 + {
1.464 + case 'F' :
1.465 + TESTNEXT(_L("Flushing Cache"));
1.466 + test_KErrNone(DPTest::FlushCache());
1.467 + ShowMemoryUse();
1.468 + iPrompt = ETrue;
1.469 + break;
1.470 +
1.471 + case 'I' :
1.472 + CacheSize(0,0);
1.473 + ShowMemoryUse();
1.474 + iPrompt = ETrue;
1.475 + break;
1.476 +
1.477 + case 'Q' :
1.478 + gQuiet = ETrue;
1.479 + iPrompt = ETrue;
1.480 + break;
1.481 +
1.482 + case 'V' :
1.483 + gQuiet = EFalse;
1.484 + iPrompt = ETrue;
1.485 + break;
1.486 +
1.487 + case '?' :
1.488 + ShowHelp();
1.489 + break;
1.490 +
1.491 + case '=' :
1.492 + iCmdGetValue = iLastChar;
1.493 + iGetHexValue = EFalse;
1.494 + iValue = 0;
1.495 + break;
1.496 +
1.497 + default :
1.498 + if (aChar.IsDigit())
1.499 + {
1.500 + if (iLastChar == 'R')
1.501 + {
1.502 + if (aChar.GetNumericValue() < (TInt)gNextChunk)
1.503 + {
1.504 + ReadChunk (&gChunk[aChar.GetNumericValue()]);
1.505 + }
1.506 + else
1.507 + {
1.508 + for (TUint i = 0; i < gNextChunk; i++)
1.509 + ReadChunk (&gChunk[i]);
1.510 + }
1.511 + iPrompt = ETrue;
1.512 + }
1.513 + if (iLastChar == 'W')
1.514 + {
1.515 + if (aChar.GetNumericValue() < (TInt)gNextChunk)
1.516 + {
1.517 + WriteChunk (&gChunk[aChar.GetNumericValue()]);
1.518 + }
1.519 + else
1.520 + {
1.521 + for (TUint i = 0; i < gNextChunk; i++)
1.522 + WriteChunk (&gChunk[i]);
1.523 + }
1.524 + iPrompt = ETrue;
1.525 + }
1.526 + if (iLastChar == 'M')
1.527 + {
1.528 + if (aChar.GetNumericValue() == 0)
1.529 + {
1.530 + iActions = (TUint16)(iPeriod < KFlushQuietLimit ? EFlushQuiet : EFlush);
1.531 + }
1.532 + else
1.533 + {
1.534 + iActions = (TUint16)(aChar.GetNumericValue() << 4);
1.535 + }
1.536 + iPrompt = ETrue;
1.537 + }
1.538 + }
1.539 + break;
1.540 + }
1.541 + }
1.542 + iLastChar = aChar;
1.543 + GetCharacter();
1.544 + return;
1.545 + }
1.546 +
1.547 +void CActiveConsole::ProcessValue()
1.548 + {
1.549 + switch (iCmdGetValue)
1.550 + {
1.551 + case 'C' :
1.552 + if (iValue > 0 && gNextChunk < MAX_CHUNKS)
1.553 + {
1.554 + CreateChunk (&gChunk[gNextChunk], iValue);
1.555 + ReadChunk (&gChunk[gNextChunk]);
1.556 + ShowMemoryUse();
1.557 + gNextChunk++;
1.558 + }
1.559 + break;
1.560 +
1.561 + case 'H' :
1.562 + CacheSize (0,iValue);
1.563 + break;
1.564 +
1.565 + case 'L' :
1.566 + CacheSize (iValue,0);
1.567 + break;
1.568 +
1.569 + case 'P' :
1.570 + iPeriod = iValue;
1.571 + iActions = (TUint16)(iValue < KFlushQuietLimit ? EFlushQuiet : EFlush);
1.572 + iTimer->Cancel();
1.573 + if (iValue > 0)
1.574 + {
1.575 + iTimer->Start(0,iValue,TCallBack(Callback,this));
1.576 + }
1.577 + break;
1.578 +
1.579 + default :
1.580 + break;
1.581 + }
1.582 + iCmdGetValue = 0;
1.583 + iPrompt = ETrue;
1.584 + }
1.585 +
1.586 +void CActiveConsole::RunL()
1.587 + {
1.588 + ProcessKeyPressL(static_cast<TChar>(test.Console()->KeyCode()));
1.589 + }
1.590 +
1.591 +TInt E32Main()
1.592 + {
1.593 + test.Title();
1.594 + test.Start(_L("Writable Data Paging Soak Test"));
1.595 +
1.596 + ParseCommandLine();
1.597 +
1.598 + if (DPTest::Attributes() & DPTest::ERomPaging)
1.599 + test.Printf(_L("Rom paging supported\n"));
1.600 + if (DPTest::Attributes() & DPTest::ECodePaging)
1.601 + test.Printf(_L("Code paging supported\n"));
1.602 + if (DPTest::Attributes() & DPTest::EDataPaging)
1.603 + test.Printf(_L("Data paging supported\n"));
1.604 +
1.605 + TInt totalRamSize;
1.606 + HAL::Get(HAL::EMemoryRAM,totalRamSize);
1.607 + HAL::Get(HAL::EMemoryPageSize,gPageSize);
1.608 + test.Printf(_L("Total RAM size 0x%08X bytes"),totalRamSize);
1.609 + test.Printf(_L(" Swap size 0x%08X bytes"),SwapSize());
1.610 + test.Printf(_L(" Page size 0x%08X bytes\n"),gPageSize);
1.611 + CacheSize(gMin,gMax);
1.612 +
1.613 + if ((DPTest::Attributes() & DPTest::EDataPaging) == 0)
1.614 + {
1.615 + test.Printf(_L("Writable Demand Paging not supported\n"));
1.616 + test.End();
1.617 + return 0;
1.618 + }
1.619 +
1.620 + ShowMemoryUse();
1.621 +
1.622 + //User::SetDebugMask(0x00000008); //KMMU
1.623 + //User::SetDebugMask(0x00000080); //KEXEC
1.624 + //User::SetDebugMask(0x90000000); //KPANIC KMMU2
1.625 + //User::SetDebugMask(0x40000000, 1); //KPAGING
1.626 +
1.627 + if (gChunkSize)
1.628 + {
1.629 + CreateChunk (&gChunk[gNextChunk], gChunkSize);
1.630 + ReadChunk (&gChunk[gNextChunk]);
1.631 + ShowMemoryUse();
1.632 + gNextChunk++;
1.633 + }
1.634 +
1.635 + CActiveScheduler* myScheduler = new (ELeave) CActiveScheduler();
1.636 + CActiveScheduler::Install(myScheduler);
1.637 +
1.638 + CActiveConsole* myActiveConsole = new CActiveConsole();
1.639 + myActiveConsole->GetCharacter();
1.640 +
1.641 + CActiveScheduler::Start();
1.642 +
1.643 + test.End();
1.644 +
1.645 + return 0;
1.646 + }