os/kernelhwsrv/kerneltest/e32test/system/t_condvar.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\system\t_condvar.cpp
sl@0
    15
// Overview:
sl@0
    16
// Test the use of the RCondVar & RMutex classes.
sl@0
    17
// API Information:
sl@0
    18
// RCondVar, RMutex
sl@0
    19
// Details:
sl@0
    20
// - Create some local conditional variables and mutexes and verify results
sl@0
    21
// are as expected.
sl@0
    22
// - Create a test thread that waits on conditional variables and mutexes, 
sl@0
    23
// append some items on an array, signal the conditional variable and mutex,
sl@0
    24
// the thread then counts the number of items on the array and passes the 
sl@0
    25
// result back to the main process. Verify results are as expected. Repeat
sl@0
    26
// with different array data.
sl@0
    27
// - Verify that a RCondVar::Wait() panics when the thread does not hold the
sl@0
    28
// specified mutex (mutex not locked).
sl@0
    29
// - Test using two mutexes with 1 conditional variable, append some items to 
sl@0
    30
// an array, verify results from the thread are as expected. 
sl@0
    31
// - Create a second thread with higher priority, perform tests similar to
sl@0
    32
// above, verify results are as expected.
sl@0
    33
// - Verify the thread timeout values are as expected.
sl@0
    34
// - Create global conditional variables and global mutexes, using two threads
sl@0
    35
// test the RCondVar::Signal() and RMutex::Wait() results are as expected.
sl@0
    36
// - Test various combinations of creating a thread, suspending and killing it
sl@0
    37
// and signalling a conditional variable and mutex. Verify results are as
sl@0
    38
// expected.
sl@0
    39
// - Create a secondary process along with a global chunk, conditional variable 
sl@0
    40
// and mutex. Signal the conditional variable and verify the results are as 
sl@0
    41
// expected.
sl@0
    42
// - Using two threads, benchmark the number of conditional variable/mutex Signal
sl@0
    43
// and Wait iterations that can be completed per second.
sl@0
    44
// Platforms/Drives/Compatibility:
sl@0
    45
// All.
sl@0
    46
// Assumptions/Requirement/Pre-requisites:
sl@0
    47
// Failures and causes:
sl@0
    48
// Base Port information:
sl@0
    49
// 
sl@0
    50
//
sl@0
    51
sl@0
    52
#include <e32std.h>
sl@0
    53
#include <e32std_private.h>
sl@0
    54
#include <e32svr.h>
sl@0
    55
#include <e32test.h>
sl@0
    56
#include <e32ldr.h>
sl@0
    57
#include <e32def.h>
sl@0
    58
#include <e32def_private.h>
sl@0
    59
sl@0
    60
RTest test(_L("T_CONDVAR"));
sl@0
    61
RMutex M1;
sl@0
    62
RMutex M2;
sl@0
    63
RCondVar CV1;
sl@0
    64
RCondVar CV2;
sl@0
    65
sl@0
    66
#define __TRACE_LINE__	test.Printf(_L("Line %d\n"),__LINE__)
sl@0
    67
sl@0
    68
struct SThreadData
sl@0
    69
	{
sl@0
    70
	SThreadData();
sl@0
    71
	RMutex iM;
sl@0
    72
	RCondVar iV;
sl@0
    73
	RArray<TInt>* iA;
sl@0
    74
	TInt iTotal;
sl@0
    75
	TInt iInnerLoops;
sl@0
    76
	TInt iOuterLoops;
sl@0
    77
	TInt iTimeoutMs;
sl@0
    78
	TInt iTimeouts;
sl@0
    79
	TInt iBadCount;
sl@0
    80
	};
sl@0
    81
sl@0
    82
struct SThreadData2
sl@0
    83
	{
sl@0
    84
	SThreadData2();
sl@0
    85
	const TText* iMutexName;
sl@0
    86
	const TText* iCondVarName;
sl@0
    87
	TInt iInnerLoops;
sl@0
    88
	};
sl@0
    89
sl@0
    90
SThreadData::SThreadData()
sl@0
    91
	{
sl@0
    92
	memset(this, 0, sizeof(*this));
sl@0
    93
	}
sl@0
    94
sl@0
    95
SThreadData2::SThreadData2()
sl@0
    96
	{
sl@0
    97
	memset(this, 0, sizeof(*this));
sl@0
    98
	}
sl@0
    99
sl@0
   100
TInt Thread0(TAny*)
sl@0
   101
	{
sl@0
   102
	return CV1.Wait(M1);
sl@0
   103
	}
sl@0
   104
sl@0
   105
