1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/thread/t_thread.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1525 @@
1.4 +// Copyright (c) 1995-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_thread.cpp
1.18 +// Overview:
1.19 +// Tests the RThread class
1.20 +// API Information:
1.21 +// RThread, RUndertaker
1.22 +// Details:
1.23 +// - Create a thread, verify its priority, change the priority and verify results.
1.24 +// - Verify naming and renaming threads works as expected.
1.25 +// - Test logging on, resuming and closing a thread. Verify results are as expected.
1.26 +// - Test creating threads with a variety of invalid parameters. Verify results.
1.27 +// - Test the RUndertaker methods: create some threads, logon to the undertaker,
1.28 +// verify results upon killing a thread and setting the thread handle.
1.29 +// - Check kernel allocation when creating threads and undertakers. Verify the
1.30 +// heap has not been corrupted.
1.31 +// - Run a thread multiple times, panic within the thread, panic external to the
1.32 +// thread and exit a thread in a variety of ways. Verify results are as expected.
1.33 +// - Create a semaphore and some threads, verify the threads can wait on and signal
1.34 +// the semaphore.
1.35 +// - Test unclosed but completed threads.
1.36 +// - Suspend and resume some threads in a variety of ways, verify results are as
1.37 +// expected.
1.38 +// - Test thread duplication.
1.39 +// - Test opening a thread using an full name, perform various tests by finding,
1.40 +// killing, closing, recreating etc. Verify the results are as expected.
1.41 +// - Test creating a thread using a duplicate name then reuse the thread with a
1.42 +// valid name. Verify results are as expected.
1.43 +// - Verify that a panicked thread releases an existing mutex.
1.44 +// - Test thread ID: attempt to open a nonexistent thread by ID, verify different
1.45 +// threads have different IDs, verify open by ID works as expected.
1.46 +// - Test RThread::StackInfo(), print results and verify results are as expected.
1.47 +// Platforms/Drives/Compatibility:
1.48 +// All.
1.49 +// Assumptions/Requirement/Pre-requisites:
1.50 +// Failures and causes:
1.51 +// Base Port information:
1.52 +//
1.53 +//
1.54 +
1.55 +#define __E32TEST_EXTENSION__
1.56 +#include <e32test.h>
1.57 +#include <e32panic.h>
1.58 +#include <e32svr.h>
1.59 +#include <u32hal.h>
1.60 +#include <e32atomics.h>
1.61 +#include <e32def.h>
1.62 +#include <e32def_private.h>
1.63 +#include "../misc/prbs.h"
1.64 +
1.65 +const TInt KNumThreads=20;
1.66 +
1.67 +const TInt KExitPanicNum=999;
1.68 +const TInt KHeapSize=0x200;
1.69 +const TInt KThreadReturnValue=9999;
1.70 +const TInt KTerminationReason=1234;
1.71 +const TInt KKillReason=4321;
1.72 +enum TInstruction {ENormal,EInstrPanic,EWait};
1.73 +
1.74 +const TInt KWaitTime=800000;
1.75 +
1.76 +class TReadInfo
1.77 + {
1.78 +public:
1.79 + TDesC* tdesc;
1.80 + TPtrC* tptrc;
1.81 + TDes* tdes;
1.82 + TPtr* tptr;
1.83 + HBufC* hbufc;
1.84 + TBufC<0x20>* tbufc;
1.85 + TBuf<0x20>* tbuf;
1.86 + TPtr* tptrdes;
1.87 + TAny* anAddress;
1.88 + };
1.89 +
1.90 +LOCAL_D RTest test(_L("T_THREAD"));
1.91 +LOCAL_D RTest rtest(_L("Read thread tests"));
1.92 +LOCAL_D RTest wtest(_L("Write thread tests"));
1.93 +
1.94 +#define rtest(x) rtest(x,__LINE__)
1.95 +#define wtest(x) wtest(x,__LINE__)
1.96 +
1.97 +LOCAL_C TInt LoopyThread(TAny*)
1.98 + {
1.99 +
1.100 + FOREVER
1.101 + User::AfterHighRes(1000);
1.102 + }
1.103 +
1.104 +LOCAL_D void testUndertaker(TOwnerType anOwnerType)
1.105 +//
1.106 +// Test RThreadWatcher
1.107 +//
1.108 + {
1.109 +
1.110 + RThread thread1;
1.111 + TInt r;
1.112 + test.Start(_L("Test the RUndertaker class"));
1.113 + test.Next(_L("Create a thread"));
1.114 +// if (anOwnerType==EOwnerThread)
1.115 +// User::SetDebugMask(0x8000867c);
1.116 + r=thread1.Create(_L("Loopy1"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
1.117 + test(r==KErrNone);
1.118 + thread1.Resume();
1.119 +
1.120 + TRequestStatus stat1;
1.121 + TInt threadHandle1;
1.122 + RThread w1;
1.123 + RUndertaker u1;
1.124 + test.Next(_L("Create an RUndertaker"));
1.125 + r=u1.Create();
1.126 + test(r==KErrNone);
1.127 + test.Next(_L("Logon to RUndertaker"));
1.128 + r=u1.Logon(stat1,threadHandle1);
1.129 + test(r==KErrNone);
1.130 + test.Next(_L("Logon again & check we're rejected"));
1.131 + r=u1.Logon(stat1,threadHandle1);
1.132 + test(r==KErrInUse);
1.133 + test.Next(_L("Cancel logon to RUndertaker"));
1.134 + r=u1.LogonCancel();
1.135 + test(r==KErrNone);
1.136 + test(stat1==KErrCancel);
1.137 +
1.138 + test.Next(_L("Logon to RUndertaker again"));
1.139 + u1.Logon(stat1,threadHandle1);
1.140 +
1.141 + test.Next(_L("Create another thread"));
1.142 + RThread thread2;
1.143 + r=thread2.Create(_L("Loopy2"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
1.144 + test(r==KErrNone);
1.145 + thread2.Resume();
1.146 +
1.147 + TRequestStatus stat2;
1.148 + TInt threadHandle2;
1.149 + RThread w2;
1.150 + RUndertaker u2;
1.151 + test.Next(_L("Create another RUndertaker"));
1.152 + r=u2.Create();
1.153 + test(r==KErrNone);
1.154 + test.Next(_L("Logon to RUndertaker"));
1.155 + r=u2.Logon(stat2,threadHandle2);
1.156 + test(r==KErrNone);
1.157 +
1.158 + test.Next(_L("Create yet another thread"));
1.159 + RThread thread3;
1.160 + r=thread3.Create(_L("Loopy3"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
1.161 + test(r==KErrNone);
1.162 + thread3.Resume();
1.163 +
1.164 + test.Next(_L("Kill the first thread & check the undertakers"));
1.165 + thread1.Kill(0x489);
1.166 + thread1.Close();
1.167 +
1.168 + User::WaitForRequest(stat1);
1.169 + User::WaitForRequest(stat2);
1.170 + test(stat1==KErrDied);
1.171 + test(stat2==KErrDied);
1.172 +
1.173 + RThread keep1;
1.174 + RThread keep2;
1.175 + test.Next(_L("Set the RThread handles"));
1.176 + keep1.SetHandle(threadHandle1);
1.177 + keep2.SetHandle(threadHandle2);
1.178 +
1.179 + test.Next(_L("Test the exit reasons"));
1.180 + test(keep1.ExitReason()==0x489);
1.181 + test(keep2.ExitReason()==0x489);
1.182 +// test.Printf(_L("Thread name %S\n"),&(w1.Name()));
1.183 +
1.184 + test.Next(_L("Logon again with both watchers"));
1.185 + r=u1.Logon(stat1,threadHandle1);
1.186 + test(r==KErrNone);
1.187 + r=u2.Logon(stat2,threadHandle2);
1.188 + test(r==KErrNone);
1.189 +
1.190 + test.Next(_L("Kill the 3rd thread & check the undertakers"));
1.191 + thread3.Kill(0x999);
1.192 + thread3.Close();
1.193 +
1.194 + User::WaitForRequest(stat1);
1.195 + User::WaitForRequest(stat2);
1.196 + test(stat1==KErrDied);
1.197 + test(stat2==KErrDied);
1.198 +
1.199 + test.Next(_L("Set the RThread handles"));
1.200 + w1.SetHandle(threadHandle1);
1.201 + w2.SetHandle(threadHandle2);
1.202 +
1.203 + test.Next(_L("Test the exit reasons"));
1.204 + test(w1.ExitReason()==0x999);
1.205 + test(w2.ExitReason()==0x999);
1.206 +// test.Printf(_L("Thread name %S\n"),&(w1.Name()));
1.207 + w1.Close();
1.208 + CLOSE_AND_WAIT(w2);
1.209 +
1.210 + test.Next(_L("Logon again with both undertakers"));
1.211 + r=u1.Logon(stat1,threadHandle1);
1.212 + test(r==KErrNone);
1.213 + r=u2.Logon(stat2,threadHandle2);
1.214 + test(r==KErrNone);
1.215 +
1.216 + test.Next(_L("Kill the 2nd thread & check the undertakers"));
1.217 + thread2.Kill(0x707);
1.218 + thread2.Close();
1.219 +
1.220 + User::WaitForRequest(stat1);
1.221 + User::WaitForRequest(stat2);
1.222 + test(stat1==KErrDied);
1.223 + test(stat2==KErrDied);
1.224 +
1.225 + test.Next(_L("Set the RThread handles"));
1.226 + w1.SetHandle(threadHandle1);
1.227 + w2.SetHandle(threadHandle2);
1.228 +
1.229 + test.Next(_L("Test the exit reasons"));
1.230 + test(w1.ExitReason()==0x707);
1.231 + test(w2.ExitReason()==0x707);
1.232 +// test.Printf(_L("Thread name %S\n"),&(w1.Name()));
1.233 +
1.234 + test.Next(_L("Check kernel allocation"));
1.235 + test.Next(_L("Please wait while I create & close masses of threads"));
1.236 + RThread t[KNumThreads];
1.237 + TInt j;
1.238 + for (j=0; j<KNumThreads; j++)
1.239 + {
1.240 + TBuf<0x10> name;
1.241 + name.Format(_L("LoopyThread%d"),j);
1.242 + test(t[j].Create(name, LoopyThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)NULL,anOwnerType)==KErrNone);
1.243 + }
1.244 + for (j=0; j<KNumThreads-1; j++)
1.245 + {
1.246 + t[j].Kill(666);
1.247 + CLOSE_AND_WAIT(t[j]);
1.248 + }
1.249 +
1.250 + test.Next(_L("Please wait while I close & create some undertakers"));
1.251 + u1.Close();
1.252 + u2.Close();
1.253 + r=u1.Create();
1.254 + test(r==KErrNone);
1.255 + r=u2.Create();
1.256 + test(r==KErrNone);
1.257 +
1.258 + test.Next(_L("Mark kernel heap"));
1.259 + __KHEAP_MARK;
1.260 +
1.261 + test.Next(_L("Create thread"));
1.262 + RThread threadx;
1.263 + r=threadx.Create(_L("Loopyx"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
1.264 + test(r==KErrNone);
1.265 + test.Next(_L("Resume thread"));
1.266 + threadx.Resume();
1.267 +
1.268 + test.Next(_L("Create undertaker"));
1.269 + TRequestStatus statx;
1.270 + TInt threadHandlex;
1.271 + RUndertaker ux;
1.272 + r=ux.Create();
1.273 + test(r==KErrNone);
1.274 + test.Next(_L("Logon to undertaker"));
1.275 + r=ux.Logon(statx,threadHandlex);
1.276 + test(r==KErrNone);
1.277 + test.Next(_L("Kill thread"));
1.278 + threadx.Kill(0x666);
1.279 + threadx.Close();
1.280 + User::WaitForRequest(statx);
1.281 + test(statx==KErrDied);
1.282 + test.Next(_L("Close thread"));
1.283 + RThread wx;
1.284 + wx.SetHandle(threadHandlex);
1.285 + CLOSE_AND_WAIT(wx);
1.286 +
1.287 + test.Next(_L("Close undertaker"));
1.288 + ux.Close();
1.289 +
1.290 + test.Next(_L("Check kernel heap"));
1.291 + __KHEAP_MARKEND;
1.292 + w1.Close();
1.293 + CLOSE_AND_WAIT(w2);
1.294 + keep1.Close();
1.295 + CLOSE_AND_WAIT(keep2);
1.296 + t[KNumThreads-1].Kill(666);
1.297 + CLOSE_AND_WAIT(t[KNumThreads-1]);
1.298 +
1.299 + test.Next(_L("Close RUndertakers"));
1.300 + u1.Close();
1.301 + u2.Close();
1.302 + test.End();
1.303 + }
1.304 +
1.305 +volatile TInt IFLAG;
1.306 +
1.307 +TInt InstructionThread(TAny* anInstruction)
1.308 + {
1.309 + __e32_atomic_store_ord32(&IFLAG, 1);
1.310 + RThread::Rendezvous(KErrNone);
1.311 + TInstruction what=(TInstruction)(TInt)anInstruction;
1.312 + if (what==EInstrPanic)
1.313 + User::Panic(_L("Hello"), KExitPanicNum);
1.314 + if (what==ENormal)
1.315 + return(KThreadReturnValue);
1.316 + User::After(500000);
1.317 + return(KErrNone);
1.318 + }
1.319 +
1.320 +TInt StartInstructionThread(RThread& aT, const TDesC& aName, TInt aInstruction, TOwnerType aOwnerType, TRequestStatus* aL, TRequestStatus* aR)
1.321 + {
1.322 + TInt r = aT.Create(aName, &InstructionThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)aInstruction, aOwnerType);
1.323 + if (r!=KErrNone)
1.324 + return r;
1.325 + if (aL)
1.326 + {
1.327 + aT.Logon(*aL);
1.328 + TInt s = aL->Int();
1.329 + test_Equal(s, KRequestPending);
1.330 + }
1.331 + if (aR)
1.332 + {
1.333 + aT.Rendezvous(*aR);
1.334 + TInt s = aR->Int();
1.335 + test_Equal(s, KRequestPending);
1.336 + aT.Resume();
1.337 + User::WaitForRequest(*aR);
1.338 + s = aR->Int();
1.339 + test_KErrNone(s);
1.340 + }
1.341 + return r;
1.342 + }
1.343 +
1.344 +
1.345 +LOCAL_D TInt test4Thread(TAny *aSem)
1.346 +//
1.347 +// Wait to be released on the semaphore.
1.348 +// Then release the semaphore.
1.349 +//
1.350 + {
1.351 +
1.352 + RSemaphore& sem=(*(RSemaphore*)aSem);
1.353 + sem.Wait();
1.354 + sem.Signal();
1.355 + return(KErrNone);
1.356 + }
1.357 +
1.358 +TInt BadPriority(TAny* aThread)
1.359 + {
1.360 + ((RThread*)aThread)->SetPriority(EPriorityNull);
1.361 + return KErrNone;
1.362 + }
1.363 +
1.364 +_LIT(KLitRomString,"RomStringRomStringRomStringRomStringRomStringRomStringRomString");
1.365 +
1.366 +LOCAL_C TInt BadFullNameThread(TAny* aPar)
1.367 + {
1.368 + RThread thread;
1.369 +
1.370 + switch ((TInt)aPar)
1.371 + {
1.372 + case 0:
1.373 + {
1.374 + HBufC* hBuf = HBufC::New(5);//Size 5 is not sufficient. thread.FullName should panic.
1.375 + test(NULL != hBuf);
1.376 + RBuf rBuf(hBuf);
1.377 + thread.FullName(rBuf);
1.378 + rBuf.Close();
1.379 + }
1.380 + return(KErrNone);
1.381 +
1.382 + case 1:
1.383 + {
1.384 + TPtr ptr((TText*)(KLitRomString.iBuf), KLitRomString.iTypeLength);
1.385 + // Passing descriptor whose data is in ROM. This may behave in different ways
1.386 + // on differrent platforms. Here, we just check that Kernel is safe.
1.387 + thread.FullName(ptr);
1.388 + }
1.389 + return(KErrNone);
1.390 + }
1.391 + return(KErrArgument);
1.392 + }
1.393 +
1.394 +
1.395 +LOCAL_D void test1()
1.396 +//
1.397 +// Test 1
1.398 +//
1.399 + {
1.400 +
1.401 + __UHEAP_MARK;
1.402 + RThread thread;
1.403 + TRequestStatus stat;
1.404 + TInt r;
1.405 +
1.406 + test.Start(_L("Close without create"));
1.407 + thread.Close();
1.408 +
1.409 + test.Next(_L("Create ENormal"));
1.410 + r = StartInstructionThread(thread, _L("Thread"), ENormal, EOwnerProcess, 0, 0);
1.411 + test_KErrNone(r);
1.412 +
1.413 + test.Next(_L("Test priorities"));
1.414 + test(thread.Priority()==EPriorityNormal);
1.415 + thread.SetPriority(EPriorityRealTime); // WINS will commute this to EPriorityMuchMore
1.416 +#if defined(__EPOC32__)
1.417 + test(thread.Priority()==EPriorityRealTime);
1.418 +#endif
1.419 + thread.SetPriority(EPriorityMuchMore);
1.420 + test(thread.Priority()==EPriorityMuchMore);
1.421 +// thread.SetPriority(EPriorityNull);
1.422 + RThread badThread;
1.423 + r = badThread.Create(_L("Bad Priority"),BadPriority,KDefaultStackSize,KHeapSize,KHeapSize,&thread);
1.424 + test(r==KErrNone);
1.425 + badThread.Logon(stat);
1.426 + test(stat==KRequestPending);
1.427 + badThread.Resume();
1.428 + User::WaitForRequest(stat);
1.429 + test(stat==EBadPriority);
1.430 + test(badThread.ExitCategory()==_L("KERN-EXEC"));
1.431 + test(badThread.ExitReason()==EBadPriority);
1.432 + test(badThread.ExitType()==EExitPanic);
1.433 + CLOSE_AND_WAIT(badThread);
1.434 + test(thread.Priority()==EPriorityMuchMore);
1.435 +
1.436 +#if defined(__EPOC32__)
1.437 + test.Next(_L("Test setting process priority from thread"));
1.438 + test(thread.ProcessPriority()==EPriorityForeground);
1.439 + thread.SetProcessPriority(EPriorityHigh);
1.440 + test(thread.ProcessPriority()==EPriorityHigh);
1.441 + test(RProcess().Priority()==EPriorityHigh);
1.442 + thread.SetProcessPriority(EPriorityForeground);
1.443 + test(thread.ProcessPriority()==EPriorityForeground);
1.444 + test(RProcess().Priority()==EPriorityForeground);
1.445 +#endif
1.446 +
1.447 + TBuf<0x100> name;
1.448 + test.Next(_L("Test thread name"));
1.449 + test(thread.Name()==_L("Thread"));
1.450 + test.Next(_L("Get owning process name"));
1.451 + RProcess p;
1.452 + test(thread.Process(p)==KErrNone);
1.453 + name=p.Name();
1.454 + name.Append(_L("::"));
1.455 + name.Append(thread.Name());
1.456 + test.Next(_L("Test fullname - via TFullName RHandleBase::FullName"));
1.457 + test(thread.FullName().CompareF(name)==0);
1.458 +
1.459 + test.Next(_L("Test fullname - via void RHandleBase::FullName(TDes& aName)"));
1.460 + HBufC* hBuf = HBufC::New(100);
1.461 + test(NULL != hBuf);
1.462 + TPtr ptr = hBuf->Des();
1.463 + thread.FullName(ptr);
1.464 + test(ptr.CompareF(name)==0);
1.465 + RBuf rBuf(hBuf);
1.466 + thread.FullName(rBuf);
1.467 + test(rBuf.CompareF(name)==0);
1.468 + rBuf.Close();
1.469 +
1.470 + test.Next(_L("Test void RHandleBase::FullName(TDes& aName) when aName is too short"));
1.471 + TInt aaa=badThread.Create(_L("BadFullNameThread1"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)0);
1.472 + test(aaa==KErrNone);
1.473 + badThread.Logon(stat);
1.474 + test(badThread.ExitType()==EExitPending);
1.475 + badThread.Resume();
1.476 + User::WaitForRequest(stat);
1.477 + test(badThread.ExitCategory()==_L("KERN-EXEC"));
1.478 + test(badThread.ExitReason()==EKUDesSetLengthOverflow);
1.479 + test(badThread.ExitType()==EExitPanic);
1.480 + CLOSE_AND_WAIT(badThread);
1.481 +
1.482 + test.Next(_L("Test void RHandleBase::FullName(TDes& aName) where aName has data in ROM "));
1.483 + aaa=badThread.Create(_L("BadFullNameThread2"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)1);
1.484 + test(aaa==KErrNone);
1.485 + badThread.Logon(stat);
1.486 + test(badThread.ExitType()==EExitPending);
1.487 + badThread.Resume();
1.488 + User::WaitForRequest(stat);
1.489 + test.Printf(_L("BadFullNameThread2 exited with ExitReason=%d and ExitType=%d\n"),badThread.ExitReason(),badThread.ExitType());
1.490 + CLOSE_AND_WAIT(badThread);
1.491 +
1.492 + test.Next(_L("Rename current thread"));
1.493 + test(User::RenameThread(_L("renamed"))==KErrNone);
1.494 + name=p.Name();
1.495 + name.Append(_L("::"));
1.496 + RThread me;
1.497 + name.Append(me.Name());
1.498 + test(me.Name()==_L("renamed"));
1.499 + test(me.FullName().CompareF(name)==0);
1.500 +
1.501 + test.Next(_L("Test running exit types"));
1.502 + test(thread.ExitType()==EExitPending);
1.503 + test(thread.ExitReason()==0);
1.504 + // no getters for iUserHeap and iFrame
1.505 + test(thread.ExitCategory()==KNullDesC);
1.506 +
1.507 + test.Next(_L("Test logging on"));
1.508 + thread.Logon(stat);
1.509 + RThread t;
1.510 + test(t.RequestCount()==0);
1.511 + test(stat==KRequestPending);
1.512 + r=thread.LogonCancel(stat); // this generates a signal
1.513 + test(r==KErrNone);
1.514 + test(stat==KErrNone);
1.515 + test(t.RequestCount()==1); // the request count is 1 due to the signal generated by LogonCancel
1.516 + test(thread.RequestCount()==0);
1.517 +
1.518 + test.Next(_L("Resuming thread"));
1.519 + thread.Resume();
1.520 + test.Next(_L("Absorb cancel"));
1.521 + User::WaitForRequest(stat);
1.522 + test.Next(_L("Test LogonCancel on dead thread is ok"));
1.523 + r=thread.LogonCancel(stat);
1.524 + test(r==KErrGeneral);
1.525 + test.Next(_L("Close thread"));
1.526 + CLOSE_AND_WAIT(thread);
1.527 + test.Next(_L("Close again"));
1.528 + thread.Close();
1.529 + thread.Close();
1.530 + thread.Close();
1.531 + thread.Close();
1.532 + __UHEAP_MARKEND;
1.533 + test.End();
1.534 + }
1.535 +
1.536 +
1.537 +LOCAL_D void test2(TOwnerType anOwnerType)
1.538 +//
1.539 +// Test 2
1.540 +//
1.541 + {
1.542 +
1.543 + __UHEAP_MARK;
1.544 + RThread thread;
1.545 + TRequestStatus stat;
1.546 + TRequestStatus rstat;
1.547 + TInt r;
1.548 +
1.549 + test.Start(_L("Run thread 10 times"));
1.550 + for (TInt xx=0;xx<10;xx++)
1.551 + {
1.552 + test.Printf(_L("\r%02d"),xx);
1.553 + r = StartInstructionThread(thread, _L("Thread1"), ENormal, anOwnerType, &stat, 0);
1.554 + test_KErrNone(r);
1.555 + thread.Resume();
1.556 + User::WaitForRequest(stat);
1.557 + CLOSE_AND_WAIT(thread);
1.558 + }
1.559 + test.Printf(_L("\n"));
1.560 +
1.561 + test.Next(_L("Panic within thread"));
1.562 + r = StartInstructionThread(thread, _L("Thread2"), EInstrPanic, anOwnerType, &stat, 0);
1.563 + test_KErrNone(r);
1.564 + test(thread.ExitType()==EExitPending);
1.565 + thread.Resume();
1.566 + User::WaitForRequest(stat);
1.567 + test(thread.ExitCategory()==_L("Hello"));
1.568 + test(thread.ExitReason()==KExitPanicNum);
1.569 + test(thread.ExitType()==EExitPanic);
1.570 + CLOSE_AND_WAIT(thread);
1.571 +
1.572 + test.Next(_L("Panic external to thread"));
1.573 + TInt ijk;
1.574 + TUint seed[2] = { 0xadf85458, 0 };
1.575 + TUint maxcount = 0;
1.576 + for (ijk=0; ijk<8192; ++ijk)
1.577 + {
1.578 + if (!(ijk&255))
1.579 + test.Printf(_L("%d\n"), ijk);
1.580 + r = StartInstructionThread(thread, _L("Thread3"), EWait, anOwnerType, &stat, 0);
1.581 + test_KErrNone(r);
1.582 + __e32_atomic_store_ord32(&IFLAG, 0);
1.583 + thread.Resume();
1.584 + thread.SetPriority(EPriorityMore);
1.585 + if (maxcount==0)
1.586 + {
1.587 + while (__e32_atomic_load_acq32(&IFLAG)==0 && --maxcount!=0)
1.588 + {
1.589 + }
1.590 + maxcount = 0u - maxcount;
1.591 + test.Printf(_L("maxcount=%u\n"), maxcount);
1.592 + }
1.593 + else
1.594 + {
1.595 + TUint random = Random(seed);
1.596 + random %= maxcount;
1.597 + ++random;
1.598 + while (__e32_atomic_load_acq32(&IFLAG)==0 && --random!=0)
1.599 + {
1.600 + }
1.601 + }
1.602 + thread.Panic(_L("panic"), 123);
1.603 + User::WaitForRequest(stat);
1.604 + test(thread.ExitCategory()==_L("panic"));
1.605 + test(thread.ExitReason()==123);
1.606 + test(thread.ExitType()==EExitPanic);
1.607 + CLOSE_AND_WAIT(thread);
1.608 + }
1.609 +
1.610 + test.Next(_L("Internal exit"));
1.611 + r = StartInstructionThread(thread, _L("Thread4"), ENormal, anOwnerType, &stat, 0);
1.612 + test_KErrNone(r);
1.613 + test(thread.ExitType()==EExitPending);
1.614 + thread.Resume();
1.615 + User::WaitForRequest(stat);
1.616 + test(thread.ExitCategory()==_L("Kill"));
1.617 + test(thread.ExitReason()==KThreadReturnValue);
1.618 + test(thread.ExitType()==EExitKill);
1.619 + CLOSE_AND_WAIT(thread);
1.620 +
1.621 + test.Next(_L("External terminate"));
1.622 + r = StartInstructionThread(thread, _L("Thread5"), EWait, anOwnerType, &stat, &rstat);
1.623 + test_KErrNone(r);
1.624 + test.Next(_L("Terminate"));
1.625 + thread.Terminate(KTerminationReason);
1.626 + test.Next(_L("Wait"));
1.627 + User::WaitForRequest(stat);
1.628 + test(thread.ExitCategory()==_L("Terminate"));
1.629 + test(thread.ExitReason()==KTerminationReason);
1.630 + test(thread.ExitType()==EExitTerminate);
1.631 + test.Next(_L("Close"));
1.632 + CLOSE_AND_WAIT(thread);
1.633 +
1.634 + test.Next(_L("External kill"));
1.635 + r = StartInstructionThread(thread, _L("Thread6"), EWait, anOwnerType, &stat, &rstat);
1.636 + test_KErrNone(r);
1.637 + thread.Suspend();
1.638 + thread.Resume();
1.639 + thread.Kill(KKillReason);
1.640 + User::WaitForRequest(stat);
1.641 + test(thread.ExitCategory()==_L("Kill"));
1.642 + test(thread.ExitReason()==KKillReason);
1.643 + test(thread.ExitType()==EExitKill);
1.644 + test.Next(_L("Kill again"));
1.645 + thread.Kill(KErrNone);
1.646 + thread.Kill(KErrNone);
1.647 + thread.Kill(KErrNone);
1.648 + CLOSE_AND_WAIT(thread);
1.649 + test.End();
1.650 + __UHEAP_MARKEND;
1.651 + }
1.652 +
1.653 +LOCAL_D void test3()
1.654 +//
1.655 +// Test 3.
1.656 +//
1.657 + {
1.658 +
1.659 + test.Start(_L("Read across thread"));
1.660 + TReadInfo info;
1.661 + TPtrC des1=_L("tdesc");
1.662 + info.tdesc=(&des1);
1.663 + TPtrC ptr1=_L("tptrc");
1.664 + info.tptrc=&ptr1;
1.665 + TBuf<0x20> tdes(_L("tdes"));
1.666 + info.tdes=&tdes;
1.667 + TBuf<0x20> tptrbuf(_L("tptr"));
1.668 + TPtr tptr((TText*)tptrbuf.Ptr(),tptrbuf.Length(),tptrbuf.MaxLength());
1.669 + info.tptr=&tptr;
1.670 + TBuf<0x20> hbufc(_L("hbufc"));
1.671 + HBufC *pH=hbufc.Alloc();
1.672 + test(pH!=NULL);
1.673 + info.hbufc=pH;
1.674 + TBufC<0x20> tbufc(_L("tbufc"));
1.675 + info.tbufc=&tbufc;
1.676 + TBuf<0x20> tbuf(_L("tbuf"));
1.677 + info.tbuf=&tbuf;
1.678 + TBufC<0x20> tptrdes(_L("tptrdes"));
1.679 + TPtr des=tptrdes.Des();
1.680 + info.tptrdes=&des;
1.681 + TBuf<0x10> b(_L("Hello"));
1.682 + info.anAddress=(&b);
1.683 + info.anAddress= info.anAddress; //prevents warning (var set but never used)
1.684 + delete pH;
1.685 + test.End();
1.686 + }
1.687 +
1.688 +LOCAL_D void test4()
1.689 +//
1.690 +// Test 4.
1.691 +//
1.692 + {
1.693 +
1.694 + test.Start(_L("Create sempahore"));
1.695 + RSemaphore sem;
1.696 + TInt r=sem.CreateLocal(0);
1.697 + test(r==KErrNone);
1.698 +//
1.699 + test.Next(_L("Create thread 1"));
1.700 + RThread t;
1.701 + r=t.Create(_L("Thread1"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
1.702 + test(r==KErrNone);
1.703 + t.Resume();
1.704 + t.Close();
1.705 +//
1.706 + test.Next(_L("Create thread 2"));
1.707 + r=t.Create(_L("Thread2"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
1.708 + test(r==KErrNone);
1.709 + t.Resume();
1.710 + t.Close();
1.711 +//
1.712 + test.Next(_L("Create thread 3"));
1.713 + r=t.Create(_L("Thread3"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
1.714 + test(r==KErrNone);
1.715 + t.Resume();
1.716 + t.Close();
1.717 +//
1.718 + test.Next(_L("Release threads"));
1.719 + sem.Signal(3);
1.720 +//
1.721 + test.Next(_L("Wait 1"));
1.722 + sem.Wait();
1.723 +//
1.724 + test.Next(_L("Wait 2"));
1.725 + sem.Wait();
1.726 +//
1.727 + test.Next(_L("Wait 2"));
1.728 + sem.Wait();
1.729 + sem.Close();
1.730 +//
1.731 + test.End();
1.732 + }
1.733 +
1.734 +TInt MinimalThread(TAny*)
1.735 +//
1.736 +// Minimal thread, used in test 5
1.737 +//
1.738 + {
1.739 + return(KErrNone);
1.740 + }
1.741 +
1.742 +LOCAL_D void test5()
1.743 +//
1.744 +// Test 5 - tests unclosed but completed threads
1.745 +//
1.746 + {
1.747 +
1.748 + test.Start(_L("Start thread"));
1.749 + RThread thread1;
1.750 + test(thread1.Create(_L("Test Thread1"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
1.751 + TRequestStatus stat1;
1.752 + thread1.Logon(stat1);
1.753 + thread1.Resume();
1.754 + User::WaitForRequest(stat1);
1.755 + test(thread1.ExitType()==EExitKill);
1.756 + // 'missing' thread1.Close();
1.757 +
1.758 + test.Next(_L("Start another thread"));
1.759 + RThread thread2;
1.760 + test(thread2.Create(_L("Test Thread2"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
1.761 + TRequestStatus stat2;
1.762 + thread2.Logon(stat2);
1.763 + thread2.Resume();
1.764 + User::WaitForRequest(stat2); //Goes wrong here in build 48
1.765 + test(thread2.ExitType()==EExitKill);
1.766 +
1.767 + test.Next(_L("Close both threads"));
1.768 + CLOSE_AND_WAIT(thread2);
1.769 + CLOSE_AND_WAIT(thread1);
1.770 +
1.771 + test.End();
1.772 + }
1.773 +
1.774 +LOCAL_D TInt test6Thread(TAny *anArg)
1.775 +//
1.776 +//
1.777 +//
1.778 + {
1.779 + ((RSemaphore*)anArg)->Wait();
1.780 + RThread t;
1.781 + RThread dup;
1.782 + dup.Duplicate(t);
1.783 + dup.Panic(_L("Test"),0);
1.784 +
1.785 + return KErrNone;
1.786 + }
1.787 +
1.788 +void test6()
1.789 +//
1.790 +// Test thread duplication
1.791 +//
1.792 + {
1.793 +
1.794 + test.Start(_L("Create thread"));
1.795 + RSemaphore sem;
1.796 + TInt r=sem.CreateLocal(0);
1.797 + test(r==KErrNone);
1.798 +
1.799 + RThread t;
1.800 + t.Create(_L("test6thread"),test6Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
1.801 + test.Next(_L("Resume thread"));
1.802 + TRequestStatus stat;
1.803 + t.Logon(stat);
1.804 + t.Resume();
1.805 + sem.Signal();
1.806 + User::WaitForRequest(stat);
1.807 + test.Next(_L("Close thread"));
1.808 + t.Close();
1.809 + sem.Close();
1.810 + test.End();
1.811 + }
1.812 +
1.813 +RSemaphore gsem;
1.814 +enum TThreadProgress { EBeforeStart, EStarted, EWaiting, EDoneWaiting, EFinished };
1.815 +TThreadProgress progress=EBeforeStart;
1.816 +LOCAL_D TInt test7thread(TAny * /*anArg*/)
1.817 +//
1.818 +//
1.819 +//
1.820 + {
1.821 +
1.822 + progress=EStarted;
1.823 + progress=EWaiting;
1.824 + gsem.Wait();
1.825 + progress=EDoneWaiting;
1.826 + gsem.Wait();
1.827 + progress=EFinished;
1.828 + return KErrNone;
1.829 + }
1.830 +
1.831 +void test7()
1.832 +//
1.833 +// Suspend/ Resume tests
1.834 +//
1.835 + {
1.836 +
1.837 + TInt r=gsem.CreateLocal(0);
1.838 + test(r==KErrNone);
1.839 + test.Start(_L("Create thread"));
1.840 + RThread t;
1.841 + r=t.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.842 + test(r==KErrNone);
1.843 + TRequestStatus stat;
1.844 + t.Logon(stat);
1.845 + test.Next(_L("Resume thread"));
1.846 + t.Resume();
1.847 + User::After(KWaitTime); // wait a bit;
1.848 + test.Next(_L("Make thread wait on a semaphore"));
1.849 + test(progress==EWaiting);
1.850 + test.Next(_L("Suspend waiting thread"));
1.851 + t.Suspend();
1.852 + test.Next(_L("Signal the semaphore"));
1.853 + gsem.Signal();
1.854 + User::After(KWaitTime);
1.855 + test.Next(_L("Test thread still suspended"));
1.856 + test(progress==EWaiting);
1.857 + test.Next(_L("resume thread"));
1.858 + t.Resume();
1.859 + test.Next(_L("Test the thread no longer waiting on the semaphore"));
1.860 + User::After(KWaitTime);
1.861 + test(progress==EDoneWaiting);
1.862 + test.Next(_L("Wait for thread to finish"));
1.863 + gsem.Signal();
1.864 + User::WaitForRequest(stat);
1.865 + test(stat==KErrNone);
1.866 + test(progress==EFinished);
1.867 + CLOSE_AND_WAIT(t);
1.868 +
1.869 + RThread tt;
1.870 + progress=EBeforeStart;
1.871 + test.Next(_L("Create Thread"));
1.872 + r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.873 + test(r==KErrNone);
1.874 + tt.Logon(stat);
1.875 + test.Next(_L("Suspend thread without starting it"));
1.876 + tt.Suspend();
1.877 + tt.Suspend();
1.878 + test.Next(_L("Resume and test suspend/resume balance"));
1.879 + tt.Resume();
1.880 + tt.Resume();
1.881 + User::After(KWaitTime);
1.882 + test(progress==EBeforeStart);
1.883 + tt.Resume();
1.884 + test.Next(_L("test thread is suspended on semaphore"));
1.885 + User::After(KWaitTime);
1.886 + test(progress==EWaiting);
1.887 + test.Next(_L("suspend thread"));
1.888 + tt.Suspend();
1.889 + tt.Suspend();
1.890 + test.Next(_L("resume thread"));
1.891 + tt.Resume();
1.892 + tt.Resume();
1.893 + test.Next(_L("test thread still suspended on semaphore"));
1.894 + User::After(KWaitTime);
1.895 + test(progress==EWaiting);
1.896 + test.Next(_L("Suspend, Suspend, Signal semaphore, Suspend"));
1.897 + tt.Suspend();
1.898 + tt.Suspend();
1.899 + gsem.Signal();
1.900 + tt.Suspend();
1.901 + test.Next(_L("test thread still suspended on semaphore"));
1.902 + User::After(KWaitTime);
1.903 + test(progress==EWaiting);
1.904 + test.Next(_L("Resume thread, checking suspend/resume balance"));
1.905 + tt.Resume();
1.906 + User::After(KWaitTime);
1.907 + test(progress==EWaiting);
1.908 + tt.Resume();
1.909 + User::After(KWaitTime);
1.910 + test(progress==EWaiting);
1.911 + tt.Resume();
1.912 + User::After(KWaitTime);
1.913 + test(progress==EDoneWaiting);
1.914 + test.Next(_L("Resume an executing thread"));
1.915 + tt.Resume();
1.916 + tt.Resume();
1.917 +// test.Next(_L("Suspend and check balance"));
1.918 +// tt.Suspend();
1.919 +// tt.Suspend();
1.920 + test.Next(_L("Wait for thread to finish"));
1.921 + gsem.Signal();
1.922 + User::After(KWaitTime);
1.923 + test(progress==EFinished);
1.924 + User::WaitForRequest(stat);
1.925 + CLOSE_AND_WAIT(tt);
1.926 +
1.927 +//
1.928 + test.Next(_L("Create Thread"));
1.929 + r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.930 + test(r==KErrNone);
1.931 + tt.Logon(stat);
1.932 + test.Next(_L("Resume"));
1.933 + tt.Resume();
1.934 + test.Next(_L("Hang thread on semaphore"));
1.935 + User::After(KWaitTime);
1.936 + test(progress==EWaiting);
1.937 + test.Next(_L("Suspend then Resume thread"));
1.938 + tt.Suspend();
1.939 + tt.Suspend();
1.940 + tt.Resume();
1.941 + User::After(KWaitTime);
1.942 + test(progress==EWaiting);
1.943 + tt.Resume();
1.944 + test.Next(_L("Check still hanging on semaphore"));
1.945 + User::After(KWaitTime);
1.946 + test(progress==EWaiting);
1.947 + test.Next(_L("Signal Semaphore"));
1.948 + gsem.Signal();
1.949 + test.Next(_L("Test thread executing again"));
1.950 + User::After(KWaitTime);
1.951 + test(progress==EDoneWaiting);
1.952 + test.Next(_L("Hang thread on another semaphore, and suspend"));
1.953 + tt.Suspend();
1.954 + test.Next(_L("Signal semaphore, and suspend again"));
1.955 + gsem.Signal();
1.956 + User::After(KWaitTime);
1.957 + test(progress==EDoneWaiting);
1.958 + tt.Suspend();
1.959 + test.Next(_L("Resume the thread"));
1.960 + tt.Resume();
1.961 + User::After(KWaitTime);
1.962 + test(progress==EDoneWaiting);
1.963 + tt.Resume();
1.964 + test.Next(_L("Wait for thread to finish"));
1.965 + User::After(KWaitTime);
1.966 + test(progress==EFinished);
1.967 + User::WaitForRequest(stat);
1.968 + CLOSE_AND_WAIT(tt);
1.969 + test.End();
1.970 + }
1.971 +
1.972 +#if 0
1.973 +RSemaphore Sem;
1.974 +LOCAL_D TInt test8thread(TAny* aPtr)
1.975 +//
1.976 +//
1.977 +//
1.978 + {
1.979 +
1.980 + typedef TBuf<0x20> TTestBuf;
1.981 + typedef volatile TTestBuf* TTestBufPtr;
1.982 + volatile TTestBufPtr& pB=*(volatile TTestBufPtr*)aPtr;
1.983 + if ((TUint)pB != 0xc90fdaa2)
1.984 + return KErrGeneral;
1.985 + Sem.Wait();
1.986 + TDesC* pD=(TDesC*)pB;
1.987 + test(*pD==_L("Everything's just hunky-dory"));
1.988 + delete (TTestBufPtr*)pB;
1.989 + __UHEAP_MARKEND;
1.990 + return KErrNone;
1.991 + }
1.992 +#endif
1.993 +
1.994 +void test8()
1.995 +//
1.996 +// Get Heap
1.997 +//
1.998 + {
1.999 + // !!! RThread::SetInitialParameter no longer exists
1.1000 +
1.1001 + /*
1.1002 + typedef TBuf<0x20> TTestBuf;
1.1003 + TTestBuf* buf=(TTestBuf*)0xc90fdaa2;
1.1004 +
1.1005 + test.Start(_L("Create thread"));
1.1006 + RThread thread;
1.1007 + TInt r=thread.Create(_L("test8thread"),test8thread,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1008 + test(r==KErrNone);
1.1009 + r=Sem.CreateLocal(0);
1.1010 + test(r==KErrNone);
1.1011 + test.Next(_L("Set parameter"));
1.1012 + r=thread.SetInitialParameter(&buf);
1.1013 + test(r==KErrNone);
1.1014 + TRequestStatus stat;
1.1015 + thread.Logon(stat);
1.1016 + thread.SetPriority(EPriorityMore);
1.1017 + test.Next(_L("Resume thread"));
1.1018 + thread.Resume();
1.1019 + test.Next(_L("Set initial parameter NULL"));
1.1020 + r=thread.SetInitialParameter(NULL);
1.1021 + test(thread.ExitType()==EExitPending);
1.1022 +
1.1023 + test.Next(_L("Get heap"));
1.1024 + RHeap* heap;
1.1025 + heap=thread.Heap();
1.1026 + test.Next(_L("Alloc inside heap"));
1.1027 + __RHEAP_MARK(heap);
1.1028 + buf=(TTestBuf*)heap->Alloc(sizeof(TTestBuf));
1.1029 + test(buf!=NULL);
1.1030 + new(buf) TTestBuf;
1.1031 + *buf=(_L("Everything's just hunky-dory"));
1.1032 +
1.1033 + Sem.Signal();
1.1034 + User::WaitForRequest(stat);
1.1035 + test(stat==KErrNone);
1.1036 + test(thread.ExitType()==EExitKill);
1.1037 + test(thread.ExitReason()==KErrNone);
1.1038 +
1.1039 + test.Next(_L("Close"));
1.1040 + thread.Close();
1.1041 + Sem.Close();
1.1042 + test.End();
1.1043 + */
1.1044 + }
1.1045 +
1.1046 +TInt Thread(TAny* /*aAny*/)
1.1047 + {
1.1048 +
1.1049 + RTest test(_L("Any old thread"));
1.1050 + test.Next(_L("Find remote thread"));
1.1051 + // find the main thread
1.1052 + TFullName name;
1.1053 + name=RProcess().Name();
1.1054 + name.Append(_L("::*"));
1.1055 + TFindThread ft;
1.1056 + ft.Find(name);
1.1057 + TInt r=ft.Next(name);
1.1058 + test(r==KErrNone);
1.1059 + RThread t;
1.1060 + t.Open(ft);
1.1061 +
1.1062 + t.Close();
1.1063 + return KErrNone;
1.1064 + }
1.1065 +
1.1066 +void test9()
1.1067 + {
1.1068 +
1.1069 + test.Start(_L("Test create a NULL TPtr"));
1.1070 + TPtr p(NULL, 10, 10);
1.1071 + test.Next(_L("Create and run remote thread"));
1.1072 + RThread t;
1.1073 + TInt r;
1.1074 + r=t.Create(_L("Any Old Thread"), Thread, 0x2000, 0x2000, 0x2000, (TAny *)&p);
1.1075 + test(KErrNone==r);
1.1076 + TRequestStatus stat;
1.1077 + t.Logon(stat);
1.1078 + t.Resume();
1.1079 + test.Next(_L("Wait for thread to complete"));
1.1080 + User::WaitForRequest(stat);
1.1081 + test(stat==KErrNone);
1.1082 + test(t.ExitCategory()==_L("Kill"));
1.1083 + test(t.ExitReason()==KErrNone);
1.1084 + test(t.ExitType()==EExitKill);
1.1085 + CLOSE_AND_WAIT(t);
1.1086 + test.End();
1.1087 + }
1.1088 +
1.1089 +
1.1090 +
1.1091 +TInt FoghornLeghorn(TAny* aMutex)
1.1092 +//
1.1093 +// Thread function
1.1094 +//
1.1095 + {
1.1096 +
1.1097 + ((RSemaphore*)aMutex)->Wait();
1.1098 + RThread thread;
1.1099 + TInt r=thread.Create(_L("I say * boy"),FoghornLeghorn,KDefaultStackSize,NULL,aMutex);
1.1100 + test(r==KErrBadName);
1.1101 + return KErrNone;
1.1102 + }
1.1103 +
1.1104 +void testOpen()
1.1105 + {
1.1106 +
1.1107 + test.Start(_L("Create Foghorn Leghorn"));
1.1108 + RSemaphore fogMut;
1.1109 + fogMut.CreateLocal(0);
1.1110 + RThread foghorn;
1.1111 + TInt r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1.1112 + test(r==KErrNone);
1.1113 + test.Next(_L("Logon"));
1.1114 + TRequestStatus stat;
1.1115 + foghorn.Logon(stat);
1.1116 + test(stat==KRequestPending);
1.1117 + test.Next(_L("Resume Foghorn Leghorn"));
1.1118 + foghorn.Resume();
1.1119 + test.Next(_L("Get full name"));
1.1120 + TFindThread find(_L("*Foghorn Leghorn"));
1.1121 + TFullName name;
1.1122 + r=find.Next(name);
1.1123 + test(r==KErrNone);
1.1124 + test.Next(_L("Open another handle using full name"));
1.1125 + RThread leghorn;
1.1126 + r=leghorn.Open(name);
1.1127 + test(r==KErrNone);
1.1128 + test.Next(_L("Kill using second handle"));
1.1129 + leghorn.Kill(34523);
1.1130 + User::WaitForRequest(stat);
1.1131 + test(stat==34523);
1.1132 + test.Next(_L("Close handles"));
1.1133 + foghorn.Close();
1.1134 + CLOSE_AND_WAIT(leghorn);
1.1135 +
1.1136 + test.Next(_L("Again! - Create Foghorn Leghorn"));
1.1137 + r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1.1138 + test(r==KErrNone);
1.1139 + test.Next(_L("Logon"));
1.1140 + foghorn.Logon(stat);
1.1141 + test(stat==KRequestPending);
1.1142 + test.Next(_L("Resume Foghorn Leghorn"));
1.1143 + foghorn.Resume();
1.1144 + test.Next(_L("Get full name"));
1.1145 + find.Find(_L("*Foghorn Leghorn"));
1.1146 + r=find.Next(name);
1.1147 + test(r==KErrNone);
1.1148 + test.Next(_L("Open another handle using full name"));
1.1149 + r=leghorn.Open(name);
1.1150 + test(r==KErrNone);
1.1151 + test.Next(_L("Kill using second handle"));
1.1152 + leghorn.Kill(67857);
1.1153 + User::WaitForRequest(stat);
1.1154 + test(stat==67857);
1.1155 + test.Next(_L("Close handles"));
1.1156 + foghorn.Close();
1.1157 + CLOSE_AND_WAIT(leghorn);
1.1158 +
1.1159 + test.Next(_L("Create Foghorn Leghorn"));
1.1160 + r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1.1161 + test(r==KErrNone);
1.1162 + test.Next(_L("Logon"));
1.1163 + foghorn.Logon(stat);
1.1164 + test(stat==KRequestPending);
1.1165 + test.Next(_L("Resume Foghorn Leghorn"));
1.1166 + foghorn.Resume();
1.1167 + test.Next(_L("Now close it"));
1.1168 + foghorn.Close();
1.1169 +
1.1170 + test.Next(_L("Get full name"));
1.1171 + find.Find(_L("*Foghorn Leghorn"));
1.1172 + r=find.Next(name);
1.1173 + test(r==KErrNone);
1.1174 + test.Next(_L("Open using full name"));
1.1175 + r=leghorn.Open(name);
1.1176 + test(r==KErrNone);
1.1177 + test.Next(_L("Kill"));
1.1178 + leghorn.Kill(67857);
1.1179 + User::WaitForRequest(stat);
1.1180 + test(stat==67857);
1.1181 + test.Next(_L("Close"));
1.1182 + CLOSE_AND_WAIT(leghorn);
1.1183 +
1.1184 + test.Next(_L("Start and get it to try to start a new thread"));
1.1185 + r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1.1186 + test(r==KErrNone);
1.1187 + foghorn.Logon(stat);
1.1188 + test(stat==KRequestPending);
1.1189 + foghorn.Resume();
1.1190 + fogMut.Signal();
1.1191 + User::WaitForRequest(stat);
1.1192 + test(stat==KErrNone);
1.1193 + test(foghorn.ExitCategory()==_L("Kill"));
1.1194 + test(foghorn.ExitReason()==KErrNone);
1.1195 + test(foghorn.ExitType()==EExitKill);
1.1196 + test.Next(_L("Close"));
1.1197 + CLOSE_AND_WAIT(foghorn);
1.1198 + fogMut.Close();
1.1199 +
1.1200 + test.End();
1.1201 + }
1.1202 +
1.1203 +TInt Bunny(TAny*)
1.1204 +//
1.1205 +// Thread function
1.1206 +//
1.1207 + {
1.1208 +
1.1209 + FOREVER
1.1210 + ;
1.1211 + }
1.1212 +
1.1213 +void testReuse()
1.1214 + {
1.1215 +
1.1216 + test.Start(_L("Create thread with duplicate name"));
1.1217 + RThread thread;
1.1218 + TFullName name=thread.Name();
1.1219 + TInt r=thread.Create(name,Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1220 + test(r==KErrAlreadyExists);
1.1221 +// thread.Resume(); handle will be invalid since create failed
1.1222 + test.Next(_L("Create with a good name"));
1.1223 + r=thread.Create(_L("Bugs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1224 + test(r==KErrNone);
1.1225 + TRequestStatus stat;
1.1226 + thread.Logon(stat);
1.1227 + test.Next(_L("Resume"));
1.1228 + thread.Resume();
1.1229 + test.Next(_L("Kill"));
1.1230 + thread.Kill(15);
1.1231 + User::WaitForRequest(stat);
1.1232 + test(stat==15);
1.1233 + CLOSE_AND_WAIT(thread);
1.1234 +
1.1235 + test.End();
1.1236 + }
1.1237 +
1.1238 +
1.1239 +TInt HongKongPhooey(TAny * /*aAny*/)
1.1240 + {
1.1241 +
1.1242 + RMutex m;
1.1243 + m.OpenGlobal(_L("Test Mutex"));
1.1244 + m.Wait();
1.1245 + User::Panic(_L("Hello"),900);
1.1246 + return KErrNone;
1.1247 + }
1.1248 +
1.1249 +void testReleaseMutex()
1.1250 +//
1.1251 +// Bug HA-187
1.1252 +//
1.1253 + {
1.1254 + TInt r;
1.1255 + test.Start(_L("Create a global Mutex"));
1.1256 + RMutex m;
1.1257 + r=m.CreateGlobal(_L("Test Mutex"));
1.1258 + test.Next(_L("Create a thread"));
1.1259 + RThread number1SuperGuy;
1.1260 + r=number1SuperGuy.Create(_L("Hong Kong Phooey"), HongKongPhooey, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1261 + test(r==KErrNone);
1.1262 + TRequestStatus s;
1.1263 + number1SuperGuy.Logon(s);
1.1264 + test.Next(_L("Resume Thread"));
1.1265 + number1SuperGuy.Resume();
1.1266 + test.Next(_L("Wait on Mutex and Panic"));
1.1267 + User::WaitForRequest(s);
1.1268 + test(number1SuperGuy.ExitType()==EExitPanic);
1.1269 + test(number1SuperGuy.ExitCategory()==_L("Hello"));
1.1270 + test(number1SuperGuy.ExitReason()==900);
1.1271 + User::After(100000); // wait a bit for everything to be cleaned up
1.1272 + m.Wait();
1.1273 + test.Next(_L("Close everything"));
1.1274 + m.Close();
1.1275 + CLOSE_AND_WAIT(number1SuperGuy);
1.1276 + test.End();
1.1277 + }
1.1278 +
1.1279 +void testId()
1.1280 + {
1.1281 +
1.1282 + test.Start(_L("Try to open nonexistant thread by ID"));
1.1283 + RThread thread;
1.1284 + TInt r=thread.Open(*(TThreadId*)&KMaxTUint);
1.1285 + test(r==KErrNotFound);
1.1286 + test.Next(_L("Get thread ID"));
1.1287 + r=thread.Create(_L("Buster Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1288 + test(r==KErrNone);
1.1289 + TThreadId id=thread.Id();
1.1290 + TThreadId id2=thread.Id();
1.1291 + test(id==id2);
1.1292 + RThread thread2;
1.1293 + r=thread2.Create(_L("Babs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.1294 + test(r==KErrNone);
1.1295 + id2=thread2.Id();
1.1296 + test(id!=id2);
1.1297 + test(*(TUint*)&id+1==*(TUint*)&id2);
1.1298 + test.Next(_L("Open by ID"));
1.1299 + TRequestStatus stat;
1.1300 + thread.Logon(stat);
1.1301 + thread.Kill(54624);
1.1302 + User::WaitForRequest(stat);
1.1303 + test(stat==54624);
1.1304 + thread.Close();
1.1305 + r=thread.Open(id2);
1.1306 + test(r==KErrNone);
1.1307 + test(thread.Name()==_L("Babs Bunny"));
1.1308 + test(thread.FullName()==thread2.FullName());
1.1309 + thread2.Close();
1.1310 + id=thread.Id();
1.1311 + test(id==id2);
1.1312 + thread.Logon(stat);
1.1313 + thread.Kill(88863);
1.1314 + User::WaitForRequest(stat);
1.1315 + test(stat==88863);
1.1316 + CLOSE_AND_WAIT(thread);
1.1317 +
1.1318 + test.End();
1.1319 + }
1.1320 +
1.1321 +struct SCreateInfo
1.1322 + {
1.1323 + TInt iStackSize;
1.1324 + TInt iMinHeapSize;
1.1325 + TInt iMaxHeapSize;
1.1326 + };
1.1327 +
1.1328 +TInt BadCreation(TAny* aCreateInfo)
1.1329 + {
1.1330 + SCreateInfo& info=*((SCreateInfo*)aCreateInfo);
1.1331 + RThread thread;
1.1332 + thread.Create(_L("Won't work"),Bunny,info.iStackSize,info.iMinHeapSize,info.iMaxHeapSize,NULL);
1.1333 + return KErrNone;
1.1334 + }
1.1335 +
1.1336 +void testCreate()
1.1337 + {
1.1338 + test.Start(_L("Negative stack size"));
1.1339 + RThread thread;
1.1340 + TRequestStatus stat;
1.1341 + TInt r;
1.1342 + {
1.1343 + SCreateInfo info={-1,0x1000,0x1000};
1.1344 + r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
1.1345 + test(KErrNone==r);
1.1346 + thread.Logon(stat);
1.1347 + thread.Resume();
1.1348 + User::WaitForRequest(stat);
1.1349 + test(stat==EThrdStackSizeNegative);
1.1350 + test(thread.ExitType()==EExitPanic);
1.1351 + test(thread.ExitReason()==EThrdStackSizeNegative);
1.1352 + test(thread.ExitCategory()==_L("USER"));
1.1353 + CLOSE_AND_WAIT(thread);
1.1354 + }
1.1355 +//
1.1356 + test.Next(_L("Negative heap min size"));
1.1357 + {
1.1358 + SCreateInfo info={0x1000,-1,0x1000};
1.1359 + r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
1.1360 + test(KErrNone==r);
1.1361 + thread.Logon(stat);
1.1362 + thread.Resume();
1.1363 + User::WaitForRequest(stat);
1.1364 + test(stat==EThrdHeapMinTooSmall);
1.1365 + test(thread.ExitType()==EExitPanic);
1.1366 + test(thread.ExitReason()==EThrdHeapMinTooSmall);
1.1367 + test(thread.ExitCategory()==_L("USER"));
1.1368 + CLOSE_AND_WAIT(thread);
1.1369 + }
1.1370 + test.Next(_L("Negative heap max size"));
1.1371 + {
1.1372 + SCreateInfo info={0x1000,0x1000,-1};
1.1373 + r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
1.1374 + test(KErrNone==r);
1.1375 + thread.Logon(stat);
1.1376 + thread.Resume();
1.1377 + User::WaitForRequest(stat);
1.1378 + test(stat==EThrdHeapMaxLessThanMin);
1.1379 + test(thread.ExitType()==EExitPanic);
1.1380 + test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
1.1381 + test(thread.ExitCategory()==_L("USER"));
1.1382 + CLOSE_AND_WAIT(thread);
1.1383 + }
1.1384 + test.Next(_L("heap max size < heap min size"));
1.1385 + {
1.1386 + SCreateInfo info={0x1000,0x2001,0x1000};
1.1387 + r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
1.1388 + test(KErrNone==r);
1.1389 + thread.Logon(stat);
1.1390 + thread.Resume();
1.1391 + User::WaitForRequest(stat);
1.1392 + test(stat==EThrdHeapMaxLessThanMin);
1.1393 + test(thread.ExitType()==EExitPanic);
1.1394 + test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
1.1395 + test(thread.ExitCategory()==_L("USER"));
1.1396 + CLOSE_AND_WAIT(thread);
1.1397 + }
1.1398 + test.Next(_L("Little min heap size"));
1.1399 + {
1.1400 + SCreateInfo info={0x1000,KMinHeapSize-1,0x1000};
1.1401 + r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
1.1402 + test(KErrNone==r);
1.1403 + thread.Logon(stat);
1.1404 + thread.Resume();
1.1405 + User::WaitForRequest(stat);
1.1406 + test(stat==EThrdHeapMinTooSmall);
1.1407 + test(thread.ExitType()==EExitPanic);
1.1408 + test(thread.ExitReason()==EThrdHeapMinTooSmall);
1.1409 + test(thread.ExitCategory()==_L("USER"));
1.1410 + CLOSE_AND_WAIT(thread);
1.1411 + }
1.1412 + test.End();
1.1413 + }
1.1414 +
1.1415 +TInt StackInfoThread(TAny*)
1.1416 + {
1.1417 + TInt a;
1.1418 + RThread::Rendezvous((TInt)&a); // Complete rendezvous using address of 'a' which is on the stack
1.1419 + return 0;
1.1420 + }
1.1421 +
1.1422 +void testThreadStackInfo()
1.1423 + {
1.1424 + // Check the info about the current thread's stack
1.1425 + RThread thread;
1.1426 + TThreadStackInfo info;
1.1427 + TInt r = thread.StackInfo(info);
1.1428 + test(r==KErrNone);
1.1429 + TLinAddr a = (TLinAddr)&info;
1.1430 + test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
1.1431 + test(a<=info.iBase);
1.1432 + test(a>=info.iLimit);
1.1433 + test(info.iExpandLimit<=info.iLimit);
1.1434 +
1.1435 + // Create another thread
1.1436 + r=thread.Create(_L("StackInfoThread"),StackInfoThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL);
1.1437 + test(r==KErrNone);
1.1438 + thread.SetPriority(EPriorityLess);
1.1439 +
1.1440 + // Resume thread and wait for it to run
1.1441 + TRequestStatus stat;
1.1442 + thread.Rendezvous(stat);
1.1443 + thread.Resume();
1.1444 + User::WaitForRequest(stat);
1.1445 +
1.1446 + // Test getting stack info of another thread
1.1447 + r = thread.StackInfo(info);
1.1448 + test(r==KErrNone);
1.1449 + a = stat.Int(); // a = an address on the threads stack
1.1450 + test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
1.1451 + test(a<=info.iBase);
1.1452 + test(a>=info.iLimit);
1.1453 + test(info.iExpandLimit<=info.iLimit);
1.1454 +
1.1455 + // Let thread run to end
1.1456 + thread.Logon(stat);
1.1457 + User::WaitForRequest(stat);
1.1458 + test(stat.Int()==0);
1.1459 + }
1.1460 +
1.1461 +GLDEF_C TInt E32Main()
1.1462 +//
1.1463 +// Main
1.1464 +//
1.1465 + {
1.1466 +
1.1467 + // don't want just in time debugging as we trap panics
1.1468 + TBool justInTime=User::JustInTime();
1.1469 + User::SetJustInTime(EFalse);
1.1470 +
1.1471 + test.Title();
1.1472 + __UHEAP_MARK;
1.1473 +
1.1474 +
1.1475 + TFullName name;
1.1476 + name=RThread().Name();
1.1477 +
1.1478 + test.Start(_L("Test threads"));
1.1479 +
1.1480 + test.Next(_L("Test 1"));
1.1481 + test1();
1.1482 +
1.1483 + test.Next(_L("Test create"));
1.1484 + testCreate();
1.1485 +
1.1486 + test.Next(_L("Test RUndertaker"));
1.1487 + testUndertaker(EOwnerProcess);
1.1488 +
1.1489 + test.Next(_L("Test2"));
1.1490 + test2(EOwnerProcess);
1.1491 + User::SetJustInTime(justInTime);
1.1492 + test.Next(_L("Test3"));
1.1493 + test3();
1.1494 + test.Next(_L("Test4"));
1.1495 + test4();
1.1496 + test.Next(_L("Completed but unclosed thread"));
1.1497 + User::SetJustInTime(EFalse);
1.1498 + test5();
1.1499 + User::SetJustInTime(justInTime);
1.1500 + test.Next(_L("Suspend/Resume"));
1.1501 + test7();
1.1502 + test.Next(_L("Testing thread duplication"));
1.1503 + User::SetJustInTime(EFalse);
1.1504 + test6();
1.1505 + User::SetJustInTime(justInTime);
1.1506 + test.Next(_L("Get thread's heap"));
1.1507 + test8();
1.1508 + test.Next(_L("Test read NULL remotely (HA-178)"));
1.1509 + test9();
1.1510 + test.Next(_L("Test Open(aFullName)"));
1.1511 + testOpen();
1.1512 + test.Next(_L("Test Reuse after a failed create"));
1.1513 + testReuse();
1.1514 + test.Next(_L("Test thread releases Mutex (HA-178)"));
1.1515 + User::SetJustInTime(EFalse);
1.1516 + testReleaseMutex();
1.1517 + User::SetJustInTime(justInTime);
1.1518 + test.Next(_L("Test Thread ID"));
1.1519 + testId();
1.1520 + test.Next(_L("Test RThread::StackInfo"));
1.1521 + testThreadStackInfo();
1.1522 + test.End();
1.1523 + __UHEAP_MARKEND;
1.1524 + return(KErrNone);
1.1525 + }
1.1526 +
1.1527 +
1.1528 +