TInt Thread1(TAny* a)
sl@0
   106
	{
sl@0
   107
	TUint32 t1, t2;
sl@0
   108
	SThreadData& d = *(SThreadData*)a;
sl@0
   109
	TInt r = KErrNone;
sl@0
   110
	TInt i = 0;
sl@0
   111
	d.iM.Wait();
sl@0
   112
	FOREVER
sl@0
   113
		{
sl@0
   114
		while (d.iA->Count()<=i && r==KErrNone)
sl@0
   115
			{
sl@0
   116
			t1 = User::NTickCount();
sl@0
   117
			if (d.iTimeoutMs)
sl@0
   118
				r = d.iV.TimedWait(d.iM, d.iTimeoutMs*1000);
sl@0
   119
			else
sl@0
   120
				r = d.iV.Wait(d.iM);
sl@0
   121
			t2 = User::NTickCount();
sl@0
   122
			++d.iInnerLoops;
sl@0
   123
			if (r == KErrTimedOut)
sl@0
   124
				{
sl@0
   125
				++d.iTimeouts;
sl@0
   126
				TInt iv = (TInt)(t2-t1);
sl@0
   127
				if (iv<d.iTimeoutMs)
sl@0
   128
					++d.iBadCount;
sl@0
   129
				r = KErrNone;
sl@0
   130
				}
sl@0
   131
			}
sl@0
   132
		if (r != KErrNone)
sl@0
   133
			break;
sl@0
   134
		++d.iOuterLoops;
sl@0
   135
		TInt c = d.iA->Count();
sl@0
   136
		for (; i<c; ++i)
sl@0
   137
			d.iTotal += (*d.iA)[i];
sl@0
   138
		}
sl@0
   139
	return r;
sl@0
   140
	}
sl@0
   141
sl@0
   142
TInt Thread2(TAny* a)
sl@0
   143
	{
sl@0
   144
	TUint32 t1, t2;
sl@0
   145
	SThreadData& d = *(SThreadData*)a;
sl@0
   146
	TInt r = KErrNone;
sl@0
   147
	d.iM.Wait();
sl@0
   148
	RThread::Rendezvous(KErrNone);
sl@0
   149
	while (r==KErrNone)
sl@0
   150
		{
sl@0
   151
		t1 = User::NTickCount();
sl@0
   152
		if (d.iTimeoutMs)
sl@0
   153
			r = d.iV.TimedWait(d.iM, d.iTimeoutMs*1000);
sl@0
   154
		else
sl@0
   155
			r = d.iV.Wait(d.iM);
sl@0
   156
		t2 = User::NTickCount();
sl@0
   157
		++d.iInnerLoops;
sl@0
   158
		if (r == KErrTimedOut)
sl@0
   159
			{
sl@0
   160
			++d.iTimeouts;
sl@0
   161
			TInt iv = (TInt)(t2-t1);
sl@0
   162
			if (iv<d.iTimeoutMs)
sl@0
   163
				++d.iBadCount;
sl@0
   164
			r = KErrNone;
sl@0
   165
			}
sl@0
   166
		}
sl@0
   167
	return r;
sl@0
   168
	}
sl@0
   169
sl@0
   170
TInt Thread3(TAny* a)
sl@0
   171
	{
sl@0
   172
	SThreadData2& d = *(SThreadData2*)a;
sl@0
   173
	RMutex m;
sl@0
   174
	RCondVar cv;
sl@0
   175
	TInt r = m.OpenGlobal(TPtrC(d.iMutexName), EOwnerThread);
sl@0
   176
	if (r!=KErrNone)
sl@0
   177
		return r;
sl@0
   178
	r = cv.OpenGlobal(TPtrC(d.iCondVarName), EOwnerThread);
sl@0
   179
	if (r!=KErrNone)
sl@0
   180
		return r;
sl@0
   181
	m.Wait();
sl@0
   182
	while (r==KErrNone)
sl@0
   183
		{
sl@0
   184
		r = cv.Wait(m);
sl@0
   185
		++d.iInnerLoops;
sl@0
   186
		}
sl@0
   187
	return r;
sl@0
   188
	}
sl@0
   189
sl@0
   190
TInt Thread4(TAny* a)
sl@0
   191
	{
sl@0
   192
	volatile TInt& count = *(volatile TInt*)a;
sl@0
   193
	TInt r = KErrNone;
sl@0
   194
	M2.Wait();
sl@0
   195
	while (r==KErrNone)
sl@0
   196
		{
sl@0
   197
		r = CV2.Wait(M2);
sl@0
   198
		++count;
sl@0
   199
		}
sl@0
   200
	return r;
sl@0
   201
	}
sl@0
   202
sl@0
   203
TInt Thread5(TAny*)
sl@0
   204
	{
sl@0
   205
	FOREVER
sl@0
   206
		{
sl@0
   207
		M2.Wait();
sl@0
   208
		CV2.Signal();
sl@0
   209
		M2.Signal();
sl@0
   210
		}
sl@0
   211
	}
sl@0
   212
sl@0
   213
void RunBench()
sl@0
   214
	{
sl@0
   215
	test.Next(_L("Benchmark"));
sl@0
   216
	RThread t4, t5;
sl@0
   217
	TInt count = 0;
sl@0
   218
	TInt r = t4.Create(KNullDesC, &Thread4, 0x1000, 0x1000, 0x1000, &count);
sl@0
   219
	test(r==KErrNone);
sl@0
   220
	t4.SetPriority(EPriorityLess);
sl@0
   221
	r = t5.Create(KNullDesC, &Thread5, 0x1000, 0x1000, 0x1000, NULL);
sl@0
   222
	test(r==KErrNone);
sl@0
   223
	t5.SetPriority(EPriorityMuchLess);
sl@0
   224
	t4.Resume();
sl@0
   225
	t5.Resume();
sl@0
   226
	User::After(500000);
sl@0
   227
	TInt initc = count;
sl@0
   228
	User::After(5000000);
sl@0
   229
	TInt finalc = count;
sl@0
   230
	test.Printf(_L("%d iterations per second\n"), (finalc-initc)/5);
sl@0
   231
	t4.Kill(0);
sl@0
   232
	t5.Kill(0);
sl@0
   233
	CLOSE_AND_WAIT(t4);
sl@0
   234
	CLOSE_AND_WAIT(t5);
sl@0
   235
	}
sl@0
   236
sl@0
   237
void CreateThread2(RThread& aThread, SThreadData& aData, TThreadPriority aPri)
sl@0
   238
	{
sl@0
   239
	TInt r = aThread.Create(KNullDesC, &Thread2, 0x1000, 0x1000, 0x1000, &aData);
sl@0
   240
	test(r==KErrNone);
sl@0
   241
	aThread.SetPriority(aPri);
sl@0
   242
	TRequestStatus s;
sl@0
   243
	aThread.Rendezvous(s);
sl@0
   244
	test(s==KRequestPending);
sl@0
   245
	aThread.Resume();
sl@0
   246
	User::WaitForRequest(s);
sl@0
   247
	test(s==KErrNone);
sl@0
   248
	test(aThread.ExitType()==EExitPending);
sl@0
   249
	aData.iM.Wait();
sl@0
   250
	}
sl@0
   251
sl@0
   252
void KillThread2(RThread& aThread)
sl@0
   253
	{
sl@0
   254
	TRequestStatus s;
sl@0
   255
	aThread.Logon(s);
sl@0
   256
	test(s==KRequestPending);
sl@0
   257
	aThread.Terminate(0);
sl@0
   258
	User::WaitForRequest(s);
sl@0
   259
	test(aThread.ExitType()==EExitTerminate);
sl@0
   260
	test(aThread.ExitReason()==0);
sl@0
   261
	test(s==0);
sl@0
   262
	CLOSE_AND_WAIT(aThread);
sl@0
   263
	}
sl@0
   264
sl@0
   265
void AppendToArray(SThreadData& aD, TInt aCount, ...)
sl@0
   266
	{
sl@0
   267
	VA_LIST list;
sl@0
   268
	VA_START(list,aCount);
sl@0
   269
	aD.iM.Wait();
sl@0
   270
	while(--aCount>=0)
sl@0
   271
		{
sl@0
   272
		test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
sl@0
   273
		}
sl@0
   274
	aD.iV.Signal();
sl@0
   275
	aD.iM.Signal();
sl@0
   276
	}
sl@0
   277
sl@0
   278
void AppendToArrayB(SThreadData& aD, TInt aCount, ...)
sl@0
   279
	{
sl@0
   280
	VA_LIST list;
sl@0
   281
	VA_START(list,aCount);
sl@0
   282
	aD.iM.Wait();
sl@0
   283
	while(--aCount>=0)
sl@0
   284
		{
sl@0
   285
		test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
sl@0
   286
		}
sl@0
   287
	aD.iV.Broadcast();
sl@0
   288
	aD.iM.Signal();
sl@0
   289
	}
sl@0
   290
sl@0
   291
void AppendToArrayB2(SThreadData& aD, TInt aCount, ...)
sl@0
   292
	{
sl@0
   293
	VA_LIST list;
sl@0
   294
	VA_START(list,aCount);
sl@0
   295
	aD.iM.Wait();
sl@0
   296
	while(--aCount>=0)
sl@0
   297
		{
sl@0
   298
		test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
sl@0
   299
		}
sl@0
   300
	aD.iM.Signal();
sl@0
   301
	aD.iV.Broadcast();
sl@0
   302
	}
sl@0
   303
sl@0
   304
void Thread2Test()
sl@0
   305
	{
sl@0
   306
	test.Next(_L("Thread2Test"));
sl@0
   307
	RCondVar cv2;
sl@0
   308
	RMutex m3;
sl@0
   309
	TInt r = cv2.CreateLocal();
sl@0
   310
	test(r==KErrNone);
sl@0
   311
	r = m3.CreateLocal();
sl@0
   312
	test(r==KErrNone);
sl@0
   313
	SThreadData d1;
sl@0
   314
	d1.iM = m3;
sl@0
   315
	d1.iV = cv2;
sl@0
   316
	RThread t1;
sl@0
   317
sl@0
   318
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   319
	cv2.Signal();
sl@0
   320
	m3.Signal();
sl@0
   321
	User::After(100000);
sl@0
   322
	test(d1.iInnerLoops == 1);
sl@0
   323
	KillThread2(t1);
sl@0
   324
sl@0
   325
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   326
	KillThread2(t1);
sl@0
   327
	m3.Signal();
sl@0
   328
	test(d1.iInnerLoops == 1);
sl@0
   329
sl@0
   330
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   331
	m3.Signal();
sl@0
   332
	User::After(10000);
sl@0
   333
	KillThread2(t1);
sl@0
   334
	test(d1.iInnerLoops == 1);
sl@0
   335
sl@0
   336
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   337
	cv2.Signal();
sl@0
   338
	User::After(10000);
sl@0
   339
	KillThread2(t1);
sl@0
   340
	m3.Signal();
sl@0
   341
	test(d1.iInnerLoops == 1);
sl@0
   342
sl@0
   343
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   344
	t1.Suspend();
sl@0
   345
	KillThread2(t1);
sl@0
   346
	m3.Signal();
sl@0
   347
	test(d1.iInnerLoops == 1);
sl@0
   348
sl@0
   349
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   350
	User::After(10000);
sl@0
   351
	t1.Suspend();
sl@0
   352
	KillThread2(t1);
sl@0
   353
	m3.Signal();
sl@0
   354
	test(d1.iInnerLoops == 1);
sl@0
   355
sl@0
   356
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   357
	cv2.Signal();
sl@0
   358
	t1.Suspend();
sl@0
   359
	KillThread2(t1);
sl@0
   360
	m3.Signal();
sl@0
   361
	test(d1.iInnerLoops == 1);
sl@0
   362
sl@0
   363
	CreateThread2(t1, d1, EPriorityLess);
sl@0
   364
	cv2.Signal();
sl@0
   365
	User::After(10000);
sl@0
   366
	t1.Suspend();
sl@0
   367
	KillThread2(t1);
sl@0
   368
	m3.Signal();
sl@0
   369
	test(d1.iInnerLoops == 1);
sl@0
   370
sl@0
   371
	cv2.Close();
sl@0
   372
	m3.Close();
sl@0
   373
	}
sl@0
   374
sl@0
   375
const TText* KMutex1Name = _S("mtx1");
sl@0
   376
const TText* KMutex2Name = _S("mtx2");
sl@0
   377
const TText* KCondVar1Name = _S("cv1");
sl@0
   378
const TText* KCondVar2Name = _S("cv2");
sl@0
   379
sl@0
   380
void TestGlobal()
sl@0
   381
	{
sl@0
   382
	test.Next(_L("Test Global"));
sl@0
   383
	RMutex mg1, mg2;
sl@0
   384
	RCondVar cvg1, cvg2;
sl@0
   385
	TInt r = mg1.CreateGlobal(TPtrC(KMutex1Name));
sl@0
   386
	test(r==KErrNone);
sl@0
   387
	r = mg2.CreateGlobal(TPtrC(KMutex2Name));
sl@0
   388
	test(r==KErrNone);
sl@0
   389
	r = cvg1.CreateGlobal(TPtrC(KCondVar1Name));
sl@0
   390
	test(r==KErrNone);
sl@0
   391
	r = cvg2.CreateGlobal(TPtrC(KCondVar2Name));
sl@0
   392
	test(r==KErrNone);
sl@0
   393
	SThreadData2 d1, d2;
sl@0
   394
	d1.iMutexName = KMutex1Name;
sl@0
   395
	d1.iCondVarName = KCondVar1Name;
sl@0
   396
	d2.iMutexName = KMutex2Name;
sl@0
   397
	d2.iCondVarName = KCondVar2Name;
sl@0
   398
sl@0
   399
	RThread t1, t2;
sl@0
   400
	r = t1.Create(KNullDesC, &Thread3, 0x1000, 0x1000, 0x1000, &d1);
sl@0
   401
	test(r==KErrNone);
sl@0
   402
	t1.SetPriority(EPriorityMore);
sl@0
   403
	TRequestStatus s1;
sl@0
   404
	t1.Logon(s1);
sl@0
   405
	t1.Resume();
sl@0
   406
	r = t2.Create(KNullDesC, &Thread3, 0x1000, 0x1000, 0x1000, &d2);
sl@0
   407
	test(r==KErrNone);
sl@0
   408
	t2.SetPriority(EPriorityMore);
sl@0
   409
	TRequestStatus s2;
sl@0
   410
	t2.Logon(s2);
sl@0
   411
	t2.Resume();
sl@0
   412
sl@0
   413
	test(s1==KRequestPending);
sl@0
   414
	test(s2==KRequestPending);
sl@0
   415
	test(d1.iInnerLoops == 0);
sl@0
   416
	test(d2.iInnerLoops == 0);
sl@0
   417
	cvg1.Signal();
sl@0
   418
	test(d1.iInnerLoops == 1);
sl@0
   419
	test(d2.iInnerLoops == 0);
sl@0
   420
	cvg2.Signal();
sl@0
   421
	test(d1.iInnerLoops == 1);
sl@0
   422
	test(d2.iInnerLoops == 1);
sl@0
   423
sl@0
   424
	cvg1.Close();
sl@0
   425
	cvg2.Close();
sl@0
   426
	test(s1==KRequestPending);
sl@0
   427
	test(s2==KRequestPending);
sl@0
   428
	test(d1.iInnerLoops == 1);
sl@0
   429
	test(d2.iInnerLoops == 1);
sl@0
   430
sl@0
   431
	t1.Kill(0);
sl@0
   432
	t2.Kill(0);
sl@0
   433
	User::WaitForRequest(s1);
sl@0
   434
	User::WaitForRequest(s2);
sl@0
   435
	test(t1.ExitType()==EExitKill);
sl@0
   436
	test(t1.ExitReason()==0);
sl@0
   437
	test(t2.ExitType()==EExitKill);
sl@0
   438
	test(t2.ExitReason()==0);
sl@0
   439
	CLOSE_AND_WAIT(t1);
sl@0
   440
	CLOSE_AND_WAIT(t2);
sl@0
   441
	r = cvg1.OpenGlobal(TPtrC(KCondVar1Name));
sl@0
   442
	test(r==KErrNotFound);
sl@0
   443
	test(cvg1.Handle()==0);
sl@0
   444
	mg1.Close();
sl@0
   445
	mg2.Close();
sl@0
   446
	}
sl@0
   447
sl@0
   448
void TestSecondaryProcess()
sl@0
   449
	{
sl@0
   450
	test.Next(_L("Test Secondary Process"));
sl@0
   451
sl@0
   452
	RProcess p;
sl@0
   453
	RChunk c;
sl@0
   454
	RMutex m;
sl@0
   455
	RCondVar cv;
sl@0
   456
sl@0
   457
	//cancel lazy dll unloading
sl@0
   458
	RLoader loader;
sl@0
   459
	TInt r = loader.Connect();
sl@0
   460
	test(r==KErrNone);
sl@0
   461
	r = loader.CancelLazyDllUnload();
sl@0
   462
	test(r==KErrNone);
sl@0
   463
	loader.Close();
sl@0
   464
sl@0
   465
	r = c.CreateGlobal(KNullDesC, 0x1000, 0x1000);
sl@0
   466
	test(r==KErrNone);
sl@0
   467
	volatile TInt& x = *(volatile TInt*)c.Base();
sl@0
   468
	x = 0;
sl@0
   469
	r = m.CreateGlobal(KNullDesC);
sl@0
   470
	test(r==KErrNone);
sl@0
   471
	r = cv.CreateGlobal(KNullDesC);
sl@0
   472
	test(r==KErrNone);
sl@0
   473
	r = p.Create(RProcess().FileName(), KNullDesC);
sl@0
   474
	test(r==KErrNone);
sl@0
   475
	p.SetPriority(EPriorityHigh);
sl@0
   476
	r = p.SetParameter(1, cv);
sl@0
   477
	test(r==KErrNone);
sl@0
   478
	r = p.SetParameter(2, m);
sl@0
   479
	test(r==KErrNone);
sl@0
   480
	r = p.SetParameter(3, c);
sl@0
   481
	test(r==KErrNone);
sl@0
   482
	TRequestStatus s;
sl@0
   483
	p.Logon(s);
sl@0
   484
	p.Resume();
sl@0
   485
	test(s==KRequestPending);
sl@0
   486
	test(x==0);
sl@0
   487
	TInt i;
sl@0
   488
	for (i=0; i<10; ++i)
sl@0
   489
		{
sl@0
   490
		cv.Signal();
sl@0
   491
		test(x == i+1);
sl@0
   492
		}
sl@0
   493
	cv.Close();
sl@0
   494
	test(s==KRequestPending);
sl@0
   495
	test(x==10);
sl@0
   496
	p.Terminate(0);
sl@0
   497
	User::WaitForRequest(s);
sl@0
   498
	test(p.ExitType()==EExitTerminate);
sl@0
   499
	test(p.ExitReason()==0);
sl@0
   500
	CLOSE_AND_WAIT(p);
sl@0
   501
	m.Close();
sl@0
   502
	c.Close();
sl@0
   503
	}
sl@0
   504
sl@0
   505
TInt SecondaryProcess(RCondVar aCV)
sl@0
   506
	{
sl@0
   507
	RDebug::Print(_L("SecProc"));
sl@0
   508
	RMutex mp;
sl@0
   509
	RChunk cp;
sl@0
   510
	TInt r = mp.Open(2);
sl@0
   511
	if (r!=KErrNone)
sl@0
   512
		return r;
sl@0
   513
	r = cp.Open(3);
sl@0
   514
	if (r!=KErrNone)
sl@0
   515
		return r;
sl@0
   516
	volatile TInt& x = *(volatile TInt*)cp.Base();
sl@0
   517
	mp.Wait();
sl@0
   518
	r = KErrNone;
sl@0
   519
	while (r==KErrNone)
sl@0
   520
		{
sl@0
   521
		r = aCV.Wait(mp);
sl@0
   522
		++x;
sl@0
   523
		RDebug::Print(_L("SecProc r=%d x=%d"), r, x);
sl@0
   524
		}
sl@0
   525
	return r;
sl@0
   526
	}
sl@0
   527
sl@0
   528
TInt E32Main()
sl@0
   529
	{
sl@0
   530
	__KHEAP_MARK;
sl@0
   531
	__UHEAP_MARK;
sl@0
   532
sl@0
   533
	TInt r;
sl@0
   534
	RCondVar cvp;
sl@0
   535
	r = cvp.Open(1);
sl@0
   536
	if (r==KErrNone)
sl@0
   537
		return SecondaryProcess(cvp);
sl@0
   538
	test.Title();
sl@0
   539
	test.Start(_L("Create condition variable"));
sl@0
   540
	r = CV1.CreateLocal();
sl@0
   541
	test(r==KErrNone);
sl@0
   542
	r = CV2.CreateLocal();
sl@0
   543
	test(r==KErrNone);
sl@0
   544
sl@0
   545
	test.Next(_L("Signal with no-one waiting"));
sl@0
   546
	CV1.Signal();
sl@0
   547
sl@0
   548
	test.Next(_L("Broadcast with no-one waiting"));
sl@0
   549
	CV1.Broadcast();
sl@0
   550
sl@0
   551
	test.Next(_L("Create mutexes"));
sl@0
   552
	r = M1.CreateLocal();
sl@0
   553
	test(r==KErrNone);
sl@0
   554
	r = M2.CreateLocal();
sl@0
   555
	test(r==KErrNone);
sl@0
   556
sl@0
   557
	RArray<TInt> array;
sl@0
   558
	SThreadData d0;
sl@0
   559
	d0.iM = M2;
sl@0
   560
	d0.iV = CV1;
sl@0
   561
	d0.iA = &array;
sl@0
   562
	test.Next(_L("Create thread to use mutex 2"));
sl@0
   563
	RThread t0;
sl@0
   564
	r = t0.Create(KNullDesC, &Thread1, 0x1000, 0x1000, 0x1000, &d0);
sl@0
   565
	test(r==KErrNone);
sl@0
   566
	t0.SetPriority(EPriorityMore);
sl@0
   567
	TRequestStatus s0;
sl@0
   568
	t0.Logon(s0);
sl@0
   569
	t0.Resume();
sl@0
   570
	__TRACE_LINE__;
sl@0
   571
	AppendToArray(d0, 1, 4);
sl@0
   572
	test(d0.iTotal==4);
sl@0
   573
	__TRACE_LINE__;
sl@0
   574
	AppendToArray(d0, 2, -3, 17);
sl@0
   575
	test(d0.iTotal==18);
sl@0
   576
	t0.Terminate(11);
sl@0
   577
	User::WaitForRequest(s0);
sl@0
   578
	test(t0.ExitType()==EExitTerminate);
sl@0
   579
	test(t0.ExitReason()==11);
sl@0
   580
	CLOSE_AND_WAIT(t0);
sl@0
   581
	array.Reset();
sl@0
   582
sl@0
   583
	SThreadData d;
sl@0
   584
	d.iM = M1;
sl@0
   585
	d.iV = CV1;
sl@0
   586
	d.iA = &array;
sl@0
   587
	test.Next(_L("Create thread to use mutex 1"));
sl@0
   588
	RThread t;
sl@0
   589
	r = t.Create(KNullDesC, &Thread1, 0x1000, 0x1000, 0x1000, &d);
sl@0
   590
	test(r==KErrNone);
sl@0
   591
	t.SetPriority(EPriorityMore);
sl@0
   592
	TRequestStatus s;
sl@0
   593
	t.Logon(s);
sl@0
   594
	t.Resume();
sl@0
   595
sl@0
   596
	test.Next(_L("Test wait with mutex unlocked"));
sl@0
   597
	r = t0.Create(KNullDesC, &Thread0, 0x1000, 0x1000, 0x1000, NULL);
sl@0
   598
	test(r==KErrNone);
sl@0
   599
	t0.SetPriority(EPriorityMore);
sl@0
   600
	t0.Logon(s0);
sl@0
   601
	TBool jit = User::JustInTime();
sl@0
   602
	User::SetJustInTime(EFalse);
sl@0
   603
	t0.Resume();
sl@0
   604
	User::WaitForRequest(s0);
sl@0
   605
	User::SetJustInTime(jit);
sl@0
   606
	test(t0.ExitType()==EExitPanic);
sl@0
   607
	test(t0.ExitCategory()==_L("KERN-EXEC"));
sl@0
   608
	test(t0.ExitReason()==ECondVarWaitMutexNotLocked);
sl@0
   609
	CLOSE_AND_WAIT(t0);
sl@0
   610
sl@0
   611
	test.Next(_L("Test trying to use two mutexes with 1 condition variable"));
sl@0
   612
	M2.Wait();
sl@0
   613
	r = CV1.Wait(M2);
sl@0
   614
	M2.Signal();
sl@0
   615
	test(r==KErrInUse);
sl@0
   616
sl@0
   617
	test(d.iTotal==0);
sl@0
   618
	__TRACE_LINE__;
sl@0
   619
	AppendToArray(d, 1, 3);
sl@0
   620
	test(d.iTotal==3);
sl@0
   621
	__TRACE_LINE__;
sl@0
   622
	AppendToArray(d, 2, 3, 19);
sl@0
   623
	test(d.iTotal==25);
sl@0
   624
	__TRACE_LINE__;
sl@0
   625
	AppendToArray(d, 4, 15, -1, -2, -30);
sl@0
   626
	test(d.iTotal==7);
sl@0
   627
	test(d.iInnerLoops==3);
sl@0
   628
	test(d.iOuterLoops==3);
sl@0
   629
	__TRACE_LINE__;
sl@0
   630
	t.Suspend();
sl@0
   631
	__TRACE_LINE__;
sl@0
   632
	t.Resume();
sl@0
   633
	test(d.iTotal==7);
sl@0
   634
	test(d.iInnerLoops==4);
sl@0
   635
	test(d.iOuterLoops==3);
sl@0
   636
	__TRACE_LINE__;
sl@0
   637
	t.SetPriority(EPriorityLess);
sl@0
   638
	test(d.iTotal==7);
sl@0
   639
	test(d.iInnerLoops==4);
sl@0
   640
	test(d.iOuterLoops==3);
sl@0
   641
	__TRACE_LINE__;
sl@0
   642
	t.SetPriority(EPriorityMore);
sl@0
   643
	test(d.iTotal==7);
sl@0
   644
	test(d.iInnerLoops==5);
sl@0
   645
	test(d.iOuterLoops==3);
sl@0
   646
	__TRACE_LINE__;
sl@0
   647
	t.Suspend();
sl@0
   648
	__TRACE_LINE__;
sl@0
   649
	AppendToArray(d, 1, 4);
sl@0
   650
	test(d.iTotal==7);
sl@0
   651
	test(d.iInnerLoops==5);
sl@0
   652
	test(d.iOuterLoops==3);
sl@0
   653
	__TRACE_LINE__;
sl@0
   654
	t.Resume();
sl@0
   655
	test(d.iTotal==11);
sl@0
   656
	test(d.iInnerLoops==6);
sl@0
   657
	test(d.iOuterLoops==4);
sl@0
   658
sl@0
   659
	SThreadData d2;
sl@0
   660
	d2.iM = M1;
sl@0
   661
	d2.iV = CV1;
sl@0
   662
	d2.iA = &array;
sl@0
   663
sl@0
   664
	test.Next(_L("Create 2nd thread"));
sl@0
   665
	RThread t2;
sl@0
   666
	r = t2.Create(KNullDesC, &Thread1, 0x1000, NULL, &d2);
sl@0
   667
	test(r==KErrNone);
sl@0
   668
	t2.SetPriority(EPriorityMuchMore);
sl@0
   669
	TRequestStatus s2;
sl@0
   670
	t2.Logon(s2);
sl@0
   671
	__TRACE_LINE__;
sl@0
   672
	t2.Resume();
sl@0
   673
sl@0
   674
	test(d2.iTotal == 11);
sl@0
   675
	test(d2.iInnerLoops == 0);
sl@0
   676
	test(d2.iOuterLoops == 1);
sl@0
   677
	__TRACE_LINE__;
sl@0
   678
	AppendToArray(d, 2, 9, 10);
sl@0
   679
	test(d2.iTotal == 30);
sl@0
   680
	test(d2.iInnerLoops == 1);
sl@0
   681
	test(d2.iOuterLoops == 2);
sl@0
   682
	test(d.iTotal==11);
sl@0
   683
	test(d.iInnerLoops==6);
sl@0
   684
	test(d.iOuterLoops==4);
sl@0
   685
	__TRACE_LINE__;
sl@0
   686
	AppendToArrayB(d, 2, 20, 30);
sl@0
   687
	test(d2.iTotal == 80);
sl@0
   688
	test(d2.iInnerLoops == 2);
sl@0
   689
	test(d2.iOuterLoops == 3);
sl@0
   690
	test(d.iTotal == 80);
sl@0
   691
	test(d.iInnerLoops == 7);
sl@0
   692
	test(d.iOuterLoops == 5);
sl@0
   693
	__TRACE_LINE__;
sl@0
   694
	AppendToArrayB2(d, 2, -10, -6);
sl@0
   695
	test(d2.iTotal == 64);
sl@0
   696
	test(d2.iInnerLoops == 3);
sl@0
   697
	test(d2.iOuterLoops == 4);
sl@0
   698
	test(d.iTotal == 64);
sl@0
   699
	test(d.iInnerLoops == 8);
sl@0
   700
	test(d.iOuterLoops == 6);
sl@0
   701
	__TRACE_LINE__;
sl@0
   702
	t2.Suspend();
sl@0
   703
	__TRACE_LINE__;
sl@0
   704
	AppendToArray(d, 2, -8, -8);
sl@0
   705
	test(d2.iTotal == 64);
sl@0
   706
	test(d2.iInnerLoops == 3);
sl@0
   707
	test(d2.iOuterLoops == 4);
sl@0
   708
	test(d.iTotal == 48);
sl@0
   709
	test(d.iInnerLoops == 9);
sl@0
   710
	test(d.iOuterLoops == 7);
sl@0
   711
	__TRACE_LINE__;
sl@0
   712
	t2.Resume();
sl@0
   713
	test(d2.iTotal == 48);
sl@0
   714
	test(d2.iInnerLoops == 4);
sl@0
   715
	test(d2.iOuterLoops == 5);
sl@0
   716
	test(d.iTotal == 48);
sl@0
   717
	test(d.iInnerLoops == 9);
sl@0
   718
	test(d.iOuterLoops == 7);
sl@0
   719
sl@0
   720
	// test timeouts
sl@0
   721
	d.iTimeoutMs = 1000;
sl@0
   722
	__TRACE_LINE__;
sl@0
   723
	t.Suspend();
sl@0
   724
	__TRACE_LINE__;
sl@0
   725
	t.Resume();
sl@0
   726
	test(d2.iTotal == 48);
sl@0
   727
	test(d2.iInnerLoops == 4);
sl@0
   728
	test(d2.iOuterLoops == 5);
sl@0
   729
	test(d2.iTimeouts == 0);
sl@0
   730
	test(d.iTotal == 48);
sl@0
   731
	test(d.iInnerLoops == 10);
sl@0
   732
	test(d.iOuterLoops == 7);
sl@0
   733
	test(d.iTimeouts == 0);
sl@0
   734
	test(array.Append(1)==0);
sl@0
   735
	TInt nt = 0;
sl@0
   736
	do	{
sl@0
   737
		if (d.iTimeouts > nt)
sl@0
   738
			{
sl@0
   739
			test(d.iTimeouts-nt == 1);
sl@0
   740
			nt = d.iTimeouts;
sl@0
   741
			test.Printf(_L("Timeout %d\n"), nt);
sl@0
   742
			test(d2.iTotal == 48);
sl@0
   743
			test(d2.iInnerLoops == 4);
sl@0
   744
			test(d2.iOuterLoops == 5);
sl@0
   745
			test(d2.iTimeouts == 0);
sl@0
   746
			test(d.iTotal == 48+nt);
sl@0
   747
			test(d.iInnerLoops == 10+nt);
sl@0
   748
			test(d.iOuterLoops == 7+nt);
sl@0
   749
			test(array.Append(1)==0);
sl@0
   750
			}
sl@0
   751
		} while (nt<10);
sl@0
   752
sl@0
   753
	d.iTimeoutMs = 0;
sl@0
   754
	AppendToArrayB(d, 0);
sl@0
   755
	test(d2.iTotal == 59);
sl@0
   756
	test(d2.iInnerLoops == 5);
sl@0
   757
	test(d2.iOuterLoops == 6);
sl@0
   758
	test(d2.iTimeouts == 0);
sl@0
   759
	test(d.iTotal == 59);
sl@0
   760
	test(d.iInnerLoops == 21);
sl@0
   761
	test(d.iOuterLoops == 18);
sl@0
   762
	test(d.iTimeouts == 10);
sl@0
   763
sl@0
   764
	__TRACE_LINE__;
sl@0
   765
	t.SetPriority(EPriorityLess);
sl@0
   766
	__TRACE_LINE__;
sl@0
   767
	AppendToArrayB(d, 1, 11);
sl@0
   768
	test(d2.iTotal == 70);
sl@0
   769
	test(d2.iInnerLoops == 6);
sl@0
   770
	test(d2.iOuterLoops == 7);
sl@0
   771
	test(d2.iTimeouts == 0);
sl@0
   772
	test(d.iTotal == 59);
sl@0
   773
	test(d.iInnerLoops == 21);
sl@0
   774
	test(d.iOuterLoops == 18);
sl@0
   775
	test(d.iTimeouts == 10);
sl@0
   776
	User::After(50000);
sl@0
   777
	test(d2.iTotal == 70);
sl@0
   778
	test(d2.iInnerLoops == 6);
sl@0
   779
	test(d2.iOuterLoops == 7);
sl@0
   780
	test(d2.iTimeouts == 0);
sl@0
   781
	test(d.iTotal == 70);
sl@0
   782
	test(d.iInnerLoops == 22);
sl@0
   783
	test(d.iOuterLoops == 19);
sl@0
   784
	test(d.iTimeouts == 10);
sl@0
   785
sl@0
   786
sl@0
   787
sl@0
   788
	__TRACE_LINE__;
sl@0
   789
	CV1.Close();
sl@0
   790
	User::WaitForRequest(s);
sl@0
   791
	test(t.ExitType()==EExitKill);
sl@0
   792
	test(t.ExitReason()==KErrGeneral);
sl@0
   793
	User::WaitForRequest(s2);
sl@0
   794
	test(t2.ExitType()==EExitKill);
sl@0
   795
	test(t2.ExitReason()==KErrGeneral);
sl@0
   796
	CLOSE_AND_WAIT(t);
sl@0
   797
	CLOSE_AND_WAIT(t2);
sl@0
   798
sl@0
   799
sl@0
   800
	M1.Close();
sl@0
   801
sl@0
   802
	TestGlobal();
sl@0
   803
sl@0
   804
	Thread2Test();
sl@0
   805
sl@0
   806
	TestSecondaryProcess();
sl@0
   807
sl@0
   808
	RunBench();
sl@0
   809
	M2.Close();
sl@0
   810
	CV2.Close();
sl@0
   811
	array.Close();
sl@0
   812
sl@0
   813
	test.End();
sl@0
   814
	test.Close();
sl@0
   815
sl@0
   816
	__UHEAP_MARKEND;
sl@0
   817
	__KHEAP_MARKEND;
sl@0
   818
	return KErrNone;
sl@0
   819
	}
sl@0
   820