|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\defrag\d_testramdefrag.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 //#define DEBUG_VER // Uncomment for tracing |
|
19 |
|
20 #include "platform.h" |
|
21 #include <kernel/kern_priv.h> |
|
22 #include <kernel/cache.h> |
|
23 #include "t_ramdefrag.h" |
|
24 |
|
25 // |
|
26 // Class definitions |
|
27 // |
|
28 const TInt KMajorVersionNumber=0; |
|
29 const TInt KMinorVersionNumber=1; |
|
30 const TInt KBuildVersionNumber=1; |
|
31 |
|
32 |
|
33 const TInt KDefragCompleteThreadPriority = 27; |
|
34 _LIT(KDefragCompleteThread,"DefragCompleteThread"); |
|
35 |
|
36 class DRamDefragFuncTestFactory : public DLogicalDevice |
|
37 { |
|
38 public: |
|
39 |
|
40 DRamDefragFuncTestFactory(); |
|
41 ~DRamDefragFuncTestFactory(); |
|
42 virtual TInt Install(); |
|
43 virtual void GetCaps(TDes8& aDes) const; |
|
44 virtual TInt Create(DLogicalChannelBase*& aChannel); |
|
45 |
|
46 TDynamicDfcQue* iDfcQ; |
|
47 }; |
|
48 |
|
49 class DRamDefragFuncTestChannel : public DLogicalChannelBase |
|
50 { |
|
51 public: |
|
52 DRamDefragFuncTestChannel(TDfcQue* aDfcQ); |
|
53 |
|
54 DRamDefragFuncTestChannel(); |
|
55 ~DRamDefragFuncTestChannel(); |
|
56 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); |
|
57 virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); |
|
58 |
|
59 TInt FreeAllFixedPages(); |
|
60 TInt AllocFixedPages(TInt aNumPages); |
|
61 TInt AllocFixedArray(TInt aNumPages); |
|
62 TInt AllocateFixed2(TInt aNumPages); |
|
63 TInt GetAllocDiff(TUint aNumPages); |
|
64 TInt FreeAllFixedPagesRead(); |
|
65 TInt AllocFixedPagesWrite(TInt aNumPages); |
|
66 TInt ZoneAllocContiguous(TUint aZoneID, TUint aNumBytes); |
|
67 TInt ZoneAllocContiguous(TUint* aZoneIdList, TUint aZoneIdCount, TUint aNumBytes); |
|
68 TInt ZoneAllocDiscontiguous(TUint aZoneID, TInt aNumPages); |
|
69 TInt ZoneAllocDiscontiguous(TUint* aZoneIdList, TUint aZoneIdCount, TInt aNumPages); |
|
70 TInt ZoneAllocToMany(TInt aZoneIndex, TInt aNumPages); |
|
71 TInt ZoneAllocToManyArray(TInt aZoneIndex, TInt aNumPages); |
|
72 TInt ZoneAllocToMany2(TInt aZoneIndex, TInt aNumPages); |
|
73 TInt AllocContiguous(TUint aNumBytes); |
|
74 TInt FreeZone(TInt aNumPages); |
|
75 TInt FreeFromAllZones(); |
|
76 TInt FreeFromAddr(TInt aNumPages, TUint32 aAddr); |
|
77 TInt PageCount(TUint aId, STestUserSidePageCount* aPageData); |
|
78 TInt CancelDefrag(); |
|
79 TInt CheckCancel(STestParameters* aParams); |
|
80 TInt CallDefrag(STestParameters* aParams); |
|
81 TInt CheckPriorities(STestParameters* aParams); |
|
82 TInt SetZoneFlag(STestFlagParams* aParams); |
|
83 TInt GetDefragOrder(); |
|
84 TInt FreeRam(); |
|
85 TInt DoSetDebugFlag(TInt aState); |
|
86 TInt ResetDriver(); |
|
87 TInt ZoneAllocDiscontiguous2(TUint aZoneID, TInt aNumPages); |
|
88 public: |
|
89 DRamDefragFuncTestFactory* iFactory; |
|
90 |
|
91 protected: |
|
92 static void DefragCompleteDfc(TAny* aSelf); |
|
93 void DefragComplete(); |
|
94 static void Defrag2CompleteDfc(TAny* aSelf); |
|
95 void Defrag2Complete(); |
|
96 static void Defrag3CompleteDfc(TAny* aSelf); |
|
97 void Defrag3Complete(); |
|
98 private: |
|
99 TPhysAddr iContigAddr; /**< The base address of fixed contiguous allocations*/ |
|
100 TUint iContigBytes; /**< The no. of contiguous fixed bytes allocated*/ |
|
101 TPhysAddr* iAddrArray; |
|
102 TUint iAddrArrayPages; |
|
103 TUint iAddrArraySize; |
|
104 TPhysAddr** iAddrPtrArray; |
|
105 TInt* iNumPagesArray; |
|
106 TInt iDebug; |
|
107 TInt iThreadCounter; |
|
108 DChunk* iChunk; |
|
109 TLinAddr iKernAddrStart; |
|
110 TInt iPageSize; |
|
111 TUint iPageShift; /**< The system's page shift */ |
|
112 TUint iZoneCount; |
|
113 TRamDefragRequest iDefragRequest; // Defrag request object |
|
114 TRamDefragRequest iDefragRequest2; |
|
115 TRamDefragRequest iDefragRequest3; |
|
116 TUint* iZoneIdArray; /**< Pointer to an kernel heap array of zone IDs*/ |
|
117 |
|
118 |
|
119 DSemaphore* iDefragSemaphore; // Semaphore enusre only one defrag operation is active per channel |
|
120 TRequestStatus* iCompleteReq; // Pointer to a request status that will signal to the user side client once the defrag has completed |
|
121 TRequestStatus* iCompleteReq2; |
|
122 TRequestStatus* iCompleteReq3; |
|
123 TRequestStatus iTmpRequestStatus1; |
|
124 TRequestStatus iTmpRequestStatus2; |
|
125 DThread* iRequestThread; // Pointer to the thread that made the defrag request |
|
126 DThread* iRequestThread2; |
|
127 DThread* iRequestThread3; |
|
128 |
|
129 TDfcQue* iDfcQ; // The DFC queue used for driver functions |
|
130 TDfc iDefragCompleteDfc; // DFC to be queued once a defrag operation has completed |
|
131 TDfc iDefragComplete2Dfc; |
|
132 TDfc iDefragComplete3Dfc; |
|
133 TInt iCounter; // Counts the number of defrags that have taken place |
|
134 TInt iOrder; // Stores the order in which queued defrags took place |
|
135 }; |
|
136 |
|
137 |
|
138 |
|
139 // |
|
140 // DRamDefragFuncTestFactory |
|
141 // |
|
142 |
|
143 DRamDefragFuncTestFactory::DRamDefragFuncTestFactory() |
|
144 // |
|
145 // Constructor |
|
146 // |
|
147 { |
|
148 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
149 //iParseMask=0;//No units, no info, no PDD |
|
150 //iUnitsMask=0;//Only one thing |
|
151 } |
|
152 |
|
153 TInt DRamDefragFuncTestFactory::Install() |
|
154 { |
|
155 return SetName(&KRamDefragFuncTestLddName); |
|
156 } |
|
157 |
|
158 DRamDefragFuncTestFactory::~DRamDefragFuncTestFactory() |
|
159 { |
|
160 if (iDfcQ != NULL) |
|
161 {// Destroy the DFC queue created when this device drvier was loaded. |
|
162 iDfcQ->Destroy(); |
|
163 } |
|
164 } |
|
165 |
|
166 void DRamDefragFuncTestFactory::GetCaps(TDes8& /*aDes*/) const |
|
167 { |
|
168 // Not used but required as DLogicalDevice::GetCaps is pure virtual |
|
169 } |
|
170 |
|
171 TInt DRamDefragFuncTestFactory::Create(DLogicalChannelBase*& aChannel) |
|
172 { |
|
173 DRamDefragFuncTestChannel* channel=new DRamDefragFuncTestChannel(iDfcQ); |
|
174 if(!channel) |
|
175 return KErrNoMemory; |
|
176 channel->iFactory = this; |
|
177 aChannel = channel; |
|
178 return KErrNone; |
|
179 } |
|
180 |
|
181 DECLARE_STANDARD_LDD() |
|
182 { |
|
183 DRamDefragFuncTestFactory* factory = new DRamDefragFuncTestFactory; |
|
184 if (factory) |
|
185 { |
|
186 // Allocate a kernel thread to run the DFC |
|
187 TInt r = Kern::DynamicDfcQCreate(factory->iDfcQ, KDefragCompleteThreadPriority, KDefragCompleteThread); |
|
188 |
|
189 if (r != KErrNone) |
|
190 {// Must close rather than delete factory as it is a DObject object. |
|
191 factory->AsyncClose(); |
|
192 return NULL; |
|
193 } |
|
194 } |
|
195 return factory; |
|
196 } |
|
197 |
|
198 // |
|
199 // DRamDefragFuncTestChannel |
|
200 // |
|
201 |
|
202 TInt DRamDefragFuncTestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/) |
|
203 { |
|
204 |
|
205 TInt ret = Kern::HalFunction(EHalGroupRam, ERamHalGetZoneCount, (TAny*)&iZoneCount, NULL); |
|
206 |
|
207 |
|
208 // Retrieve the page size and use it to detemine the page shift (assumes 32-bit system). |
|
209 TInt r = Kern::HalFunction(EHalGroupKernel, EKernelHalPageSizeInBytes, &iPageSize, 0); |
|
210 if (r != KErrNone) |
|
211 { |
|
212 TESTDEBUG(Kern::Printf("ERROR - Unable to determine page size")); |
|
213 return r; |
|
214 } |
|
215 TUint32 pageMask = iPageSize; |
|
216 TUint i = 0; |
|
217 for (; i < 32; i++) |
|
218 { |
|
219 if (pageMask & 1) |
|
220 { |
|
221 if (pageMask & ~1u) |
|
222 { |
|
223 TESTDEBUG(Kern::Printf("ERROR - page size not a power of 2")); |
|
224 return KErrNotSupported; |
|
225 } |
|
226 iPageShift = i; |
|
227 break; |
|
228 } |
|
229 pageMask >>= 1; |
|
230 } |
|
231 |
|
232 // Create a semaphore to protect defrag invocation. OK to just use one name as |
|
233 // the semaphore is not global so it's name doesn't need to be unique. |
|
234 ret = Kern::SemaphoreCreate(iDefragSemaphore, _L("DefragRefSem"), 1); |
|
235 if (ret != KErrNone) |
|
236 { |
|
237 return ret; |
|
238 } |
|
239 iDefragCompleteDfc.SetDfcQ(iDfcQ); |
|
240 iDefragComplete2Dfc.SetDfcQ(iDfcQ); |
|
241 iDefragComplete3Dfc.SetDfcQ(iDfcQ); |
|
242 |
|
243 // Create an array to store some RAM zone IDs for use but the multi-zone |
|
244 // specific allcoation methods. |
|
245 NKern::ThreadEnterCS(); |
|
246 iZoneIdArray = new TUint[KMaxRamZones]; |
|
247 if (iZoneIdArray == NULL) |
|
248 { |
|
249 ret = KErrNoMemory; |
|
250 } |
|
251 NKern::ThreadLeaveCS(); |
|
252 |
|
253 return ret; |
|
254 } |
|
255 |
|
256 DRamDefragFuncTestChannel::DRamDefragFuncTestChannel(TDfcQue* aDfcQ) |
|
257 : |
|
258 iContigAddr(KPhysAddrInvalid), |
|
259 iContigBytes(0), |
|
260 iAddrArray(NULL), |
|
261 iAddrArrayPages(0), |
|
262 iAddrArraySize(0), |
|
263 iAddrPtrArray(NULL), |
|
264 iNumPagesArray(NULL), |
|
265 iDebug(0), |
|
266 iThreadCounter(1), |
|
267 iChunk(NULL), |
|
268 iPageSize(0), |
|
269 iPageShift(0), |
|
270 iZoneCount(0), |
|
271 iZoneIdArray(NULL), |
|
272 iDefragSemaphore(NULL), |
|
273 iCompleteReq(NULL), |
|
274 iCompleteReq2(NULL), |
|
275 iCompleteReq3(NULL), |
|
276 iRequestThread(NULL), |
|
277 iRequestThread2(NULL), |
|
278 iRequestThread3(NULL), |
|
279 iDfcQ(aDfcQ), |
|
280 iDefragCompleteDfc(DefragCompleteDfc, (TAny*)this, 1), |
|
281 iDefragComplete2Dfc(Defrag2CompleteDfc, (TAny*)this, 1), |
|
282 iDefragComplete3Dfc(Defrag3CompleteDfc, (TAny*)this, 1), |
|
283 iCounter(0), |
|
284 iOrder(0) |
|
285 { |
|
286 } |
|
287 |
|
288 DRamDefragFuncTestChannel::~DRamDefragFuncTestChannel() |
|
289 { |
|
290 if (iDefragSemaphore != NULL) |
|
291 { |
|
292 iDefragSemaphore->Close(NULL); |
|
293 } |
|
294 if (iZoneIdArray != NULL) |
|
295 { |
|
296 NKern::ThreadEnterCS(); |
|
297 delete[] iZoneIdArray; |
|
298 NKern::ThreadLeaveCS(); |
|
299 } |
|
300 } |
|
301 |
|
302 TInt DRamDefragFuncTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2) |
|
303 { |
|
304 TInt threadCount = __e32_atomic_tas_ord32(&iThreadCounter, 1, 1, 0); |
|
305 if (threadCount >= 2) |
|
306 { |
|
307 Kern::Printf("DRamDefragFuncTestChannel::Request threadCount = %d\n", threadCount); |
|
308 } |
|
309 |
|
310 Kern::SemaphoreWait(*iDefragSemaphore); |
|
311 |
|
312 |
|
313 TInt retVal = KErrNotSupported; |
|
314 switch(aFunction) |
|
315 { |
|
316 case RRamDefragFuncTestLdd::EAllocateFixed: |
|
317 retVal = DRamDefragFuncTestChannel::AllocFixedPages((TInt)a1); |
|
318 break; |
|
319 |
|
320 case RRamDefragFuncTestLdd::EAllocFixedArray: |
|
321 retVal = DRamDefragFuncTestChannel::AllocFixedArray((TInt)a1); |
|
322 break; |
|
323 |
|
324 case RRamDefragFuncTestLdd::EAllocateFixed2: |
|
325 retVal = DRamDefragFuncTestChannel::AllocateFixed2((TInt)a1); |
|
326 break; |
|
327 |
|
328 case RRamDefragFuncTestLdd::EGetAllocDiff: |
|
329 retVal = DRamDefragFuncTestChannel::GetAllocDiff((TUint)a1); |
|
330 break; |
|
331 |
|
332 case RRamDefragFuncTestLdd::EFreeAllFixed: |
|
333 retVal = DRamDefragFuncTestChannel::FreeAllFixedPages(); |
|
334 break; |
|
335 |
|
336 case RRamDefragFuncTestLdd::EAllocateFixedWrite: |
|
337 retVal = DRamDefragFuncTestChannel::AllocFixedPagesWrite((TInt)a1); |
|
338 break; |
|
339 |
|
340 case RRamDefragFuncTestLdd::EFreeAllFixedRead: |
|
341 retVal = DRamDefragFuncTestChannel::FreeAllFixedPagesRead(); |
|
342 break; |
|
343 |
|
344 case RRamDefragFuncTestLdd::EZoneAllocContiguous: |
|
345 retVal = DRamDefragFuncTestChannel::ZoneAllocContiguous((TUint)a1, (TUint)a2); |
|
346 break; |
|
347 |
|
348 case RRamDefragFuncTestLdd::EMultiZoneAllocContiguous: |
|
349 { |
|
350 SMultiZoneAlloc multiZone; |
|
351 kumemget(&multiZone, a1, sizeof(SMultiZoneAlloc)); |
|
352 retVal = DRamDefragFuncTestChannel::ZoneAllocContiguous(multiZone.iZoneId, multiZone.iZoneIdSize, (TUint)a2); |
|
353 } |
|
354 break; |
|
355 |
|
356 case RRamDefragFuncTestLdd::EZoneAllocDiscontiguous: |
|
357 retVal = DRamDefragFuncTestChannel::ZoneAllocDiscontiguous((TUint)a1, (TUint)a2); |
|
358 break; |
|
359 |
|
360 case RRamDefragFuncTestLdd::EMultiZoneAllocDiscontiguous: |
|
361 { |
|
362 SMultiZoneAlloc multiZone; |
|
363 kumemget(&multiZone, a1, sizeof(SMultiZoneAlloc)); |
|
364 retVal = DRamDefragFuncTestChannel::ZoneAllocDiscontiguous(multiZone.iZoneId, multiZone.iZoneIdSize, (TUint)a2); |
|
365 } |
|
366 break; |
|
367 |
|
368 case RRamDefragFuncTestLdd::EZoneAllocDiscontiguous2: |
|
369 retVal = DRamDefragFuncTestChannel::ZoneAllocDiscontiguous2((TUint)a1, (TUint)a2); |
|
370 break; |
|
371 |
|
372 case RRamDefragFuncTestLdd::EZoneAllocToMany: |
|
373 retVal = DRamDefragFuncTestChannel::ZoneAllocToMany((TUint)a1, (TInt)a2); |
|
374 break; |
|
375 |
|
376 case RRamDefragFuncTestLdd::EZoneAllocToManyArray: |
|
377 retVal = DRamDefragFuncTestChannel::ZoneAllocToManyArray((TUint)a1, (TInt)a2); |
|
378 break; |
|
379 |
|
380 case RRamDefragFuncTestLdd::EZoneAllocToMany2: |
|
381 retVal = DRamDefragFuncTestChannel::ZoneAllocToMany2((TUint)a1, (TInt)a2); |
|
382 break; |
|
383 |
|
384 case RRamDefragFuncTestLdd::EAllocContiguous: |
|
385 retVal = DRamDefragFuncTestChannel::AllocContiguous((TUint)a1); |
|
386 break; |
|
387 |
|
388 case RRamDefragFuncTestLdd::EFreeZone: |
|
389 retVal = DRamDefragFuncTestChannel::FreeZone((TInt)a1); |
|
390 break; |
|
391 |
|
392 case RRamDefragFuncTestLdd::EFreeFromAllZones: |
|
393 retVal = DRamDefragFuncTestChannel::FreeFromAllZones(); |
|
394 break; |
|
395 |
|
396 case RRamDefragFuncTestLdd::EFreeFromAddr: |
|
397 retVal = DRamDefragFuncTestChannel::FreeFromAddr((TInt)a1, (TUint32)a2); |
|
398 break; |
|
399 |
|
400 case RRamDefragFuncTestLdd::EPageCount: |
|
401 retVal = DRamDefragFuncTestChannel::PageCount((TUint)a1, (STestUserSidePageCount*)a2); |
|
402 break; |
|
403 |
|
404 case RRamDefragFuncTestLdd::ECheckCancel: |
|
405 retVal = DRamDefragFuncTestChannel::CheckCancel((STestParameters*)a1); |
|
406 break; |
|
407 |
|
408 case RRamDefragFuncTestLdd::ECallDefrag: |
|
409 retVal = DRamDefragFuncTestChannel::CallDefrag((STestParameters*)a1); |
|
410 break; |
|
411 |
|
412 case RRamDefragFuncTestLdd::ESetZoneFlag: |
|
413 retVal = DRamDefragFuncTestChannel::SetZoneFlag((STestFlagParams*)a1); |
|
414 break; |
|
415 |
|
416 case RRamDefragFuncTestLdd::ECheckPriorities: |
|
417 retVal = DRamDefragFuncTestChannel::CheckPriorities((STestParameters*)a1); |
|
418 break; |
|
419 |
|
420 case RRamDefragFuncTestLdd::EGetDefragOrder: |
|
421 retVal = DRamDefragFuncTestChannel::GetDefragOrder(); |
|
422 break; |
|
423 |
|
424 case RRamDefragFuncTestLdd::EDoSetDebugFlag: |
|
425 retVal = DoSetDebugFlag((TInt) a1); |
|
426 break; |
|
427 |
|
428 case RRamDefragFuncTestLdd::EResetDriver: |
|
429 retVal = ResetDriver(); |
|
430 break; |
|
431 |
|
432 default: |
|
433 break; |
|
434 } |
|
435 |
|
436 Kern::SemaphoreSignal(*iDefragSemaphore); |
|
437 __e32_atomic_tas_ord32(&iThreadCounter, 1, -1, 0); |
|
438 return retVal; |
|
439 } |
|
440 |
|
441 |
|
442 #define CHECK(c) { if(!(c)) { Kern::Printf("Fail %d", __LINE__); ; retVal = __LINE__;} } |
|
443 |
|
444 |
|
445 // |
|
446 // FreeAllFixedPages |
|
447 // |
|
448 // Free ALL of the fixed pages that were allocated |
|
449 // |
|
450 TInt DRamDefragFuncTestChannel::FreeAllFixedPages() |
|
451 { |
|
452 NKern::ThreadEnterCS(); |
|
453 |
|
454 TInt retVal = KErrNone; |
|
455 |
|
456 if (iAddrArray != NULL) |
|
457 { |
|
458 retVal = Epoc::FreePhysicalRam(iAddrArrayPages, iAddrArray); |
|
459 CHECK(retVal == KErrNone); |
|
460 |
|
461 delete[] iAddrArray; |
|
462 iAddrArray = NULL; |
|
463 iAddrArrayPages = 0; |
|
464 } |
|
465 |
|
466 if (iContigAddr != KPhysAddrInvalid) |
|
467 { |
|
468 retVal = Epoc::FreePhysicalRam(iContigAddr, iContigBytes); |
|
469 iContigAddr = KPhysAddrInvalid; |
|
470 iContigBytes = 0; |
|
471 CHECK(retVal == KErrNone); |
|
472 } |
|
473 NKern::ThreadLeaveCS(); |
|
474 |
|
475 retVal = FreeFromAllZones(); |
|
476 return retVal; |
|
477 } |
|
478 |
|
479 |
|
480 |
|
481 // |
|
482 // FreeAllFixedPagesRead() |
|
483 // |
|
484 // Read the fixed pages that were mapped to iChunk and verify that |
|
485 // the contents have not changed. Then free the fixed pages |
|
486 // that were allocated for iChunk. |
|
487 // |
|
488 TInt DRamDefragFuncTestChannel::FreeAllFixedPagesRead() |
|
489 { |
|
490 |
|
491 TInt retVal = KErrNone; |
|
492 TUint index; |
|
493 |
|
494 if (iAddrArray == NULL || iChunk == NULL || !iAddrArrayPages) |
|
495 { |
|
496 return KErrCorrupt; |
|
497 } |
|
498 |
|
499 TInt r = Kern::ChunkAddress(iChunk, 0, iAddrArrayPages << iPageShift, iKernAddrStart); |
|
500 if (r != KErrNone) |
|
501 { |
|
502 Kern::Printf("ERROR ? FreeAllFixedPages : Couldn't get linear address of iChunk! %d", r); |
|
503 } |
|
504 else |
|
505 { |
|
506 for (index = 0; index < iAddrArrayPages; index ++) |
|
507 { |
|
508 if (iAddrArray[index] != NULL) |
|
509 { |
|
510 TUint* pInt = (TUint *)(iKernAddrStart + (index << iPageShift)); |
|
511 TUint* pIntEnd = pInt + (iPageSize / sizeof(TInt)); |
|
512 // Read each word in this the page and verify that |
|
513 // they are still the index of the current page in the chunk. |
|
514 while (pInt < pIntEnd) |
|
515 { |
|
516 if (*pInt++ != index) |
|
517 { |
|
518 Kern::Printf("ERROR ? FreeAllFixedPages : page at index %d is corrupt! 0x%08x", index, *pInt); |
|
519 } |
|
520 } |
|
521 } |
|
522 } |
|
523 } |
|
524 NKern::ThreadEnterCS(); |
|
525 |
|
526 // Must close chunk before we free memory otherwise it would still be |
|
527 // possible to access memory that has been freed and potentially reused. |
|
528 Kern::ChunkClose(iChunk); |
|
529 iChunk = NULL; |
|
530 retVal = Epoc::FreePhysicalRam(iAddrArrayPages, iAddrArray); |
|
531 delete[] iAddrArray; |
|
532 |
|
533 NKern::ThreadLeaveCS(); |
|
534 |
|
535 iAddrArray = NULL; |
|
536 iAddrArrayPages = 0; |
|
537 return retVal; |
|
538 } |
|
539 |
|
540 // |
|
541 // AllocFixedPagesWrite |
|
542 // |
|
543 // Allocate a number of fixed pages to memory then create a shared chunk and map these pages into the chunk |
|
544 // |
|
545 TInt DRamDefragFuncTestChannel::AllocFixedPagesWrite(TInt aNumPages) |
|
546 { |
|
547 |
|
548 TInt retVal = KErrNone; |
|
549 TUint index = 0; |
|
550 TChunkCreateInfo chunkInfo; |
|
551 TUint32 mapAttr; |
|
552 |
|
553 if (iAddrArray != NULL || iChunk != NULL) |
|
554 { |
|
555 return KErrInUse; |
|
556 } |
|
557 |
|
558 if (aNumPages == FILL_ALL_FIXED) |
|
559 {// Fill memory with fixed pages, leaving room for the kernel to expand. |
|
560 TUint freePages = FreeRam() >> iPageShift; |
|
561 // Calculate how many page tables will be required: |
|
562 // 1024 pages per page table |
|
563 // 4 page table per page |
|
564 TUint pageTablePages = (freePages >> 10) >> 2; |
|
565 TUint physAddrPages = (sizeof(TPhysAddr) * freePages) >> iPageShift; |
|
566 TESTDEBUG(Kern::Printf("pageTablePages %d physAddrPages %d", pageTablePages, physAddrPages)); |
|
567 // Determine how many heap pages will be required, with some extra space as well. |
|
568 TUint fixedOverhead = (pageTablePages + physAddrPages) << 4; |
|
569 TESTDEBUG(Kern::Printf("freePages %d fixedOverhead %d", freePages, fixedOverhead)); |
|
570 aNumPages = freePages - fixedOverhead; |
|
571 TESTDEBUG(Kern::Printf("aNumPages = %d", aNumPages)); |
|
572 } |
|
573 |
|
574 NKern::ThreadEnterCS(); |
|
575 |
|
576 iAddrArray = new TPhysAddr[aNumPages]; |
|
577 if(!iAddrArray) |
|
578 { |
|
579 retVal = KErrNoMemory; |
|
580 goto exit; |
|
581 } |
|
582 |
|
583 TESTDEBUG(Kern::Printf("amount of free pages = %d", FreeRam() >> iPageShift)); |
|
584 |
|
585 // create a shared chunk and map these pages into the chunk. |
|
586 |
|
587 chunkInfo.iType = TChunkCreateInfo::ESharedKernelSingle; |
|
588 chunkInfo.iMaxSize = aNumPages << iPageShift; |
|
589 chunkInfo.iMapAttr = EMapAttrFullyBlocking; |
|
590 chunkInfo.iOwnsMemory = EFalse; |
|
591 |
|
592 TESTDEBUG(Kern::Printf("Creating chunk - amount of free pages = %d\n", FreeRam() >> iPageShift)); |
|
593 retVal = Kern::ChunkCreate(chunkInfo, iChunk, iKernAddrStart, mapAttr); |
|
594 if (retVal != KErrNone) |
|
595 { |
|
596 Kern::Printf("ChunkCreate failed retVal = %d", retVal); |
|
597 goto exit; |
|
598 } |
|
599 |
|
600 TESTDEBUG(Kern::Printf("Created chunk - amount of free pages = %d\n", FreeRam() >> iPageShift)); |
|
601 |
|
602 retVal = Epoc::AllocPhysicalRam(aNumPages, iAddrArray); |
|
603 if (retVal != KErrNone) |
|
604 { |
|
605 TESTDEBUG(Kern::Printf("Alloc of %d pages was unsuccessful\n", aNumPages)); |
|
606 goto exit; |
|
607 } |
|
608 iAddrArrayPages = aNumPages; |
|
609 TESTDEBUG(Kern::Printf("Committing chunk - amount of free pages = %d\n", FreeRam() >> iPageShift)); |
|
610 retVal = Kern::ChunkCommitPhysical(iChunk, 0, iAddrArrayPages << iPageShift, iAddrArray); |
|
611 if (retVal != KErrNone) |
|
612 { |
|
613 Kern::Printf("Commit was bad retVal = %d", retVal); |
|
614 goto exit; |
|
615 } |
|
616 TESTDEBUG(Kern::Printf("Committed chunk - amount of free pages = %d\n", FreeRam() >> iPageShift)); |
|
617 TESTDEBUG(Kern::Printf("Start - 0x%08x\n", iKernAddrStart)); |
|
618 for (index = 0; index < iAddrArrayPages; index ++) |
|
619 { |
|
620 TInt* pInt = (TInt *)(iKernAddrStart + (index << iPageShift)); |
|
621 TInt* pIntEnd = pInt + (iPageSize / sizeof(TInt)); |
|
622 // write the index into all of the words of the page. |
|
623 while (pInt < pIntEnd) |
|
624 { |
|
625 *pInt++ = index; |
|
626 } |
|
627 } |
|
628 |
|
629 TESTDEBUG(Kern::Printf("Allocated %d pages\n", iAddrArrayPages)); |
|
630 exit: |
|
631 if (retVal != KErrNone) |
|
632 {// Cleanup as something went wrong |
|
633 if (iChunk) |
|
634 { |
|
635 Kern::ChunkClose(iChunk); |
|
636 iChunk = NULL; |
|
637 } |
|
638 if (iAddrArray != NULL) |
|
639 { |
|
640 Epoc::FreePhysicalRam(iAddrArrayPages, iAddrArray); |
|
641 delete[] iAddrArray; |
|
642 iAddrArray = NULL; |
|
643 } |
|
644 iAddrArrayPages = 0; |
|
645 } |
|
646 |
|
647 NKern::ThreadLeaveCS(); |
|
648 return retVal; |
|
649 } |
|
650 |
|
651 TInt DRamDefragFuncTestChannel::GetAllocDiff(TUint aNumPages) |
|
652 { |
|
653 TUint initialFreeRam = FreeRam(); |
|
654 TInt ret = KErrNone; |
|
655 TInt ramDifference; |
|
656 |
|
657 NKern::ThreadEnterCS(); |
|
658 |
|
659 if (iAddrArray != NULL) |
|
660 { |
|
661 ret = KErrInUse; |
|
662 goto exit; |
|
663 } |
|
664 iAddrArray = (TPhysAddr *)Kern::AllocZ(sizeof(TPhysAddr) * aNumPages); |
|
665 |
|
666 if(!iAddrArray) |
|
667 { |
|
668 ret = KErrNoMemory; |
|
669 goto exit; |
|
670 } |
|
671 |
|
672 ramDifference = initialFreeRam - FreeRam(); |
|
673 |
|
674 Kern::Free(iAddrArray); |
|
675 iAddrArray = NULL; |
|
676 |
|
677 ret = ramDifference >> iPageShift; |
|
678 exit: |
|
679 NKern::ThreadLeaveCS(); |
|
680 return ret; |
|
681 } |
|
682 // |
|
683 // AllocFixedPages |
|
684 // |
|
685 // Allocate a number of fixed pages to memory |
|
686 // |
|
687 TInt DRamDefragFuncTestChannel::AllocFixedPages(TInt aNumPages) |
|
688 { |
|
689 TInt r = AllocFixedArray(aNumPages); |
|
690 if (r != KErrNone) |
|
691 { |
|
692 return r; |
|
693 } |
|
694 return AllocateFixed2(aNumPages); |
|
695 } |
|
696 |
|
697 /** |
|
698 Allocate the array required to store the physical addresses of |
|
699 number of fixed pages to be allocated. |
|
700 |
|
701 @param aNumPages The number of fixed pages to be allocated. |
|
702 @return KErrNone on success. |
|
703 */ |
|
704 TInt DRamDefragFuncTestChannel::AllocFixedArray(TInt aNumPages) |
|
705 { |
|
706 if (iAddrArray != NULL) |
|
707 { |
|
708 return KErrInUse; |
|
709 } |
|
710 |
|
711 if (aNumPages == FILL_ALL_FIXED) |
|
712 {// Fill memory with fixed pages. |
|
713 aNumPages = FreeRam() >> iPageShift; |
|
714 TESTDEBUG(Kern::Printf("aNumPages %d FreeRam() %d", aNumPages, FreeRam())); |
|
715 } |
|
716 NKern::ThreadEnterCS(); |
|
717 |
|
718 iAddrArray = new TPhysAddr[aNumPages]; |
|
719 iAddrArraySize = aNumPages; // Only required for AllocateFixed2() when aNumPages == FILL_ALL_FIXED. |
|
720 iAddrArrayPages = 0; // No physical pages have been allocated yet. |
|
721 |
|
722 NKern::ThreadLeaveCS(); |
|
723 |
|
724 if (!iAddrArray) |
|
725 { |
|
726 return KErrNoMemory; |
|
727 } |
|
728 return KErrNone; |
|
729 } |
|
730 |
|
731 |
|
732 /** |
|
733 Allocate the specified number of fixed pages. |
|
734 This should only be invoked when iAddrArray has already been allocated |
|
735 |
|
736 @param aNumPages The number of pages to allocate. |
|
737 */ |
|
738 TInt DRamDefragFuncTestChannel::AllocateFixed2(TInt aNumPages) |
|
739 { |
|
740 if (iAddrArray == NULL) |
|
741 { |
|
742 return KErrGeneral; |
|
743 } |
|
744 TInt retVal = KErrNone; |
|
745 NKern::ThreadEnterCS(); |
|
746 if (aNumPages == FILL_ALL_FIXED) |
|
747 { |
|
748 // Allocate a number of fixed pages to RAM a page at time so that the allocations |
|
749 // will always fill as much memory as possible. |
|
750 TPhysAddr* addrPtr = iAddrArray; |
|
751 TPhysAddr* addrPtrEnd = addrPtr + iAddrArraySize; |
|
752 while (addrPtr < addrPtrEnd) |
|
753 { |
|
754 retVal = Epoc::AllocPhysicalRam(1, addrPtr++); |
|
755 if (retVal != KErrNone) |
|
756 break; |
|
757 iAddrArrayPages++; |
|
758 } |
|
759 } |
|
760 else |
|
761 { |
|
762 retVal = Epoc::AllocPhysicalRam(aNumPages, iAddrArray); |
|
763 if (retVal != KErrNone) |
|
764 { |
|
765 TESTDEBUG(Kern::Printf("aNumPages %d FreeRam() %d", aNumPages, FreeRam())); |
|
766 delete[] iAddrArray; |
|
767 iAddrArray = NULL; |
|
768 TESTDEBUG(Kern::Printf("aNumPages %d FreeRam() %d", aNumPages, FreeRam())); |
|
769 TESTDEBUG(Kern::Printf("Fixed pages alloc was unsuccessful\n")); |
|
770 } |
|
771 else |
|
772 iAddrArrayPages = aNumPages; |
|
773 } |
|
774 |
|
775 NKern::ThreadLeaveCS(); |
|
776 return retVal; |
|
777 } |
|
778 // |
|
779 // CheckCancel |
|
780 // |
|
781 // Check that when a defrag is cancelled, the correct return value is reported |
|
782 // |
|
783 TInt DRamDefragFuncTestChannel::CheckCancel(STestParameters* aParams) |
|
784 { |
|
785 TInt returnValue = KErrNone; |
|
786 STestParameters params; |
|
787 kumemget(¶ms, aParams, sizeof(STestParameters)); |
|
788 |
|
789 Kern::Printf( "defragtype = %d, defragversion = %d, priority = %d, maxpages = %d, ID = %d", |
|
790 params.iDefragType, params.iDefragVersion, params.iPriority, params.iMaxPages, params.iID); |
|
791 |
|
792 |
|
793 NFastSemaphore sem; |
|
794 NKern::FSSetOwner(&sem, 0); |
|
795 TPhysAddr zoneAddress; |
|
796 TInt maxPages = 0; |
|
797 TInt priority = (NKern::CurrentThread()->iPriority) - 2; |
|
798 |
|
799 if (params.iDefragType == DEFRAG_TYPE_GEN) // DefragRam |
|
800 { |
|
801 returnValue = iDefragRequest.DefragRam(&sem, priority, maxPages); |
|
802 } |
|
803 else if (params.iDefragType == DEFRAG_TYPE_EMPTY) // EmptyRamZone |
|
804 { |
|
805 returnValue = iDefragRequest.EmptyRamZone(params.iID, &sem, priority); |
|
806 } |
|
807 else if (params.iDefragType == DEFRAG_TYPE_CLAIM) // ClaimRamZone |
|
808 { |
|
809 returnValue = iDefragRequest.ClaimRamZone(params.iID, zoneAddress, &sem, priority); |
|
810 } |
|
811 else |
|
812 { |
|
813 Kern::Printf("A valid defrag type was not specified"); |
|
814 return KErrGeneral; |
|
815 } |
|
816 |
|
817 iDefragRequest.Cancel(); |
|
818 NKern::FSWait(&sem); |
|
819 returnValue = iDefragRequest.Result(); |
|
820 return returnValue; |
|
821 } |
|
822 |
|
823 |
|
824 // |
|
825 // CheckPriorities |
|
826 // |
|
827 // Queue defrags with differing priorities and ensure they complete in the correct order |
|
828 // |
|
829 TInt DRamDefragFuncTestChannel::CheckPriorities(STestParameters* aParams) |
|
830 { |
|
831 STestParameters params; |
|
832 kumemget(¶ms, aParams, sizeof(STestParameters)); |
|
833 |
|
834 // Still have an outstanding defrag operation |
|
835 if (iCompleteReq != NULL | iCompleteReq2 != NULL | iCompleteReq3 != NULL) |
|
836 { |
|
837 return KErrInUse; |
|
838 } |
|
839 |
|
840 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
841 // then try to complete the request on a destroyed thread. |
|
842 iRequestThread = &Kern::CurrentThread(); |
|
843 iRequestThread->Open(); |
|
844 iCompleteReq = params.iReqStat; |
|
845 |
|
846 // Open a reference on this channel to stop the destructor running before |
|
847 // this defrag request has completed. |
|
848 Open(); |
|
849 TUint defragZone = params.iID - 1; |
|
850 TInt returnValue = iDefragRequest.EmptyRamZone(defragZone, &iDefragCompleteDfc, 1); |
|
851 if (returnValue != KErrNone) |
|
852 { |
|
853 AsyncClose(); |
|
854 iCompleteReq = NULL; |
|
855 iRequestThread->AsyncClose(); |
|
856 iRequestThread = NULL; |
|
857 return returnValue; |
|
858 } |
|
859 |
|
860 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
861 // then try to complete the request on a destroyed thread. |
|
862 iRequestThread2 = &Kern::CurrentThread(); |
|
863 iRequestThread2->Open(); |
|
864 iCompleteReq2 = params.iReqStat2; |
|
865 // Open a reference on this channel to stop the destructor running before |
|
866 // this defrag request has completed. |
|
867 Open(); |
|
868 defragZone = params.iID; |
|
869 returnValue = iDefragRequest2.EmptyRamZone(defragZone, &iDefragComplete2Dfc, 30); |
|
870 if (returnValue != KErrNone) |
|
871 { |
|
872 // Cancel any successfully queued operations. |
|
873 // Set dfcs to signal dummy request statuses as user side |
|
874 // request status shouldn't be signalled. |
|
875 iCompleteReq = &iTmpRequestStatus1; |
|
876 iDefragRequest.Cancel(); |
|
877 |
|
878 // Clean up this operation. |
|
879 AsyncClose(); |
|
880 iCompleteReq2 = NULL; |
|
881 iRequestThread2->AsyncClose(); |
|
882 iRequestThread2 = NULL; |
|
883 return returnValue; |
|
884 } |
|
885 |
|
886 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
887 // then try to complete the request on a destroyed thread. |
|
888 iRequestThread3 = &Kern::CurrentThread(); |
|
889 iRequestThread3->Open(); |
|
890 iCompleteReq3 = params.iReqStat3; |
|
891 // Open a reference on this channel to stop the destructor running before |
|
892 // this defrag request has completed. |
|
893 Open(); |
|
894 defragZone = params.iID + 2; |
|
895 returnValue = iDefragRequest3.EmptyRamZone(defragZone, &iDefragComplete3Dfc, 60); |
|
896 if (returnValue != KErrNone) |
|
897 { |
|
898 // Cancel any successfully queued operations. |
|
899 // Set dfcs to signal dummy request statuses as user side |
|
900 // request status shouldn't be signalled. |
|
901 iCompleteReq = &iTmpRequestStatus1; |
|
902 iCompleteReq2 = &iTmpRequestStatus2; |
|
903 iDefragRequest.Cancel(); |
|
904 iDefragRequest2.Cancel(); |
|
905 |
|
906 // clean up this defrag operation |
|
907 AsyncClose(); |
|
908 iCompleteReq3 = NULL; |
|
909 iRequestThread3->AsyncClose(); |
|
910 iRequestThread3 = NULL; |
|
911 return returnValue; |
|
912 } |
|
913 return returnValue; |
|
914 } |
|
915 |
|
916 // |
|
917 // GetDefragOrder |
|
918 // |
|
919 // Get the order in which the defrags were completed |
|
920 // |
|
921 TInt DRamDefragFuncTestChannel::GetDefragOrder() |
|
922 { |
|
923 Kern::Printf("order = %d", iOrder); |
|
924 return iOrder; |
|
925 } |
|
926 |
|
927 |
|
928 // |
|
929 // CallDefrag |
|
930 // |
|
931 // Call a specific defrag depening on the parameters that it is called with |
|
932 // |
|
933 TInt DRamDefragFuncTestChannel::CallDefrag(STestParameters* aParams) |
|
934 { |
|
935 TInt returnValue = 0; |
|
936 STestParameters params; |
|
937 kumemget(¶ms, aParams, sizeof(STestParameters)); |
|
938 |
|
939 TESTDEBUG(Kern::Printf("defragtype = %d, defragversion = %d, priority = %d, maxpages = %d, ID = %d", |
|
940 params.iDefragType, params.iDefragVersion, params.iPriority, params.iMaxPages, params.iID)); |
|
941 |
|
942 |
|
943 NFastSemaphore sem; |
|
944 NKern::FSSetOwner(&sem, 0); |
|
945 |
|
946 if (params.iDefragType == DEFRAG_TYPE_GEN) // DefragRam |
|
947 { |
|
948 switch(params.iDefragVersion) |
|
949 { |
|
950 case DEFRAG_VER_SYNC: // Sync |
|
951 returnValue = iDefragRequest.DefragRam(params.iPriority, params.iMaxPages); |
|
952 break; |
|
953 |
|
954 case DEFRAG_VER_SEM: // Semaphore |
|
955 returnValue = iDefragRequest.DefragRam(&sem, params.iPriority, params.iMaxPages); |
|
956 NKern::FSWait(&sem); |
|
957 returnValue = iDefragRequest.Result(); |
|
958 break; |
|
959 |
|
960 case DEFRAG_VER_DFC: // Dfc |
|
961 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
962 // then try to complete the request on a destroyed thread. |
|
963 if (iCompleteReq == NULL) |
|
964 { |
|
965 iRequestThread = &Kern::CurrentThread(); |
|
966 iRequestThread->Open(); |
|
967 iCompleteReq = params.iReqStat; |
|
968 // Open a reference on this channel to stop the destructor running before |
|
969 // the defrag request has completed. |
|
970 Open(); |
|
971 |
|
972 returnValue = iDefragRequest.DefragRam(&iDefragCompleteDfc, params.iPriority, params.iMaxPages); |
|
973 if (returnValue != KErrNone) |
|
974 {// defrag operation didn't start so close all openned handles |
|
975 AsyncClose(); |
|
976 iRequestThread->AsyncClose(); |
|
977 iRequestThread = NULL; |
|
978 iCompleteReq = NULL; |
|
979 } |
|
980 } |
|
981 else |
|
982 {// Still have a pending defrag request |
|
983 returnValue = KErrInUse; |
|
984 } |
|
985 break; |
|
986 |
|
987 default: |
|
988 break; |
|
989 } |
|
990 } |
|
991 |
|
992 else if (params.iDefragType == DEFRAG_TYPE_EMPTY) // EmptyRamZone |
|
993 { |
|
994 switch(params.iDefragVersion) |
|
995 { |
|
996 case DEFRAG_VER_SYNC: // Sync |
|
997 |
|
998 returnValue = iDefragRequest.EmptyRamZone(params.iID, params.iPriority); |
|
999 break; |
|
1000 |
|
1001 case DEFRAG_VER_SEM: // Semaphore |
|
1002 returnValue = iDefragRequest.EmptyRamZone(params.iID, &sem, params.iPriority); |
|
1003 NKern::FSWait(&sem); |
|
1004 returnValue = iDefragRequest.Result(); |
|
1005 break; |
|
1006 |
|
1007 case DEFRAG_VER_DFC: // Dfc |
|
1008 if (iCompleteReq == NULL) |
|
1009 { |
|
1010 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
1011 // then try to complete the request on a destroyed thread. |
|
1012 iRequestThread = &Kern::CurrentThread(); |
|
1013 iRequestThread->Open(); |
|
1014 iCompleteReq = params.iReqStat; |
|
1015 // Open a reference on this channel to stop the destructor running before |
|
1016 // the defrag request has completed. |
|
1017 Open(); |
|
1018 |
|
1019 returnValue = iDefragRequest.EmptyRamZone(params.iID, &iDefragCompleteDfc, params.iPriority); |
|
1020 if (returnValue != KErrNone) |
|
1021 {// defrag operation didn't start so close all openned handles |
|
1022 AsyncClose(); |
|
1023 iRequestThread->AsyncClose(); |
|
1024 iRequestThread = NULL; |
|
1025 iCompleteReq = NULL; |
|
1026 } |
|
1027 } |
|
1028 else |
|
1029 {// Still have a pending defrag request |
|
1030 returnValue = KErrInUse; |
|
1031 } |
|
1032 break; |
|
1033 |
|
1034 default: |
|
1035 break; |
|
1036 } |
|
1037 } |
|
1038 |
|
1039 else if (params.iDefragType == DEFRAG_TYPE_CLAIM) // ClaimRamZone |
|
1040 { |
|
1041 if (iContigAddr != KPhysAddrInvalid) |
|
1042 { |
|
1043 return KErrInUse; |
|
1044 } |
|
1045 switch(params.iDefragVersion) |
|
1046 { |
|
1047 case DEFRAG_VER_SYNC: // Sync |
|
1048 |
|
1049 returnValue = iDefragRequest.ClaimRamZone(params.iID, iContigAddr, params.iPriority); |
|
1050 break; |
|
1051 |
|
1052 case DEFRAG_VER_SEM: // Semaphore |
|
1053 returnValue = iDefragRequest.ClaimRamZone(params.iID, iContigAddr, &sem, params.iPriority); |
|
1054 NKern::FSWait(&sem); |
|
1055 returnValue = iDefragRequest.Result(); |
|
1056 break; |
|
1057 |
|
1058 case DEFRAG_VER_DFC: // Dfc |
|
1059 if (iCompleteReq == NULL) |
|
1060 { |
|
1061 // Open a handle to the thread so that it isn't destroyed as defrag dfc may |
|
1062 // then try to complete the request on a destroyed thread. |
|
1063 iRequestThread = &Kern::CurrentThread(); |
|
1064 iRequestThread->Open(); |
|
1065 iCompleteReq = params.iReqStat; |
|
1066 // Open a reference on this channel to stop the destructor running before |
|
1067 // the defrag request has completed. |
|
1068 Open(); |
|
1069 |
|
1070 // If the claim is successful iContigAddr will be set just before the dfc |
|
1071 // callback function to the physical base address of the RAM zone claimed. |
|
1072 // Therefore, the check for iContigAddr is not necessarily safe so use |
|
1073 // this DFC version with care and don't use it combination with any |
|
1074 // contiguous allocation methods. |
|
1075 returnValue = iDefragRequest.ClaimRamZone(params.iID, iContigAddr, &iDefragCompleteDfc, |
|
1076 params.iPriority); |
|
1077 if (returnValue != KErrNone) |
|
1078 {// defrag operation didn't start so close all openned handles |
|
1079 AsyncClose(); |
|
1080 iRequestThread->AsyncClose(); |
|
1081 iRequestThread = NULL; |
|
1082 iCompleteReq = NULL; |
|
1083 } |
|
1084 } |
|
1085 else |
|
1086 {// Still have a pending defrag request |
|
1087 returnValue = KErrInUse; |
|
1088 } |
|
1089 break; |
|
1090 |
|
1091 default: |
|
1092 break; |
|
1093 } |
|
1094 if (returnValue == KErrNone && params.iDefragVersion != DEFRAG_VER_DFC) |
|
1095 { |
|
1096 // Get the size of the zone just claimed so that it can be freed. Don't set |
|
1097 // iContigBytes for DFC method as it will be cleared by address in t_ramdefrag |
|
1098 |
|
1099 NKern::ThreadEnterCS(); |
|
1100 |
|
1101 SRamZonePageCount pageCount; |
|
1102 returnValue = Epoc::GetRamZonePageCount(params.iID, pageCount); |
|
1103 |
|
1104 NKern::ThreadLeaveCS(); |
|
1105 |
|
1106 __NK_ASSERT_ALWAYS(returnValue == KErrNone); // If this fails something is seriously wrong |
|
1107 iContigBytes = pageCount.iFixedPages << iPageShift; |
|
1108 } |
|
1109 else |
|
1110 {// The claim failed so allow other contiguous allocations. |
|
1111 iContigAddr = KPhysAddrInvalid; |
|
1112 } |
|
1113 } |
|
1114 |
|
1115 return returnValue; |
|
1116 } |
|
1117 |
|
1118 |
|
1119 |
|
1120 // |
|
1121 // SetZoneFlag |
|
1122 // |
|
1123 // Change the flag settings of a zone |
|
1124 // |
|
1125 TInt DRamDefragFuncTestChannel::SetZoneFlag(STestFlagParams* aParams) |
|
1126 { |
|
1127 |
|
1128 TInt returnValue = 0; |
|
1129 STestFlagParams flagParams; |
|
1130 kumemget(&flagParams, aParams, sizeof(STestFlagParams)); |
|
1131 TUint setFlag = 0x0; |
|
1132 switch(flagParams.iSetFlag) |
|
1133 { |
|
1134 case NO_FIXED_FLAG: |
|
1135 setFlag = KRamZoneFlagNoFixed; |
|
1136 break; |
|
1137 |
|
1138 case NO_MOVE_FLAG: |
|
1139 setFlag = KRamZoneFlagNoMovable; |
|
1140 break; |
|
1141 |
|
1142 case NO_DISCARD_FLAG: |
|
1143 setFlag = KRamZoneFlagNoDiscard; |
|
1144 break; |
|
1145 |
|
1146 case NO_ALLOC_FLAG: |
|
1147 setFlag = KRamZoneFlagNoAlloc; |
|
1148 break; |
|
1149 |
|
1150 case ONLY_DISCARD_FLAG: |
|
1151 setFlag = KRamZoneFlagDiscardOnly; |
|
1152 break; |
|
1153 |
|
1154 case RESET_FLAG: |
|
1155 setFlag = 0x00; |
|
1156 break; |
|
1157 |
|
1158 case ORIG_FLAG: |
|
1159 setFlag = flagParams.iOptSetFlag; |
|
1160 break; |
|
1161 |
|
1162 default: |
|
1163 break; |
|
1164 } |
|
1165 |
|
1166 NKern::ThreadEnterCS(); |
|
1167 |
|
1168 returnValue = Epoc::ModifyRamZoneFlags(flagParams.iZoneID, flagParams.iZoneFlag, setFlag); |
|
1169 |
|
1170 NKern::ThreadLeaveCS(); |
|
1171 return returnValue; |
|
1172 } |
|
1173 // |
|
1174 // PageCount |
|
1175 // |
|
1176 // Call the GetRamZonePageCount function |
|
1177 // |
|
1178 TInt DRamDefragFuncTestChannel::PageCount(TUint aId, STestUserSidePageCount* aPageData) |
|
1179 { |
|
1180 TInt returnValue = 0; |
|
1181 STestUserSidePageCount pageData; |
|
1182 SRamZonePageCount pageCount; |
|
1183 |
|
1184 NKern::ThreadEnterCS(); |
|
1185 |
|
1186 returnValue = Epoc::GetRamZonePageCount(aId, pageCount); |
|
1187 |
|
1188 NKern::ThreadLeaveCS(); |
|
1189 |
|
1190 pageData.iFreePages = pageCount.iFreePages; |
|
1191 pageData.iFixedPages = pageCount.iFixedPages; |
|
1192 pageData.iMovablePages = pageCount.iMovablePages; |
|
1193 pageData.iDiscardablePages = pageCount.iDiscardablePages; |
|
1194 |
|
1195 kumemput(aPageData, &pageData, sizeof(STestUserSidePageCount)); |
|
1196 return returnValue; |
|
1197 } |
|
1198 |
|
1199 // |
|
1200 // ZoneAllocContiguous |
|
1201 // |
|
1202 // Call the contiguous overload of the Epoc::ZoneAllocPhysicalRam() function |
|
1203 // |
|
1204 TInt DRamDefragFuncTestChannel::ZoneAllocContiguous(TUint aZoneID, TUint aNumBytes) |
|
1205 { |
|
1206 TInt returnValue = KErrNone; |
|
1207 |
|
1208 if (iContigAddr != KPhysAddrInvalid) |
|
1209 { |
|
1210 return KErrInUse; |
|
1211 } |
|
1212 iContigBytes = aNumBytes; |
|
1213 |
|
1214 NKern::ThreadEnterCS(); |
|
1215 |
|
1216 returnValue = Epoc::ZoneAllocPhysicalRam(aZoneID, iContigBytes, iContigAddr, 0); |
|
1217 |
|
1218 NKern::ThreadLeaveCS(); |
|
1219 |
|
1220 if (returnValue != KErrNone) |
|
1221 { |
|
1222 iContigAddr = KPhysAddrInvalid; |
|
1223 } |
|
1224 return returnValue; |
|
1225 } |
|
1226 |
|
1227 // |
|
1228 // ZoneAllocContiguous |
|
1229 // |
|
1230 // Call the contiguous overload of the Epoc::ZoneAllocPhysicalRam() function |
|
1231 // |
|
1232 TInt DRamDefragFuncTestChannel::ZoneAllocContiguous(TUint* aZoneIdList, TUint aZoneIdCount, TUint aNumBytes) |
|
1233 { |
|
1234 TInt returnValue = KErrNone; |
|
1235 |
|
1236 if (iContigAddr != KPhysAddrInvalid) |
|
1237 { |
|
1238 return KErrInUse; |
|
1239 } |
|
1240 iContigBytes = aNumBytes; |
|
1241 |
|
1242 // Copy the RAM zone IDs from user side memory to kernel memory. |
|
1243 if (aZoneIdCount > KMaxRamZones) |
|
1244 {// Too many IDs. |
|
1245 return KErrArgument; |
|
1246 } |
|
1247 kumemget32(iZoneIdArray, aZoneIdList, sizeof(TUint) * aZoneIdCount); |
|
1248 |
|
1249 NKern::ThreadEnterCS(); |
|
1250 |
|
1251 returnValue = Epoc::ZoneAllocPhysicalRam(iZoneIdArray, aZoneIdCount, iContigBytes, iContigAddr, 0); |
|
1252 |
|
1253 NKern::ThreadLeaveCS(); |
|
1254 |
|
1255 if (returnValue != KErrNone) |
|
1256 { |
|
1257 iContigAddr = KPhysAddrInvalid; |
|
1258 } |
|
1259 return returnValue; |
|
1260 } |
|
1261 |
|
1262 // |
|
1263 // AllocContiguous |
|
1264 // |
|
1265 // Call the contiguous overload of Epoc::AllocPhysicalRam() |
|
1266 // |
|
1267 TInt DRamDefragFuncTestChannel::AllocContiguous(TUint aNumBytes) |
|
1268 { |
|
1269 TInt returnValue = 0; |
|
1270 |
|
1271 if (iContigAddr != KPhysAddrInvalid) |
|
1272 { |
|
1273 return KErrInUse; |
|
1274 } |
|
1275 |
|
1276 NKern::ThreadEnterCS(); |
|
1277 |
|
1278 returnValue = Epoc::AllocPhysicalRam(aNumBytes, iContigAddr, 0); |
|
1279 |
|
1280 NKern::ThreadLeaveCS(); |
|
1281 |
|
1282 if (returnValue != KErrNone) |
|
1283 { |
|
1284 iContigAddr = KPhysAddrInvalid; |
|
1285 } |
|
1286 iContigBytes = aNumBytes; |
|
1287 return returnValue; |
|
1288 } |
|
1289 |
|
1290 |
|
1291 // |
|
1292 // ZoneAllocDiscontiguous |
|
1293 // |
|
1294 // Call the discontiguous overload of Epoc::ZoneAllocPhysicalRam() function |
|
1295 // |
|
1296 TInt DRamDefragFuncTestChannel::ZoneAllocDiscontiguous(TUint aZoneId, TInt aNumPages) |
|
1297 { |
|
1298 TInt r = AllocFixedArray(aNumPages); |
|
1299 if (r != KErrNone) |
|
1300 { |
|
1301 return r; |
|
1302 } |
|
1303 return ZoneAllocDiscontiguous2(aZoneId, aNumPages); |
|
1304 } |
|
1305 |
|
1306 /** |
|
1307 Allocate the specified number of fixed pages from the specified RAM zone. |
|
1308 This should only be invoked when iAddrArray has already been allocated |
|
1309 |
|
1310 @param aZoneID The ID of the RAM zone to allocate from |
|
1311 @param aNumPages The number of pages to allocate. |
|
1312 */ |
|
1313 TInt DRamDefragFuncTestChannel::ZoneAllocDiscontiguous2(TUint aZoneID, TInt aNumPages) |
|
1314 { |
|
1315 if (iAddrArray == NULL) |
|
1316 { |
|
1317 return KErrGeneral; |
|
1318 } |
|
1319 |
|
1320 NKern::ThreadEnterCS(); |
|
1321 |
|
1322 TESTDEBUG(Kern::Printf("Allocating fixed pages")); |
|
1323 TInt returnValue = Epoc::ZoneAllocPhysicalRam(aZoneID, aNumPages, iAddrArray); |
|
1324 |
|
1325 if (KErrNone != returnValue) |
|
1326 { |
|
1327 TESTDEBUG(Kern::Printf("Alloc was unsuccessful, r = %d\n", returnValue)); |
|
1328 TESTDEBUG(Kern::Printf("aNumPages = %d, aZoneID = %d", aNumPages, aZoneID)); |
|
1329 Kern::Free(iAddrArray); |
|
1330 iAddrArray = NULL; |
|
1331 goto exit; |
|
1332 } |
|
1333 iAddrArrayPages = aNumPages; |
|
1334 TESTDEBUG(Kern::Printf("iAddrArrayPages = %d, aZoneID = %d", iAddrArrayPages, aZoneID)); |
|
1335 |
|
1336 exit: |
|
1337 NKern::ThreadLeaveCS(); |
|
1338 return returnValue; |
|
1339 } |
|
1340 |
|
1341 |
|
1342 // |
|
1343 // ZoneAllocDiscontiguous |
|
1344 // |
|
1345 // Call the discontiguous overload of Epoc::ZoneAllocPhysicalRam() function |
|
1346 // |
|
1347 TInt DRamDefragFuncTestChannel::ZoneAllocDiscontiguous(TUint* aZoneIdList, TUint aZoneIdCount, TInt aNumPages) |
|
1348 { |
|
1349 TInt returnValue = 0; |
|
1350 |
|
1351 if (iAddrArray != NULL) |
|
1352 { |
|
1353 return KErrInUse; |
|
1354 } |
|
1355 NKern::ThreadEnterCS(); |
|
1356 |
|
1357 iAddrArray = new TPhysAddr[aNumPages]; |
|
1358 |
|
1359 NKern::ThreadLeaveCS(); |
|
1360 |
|
1361 if (iAddrArray == NULL) |
|
1362 { |
|
1363 return KErrNoMemory; |
|
1364 } |
|
1365 |
|
1366 // copy user side data to kernel side buffer. |
|
1367 if (aZoneIdCount > KMaxRamZones) |
|
1368 {// Too many IDs. |
|
1369 return KErrArgument; |
|
1370 } |
|
1371 kumemget(iZoneIdArray, aZoneIdList, sizeof(TUint) * aZoneIdCount); |
|
1372 |
|
1373 NKern::ThreadEnterCS(); |
|
1374 |
|
1375 TESTDEBUG(Kern::Printf("Allocating fixed pages")); |
|
1376 returnValue = Epoc::ZoneAllocPhysicalRam(iZoneIdArray, aZoneIdCount, aNumPages, iAddrArray); |
|
1377 |
|
1378 if (KErrNone != returnValue) |
|
1379 { |
|
1380 TESTDEBUG(Kern::Printf("Alloc was unsuccessful, r = %d\n", returnValue)); |
|
1381 TESTDEBUG(Kern::Printf("aNumPages = %d, aZoneID = %d", aNumPages, aZoneIdCount)); |
|
1382 delete[] iAddrArray; |
|
1383 iAddrArray = NULL; |
|
1384 goto exit; |
|
1385 } |
|
1386 iAddrArrayPages = aNumPages; |
|
1387 TESTDEBUG(Kern::Printf("iAddrArrayPages = %d, zones = %d", iAddrArrayPages, aZoneIdCount)); |
|
1388 |
|
1389 exit: |
|
1390 NKern::ThreadLeaveCS(); |
|
1391 return returnValue; |
|
1392 } |
|
1393 |
|
1394 // |
|
1395 // ZoneAllocToMany |
|
1396 // |
|
1397 // Call the overloaded Epoc::ZoneAllocPhysicalRam function on a number of zones |
|
1398 // |
|
1399 TInt DRamDefragFuncTestChannel::ZoneAllocToMany(TInt aZoneIndex, TInt aNumPages) |
|
1400 { |
|
1401 TInt r = ZoneAllocToManyArray(aZoneIndex, aNumPages); |
|
1402 if (r != KErrNone) |
|
1403 { |
|
1404 return r; |
|
1405 } |
|
1406 return ZoneAllocToMany2(aZoneIndex, aNumPages); |
|
1407 } |
|
1408 |
|
1409 // |
|
1410 // ZoneAllocToManyArray |
|
1411 // |
|
1412 // Allocate the arrays required to store the physical addresses of the different zones |
|
1413 // for the number of fixed pages to be allocated to that zone. |
|
1414 // |
|
1415 TInt DRamDefragFuncTestChannel::ZoneAllocToManyArray(TInt aZoneIndex, TInt aNumPages) |
|
1416 { |
|
1417 TInt returnValue = KErrNone; |
|
1418 NKern::ThreadEnterCS(); |
|
1419 |
|
1420 if (iAddrPtrArray == NULL) |
|
1421 { |
|
1422 iAddrPtrArray = (TPhysAddr**)Kern::AllocZ(sizeof(TPhysAddr*) * iZoneCount); |
|
1423 } |
|
1424 if (iNumPagesArray == NULL) |
|
1425 { |
|
1426 iNumPagesArray = (TInt *)Kern::AllocZ(sizeof(TInt) * iZoneCount); |
|
1427 } |
|
1428 |
|
1429 if (iAddrPtrArray[aZoneIndex] != NULL) |
|
1430 { |
|
1431 returnValue = KErrInUse; |
|
1432 goto exit; |
|
1433 } |
|
1434 |
|
1435 iAddrPtrArray[aZoneIndex] = (TPhysAddr *)Kern::AllocZ(sizeof(TPhysAddr) * aNumPages); |
|
1436 if (iAddrPtrArray[aZoneIndex] == NULL) |
|
1437 { |
|
1438 returnValue = KErrNoMemory; |
|
1439 goto exit; |
|
1440 } |
|
1441 |
|
1442 exit: |
|
1443 NKern::ThreadLeaveCS(); |
|
1444 return returnValue; |
|
1445 } |
|
1446 |
|
1447 // |
|
1448 // ZoneAllocToMany2 |
|
1449 // |
|
1450 // Call the overloaded Epoc::ZoneAllocPhysicalRam function on a number of zones |
|
1451 // This should only be invoked when iAddrPtrArray, iNumPagesArray and iAddrPtrArray[aZoneIndex] |
|
1452 // have already been allocated |
|
1453 // |
|
1454 TInt DRamDefragFuncTestChannel::ZoneAllocToMany2(TInt aZoneIndex, TInt aNumPages) |
|
1455 { |
|
1456 TInt returnValue = KErrNone; |
|
1457 struct SRamZoneConfig zoneConfig; |
|
1458 TUint zoneID = KRamZoneInvalidId; |
|
1459 |
|
1460 if (iAddrPtrArray == NULL || |
|
1461 iNumPagesArray == NULL || |
|
1462 iAddrPtrArray[aZoneIndex] == NULL) |
|
1463 { |
|
1464 return KErrGeneral; |
|
1465 } |
|
1466 |
|
1467 |
|
1468 NKern::ThreadEnterCS(); |
|
1469 |
|
1470 // Get the zone ID |
|
1471 Kern::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)aZoneIndex, (TAny*)&zoneConfig); |
|
1472 zoneID = zoneConfig.iZoneId; |
|
1473 returnValue = Epoc::ZoneAllocPhysicalRam(zoneID, aNumPages, iAddrPtrArray[aZoneIndex]); |
|
1474 |
|
1475 if (KErrNone != returnValue) |
|
1476 { |
|
1477 TESTDEBUG(Kern::Printf("Alloc was unsuccessful, r = %d\n", returnValue)); |
|
1478 Kern::Free(iAddrPtrArray[aZoneIndex]); |
|
1479 iAddrPtrArray[aZoneIndex] = NULL; |
|
1480 goto exit; |
|
1481 } |
|
1482 iNumPagesArray[aZoneIndex] = aNumPages; |
|
1483 |
|
1484 exit: |
|
1485 NKern::ThreadLeaveCS(); |
|
1486 return returnValue; |
|
1487 } |
|
1488 |
|
1489 // |
|
1490 // FreeZone |
|
1491 // |
|
1492 // Call the overloaded Epoc::FreePhysicalRam function |
|
1493 // |
|
1494 TInt DRamDefragFuncTestChannel::FreeZone(TInt aNumPages) |
|
1495 { |
|
1496 TInt returnValue = 0; |
|
1497 |
|
1498 if (iAddrArray == NULL) |
|
1499 { |
|
1500 return KErrCorrupt; |
|
1501 } |
|
1502 |
|
1503 NKern::ThreadEnterCS(); |
|
1504 |
|
1505 returnValue = Epoc::FreePhysicalRam(aNumPages, iAddrArray); |
|
1506 |
|
1507 Kern::Free(iAddrArray); |
|
1508 iAddrArray = NULL; |
|
1509 |
|
1510 NKern::ThreadLeaveCS(); |
|
1511 return returnValue; |
|
1512 } |
|
1513 |
|
1514 // |
|
1515 // FreeFromAllZones |
|
1516 // |
|
1517 // Call the overloaded Epoc::FreePhysicalRam function |
|
1518 // |
|
1519 TInt DRamDefragFuncTestChannel::FreeFromAllZones() |
|
1520 { |
|
1521 TInt returnValue = 0; |
|
1522 |
|
1523 if (iAddrPtrArray == NULL) |
|
1524 { |
|
1525 return KErrCorrupt; |
|
1526 } |
|
1527 |
|
1528 NKern::ThreadEnterCS(); |
|
1529 |
|
1530 for (TUint i=0; i<iZoneCount; i++) |
|
1531 { |
|
1532 if (iAddrPtrArray[i] != NULL) |
|
1533 { |
|
1534 returnValue = Epoc::FreePhysicalRam(iNumPagesArray[i], iAddrPtrArray[i]); |
|
1535 iAddrPtrArray[i] = NULL; |
|
1536 } |
|
1537 } |
|
1538 Kern::Free(iAddrPtrArray); |
|
1539 iAddrPtrArray = NULL; |
|
1540 |
|
1541 Kern::Free(iNumPagesArray); |
|
1542 iNumPagesArray = NULL; |
|
1543 |
|
1544 NKern::ThreadLeaveCS(); |
|
1545 return returnValue; |
|
1546 } |
|
1547 // |
|
1548 // FreeFromAddr |
|
1549 // |
|
1550 // Free a specific number of pages starting from a specific address |
|
1551 // |
|
1552 TInt DRamDefragFuncTestChannel::FreeFromAddr(TInt aNumPages, TUint32 aAddr) |
|
1553 { |
|
1554 TInt returnValue = 0; |
|
1555 TPhysAddr address = aAddr; |
|
1556 |
|
1557 NKern::ThreadEnterCS(); |
|
1558 |
|
1559 returnValue = Epoc::FreePhysicalRam(address, aNumPages << iPageShift); |
|
1560 |
|
1561 NKern::ThreadLeaveCS(); |
|
1562 |
|
1563 return returnValue; |
|
1564 } |
|
1565 |
|
1566 // |
|
1567 // FreeRam |
|
1568 // |
|
1569 // Returns the current free RAM available in bytes |
|
1570 // |
|
1571 TInt DRamDefragFuncTestChannel::FreeRam() |
|
1572 { |
|
1573 return Kern::FreeRamInBytes(); |
|
1574 } |
|
1575 |
|
1576 TInt DRamDefragFuncTestChannel::DoSetDebugFlag(TInt aState) |
|
1577 { |
|
1578 iDebug = aState; |
|
1579 return KErrNone; |
|
1580 } |
|
1581 |
|
1582 |
|
1583 // |
|
1584 // DefragCompleteDfc |
|
1585 // |
|
1586 // DFC callback called when a defrag operation has completed. |
|
1587 // |
|
1588 void DRamDefragFuncTestChannel::DefragCompleteDfc(TAny* aSelf) |
|
1589 { |
|
1590 // Just call non-static method |
|
1591 TESTDEBUG(Kern::Printf("Calling DefragCompleteDfc")); |
|
1592 ((DRamDefragFuncTestChannel*)aSelf)->DefragComplete(); |
|
1593 } |
|
1594 |
|
1595 |
|
1596 // |
|
1597 // DefragComplete |
|
1598 // |
|
1599 // Invoked by the DFC callback which is called when a defrag |
|
1600 // operation has completed. |
|
1601 // |
|
1602 void DRamDefragFuncTestChannel::DefragComplete() |
|
1603 { |
|
1604 TESTDEBUG(Kern::Printf(">DDefragChannel::DefragComplete - First Defrag")); |
|
1605 TInt result = iDefragRequest.Result(); |
|
1606 TESTDEBUG(Kern::Printf("complete code %d", result)); |
|
1607 |
|
1608 // Complete the request and close the handle to the driver |
|
1609 Kern::SemaphoreWait(*iDefragSemaphore); |
|
1610 |
|
1611 Kern::RequestComplete(iRequestThread, iCompleteReq, result); |
|
1612 iCompleteReq = NULL; |
|
1613 iRequestThread->Close(NULL); |
|
1614 iRequestThread = NULL; |
|
1615 |
|
1616 Kern::SemaphoreSignal(*iDefragSemaphore); |
|
1617 |
|
1618 ++iCounter; |
|
1619 if (iCounter == 1) |
|
1620 iOrder = 1; |
|
1621 else if (iCounter == 2 && iOrder == 2) |
|
1622 iOrder = 21; |
|
1623 else if (iCounter == 2 && iOrder == 3) |
|
1624 iOrder = 31; |
|
1625 else if (iCounter == 3 && iOrder == 23) |
|
1626 iOrder = 231; |
|
1627 else if (iCounter == 3 && iOrder == 32) |
|
1628 iOrder = 321; |
|
1629 TESTDEBUG(Kern::Printf("order = %d", iOrder)); |
|
1630 TESTDEBUG(Kern::Printf("<DDefragChannel::DefragComplete")); |
|
1631 |
|
1632 // Close the handle on this channel - WARNING this channel may be |
|
1633 // deleted immmediately after this call so don't access any members |
|
1634 AsyncClose(); |
|
1635 } |
|
1636 |
|
1637 |
|
1638 // |
|
1639 // Defrag2CompleteDfc |
|
1640 // |
|
1641 // DFC callback called when a defrag operation has completed. |
|
1642 // This is used for a particular test case when 3 |
|
1643 // defrags are queued at the same time. |
|
1644 // |
|
1645 void DRamDefragFuncTestChannel::Defrag2CompleteDfc(TAny* aSelf) |
|
1646 { |
|
1647 // Just call non-static method |
|
1648 TESTDEBUG(Kern::Printf("Calling DefragCompleteDfc")); |
|
1649 ((DRamDefragFuncTestChannel*)aSelf)->Defrag2Complete(); |
|
1650 } |
|
1651 |
|
1652 |
|
1653 // |
|
1654 // Defrag2Complete |
|
1655 // |
|
1656 // Invoked by the DFC callback which is called when a defrag |
|
1657 // operation has completed. This is used for a particular test case when 3 |
|
1658 // defrags are queued at the same time. |
|
1659 // |
|
1660 void DRamDefragFuncTestChannel::Defrag2Complete() |
|
1661 { |
|
1662 TESTDEBUG(Kern::Printf(">DDefragChannel::Defrag2Complete - Second Defrag")); |
|
1663 TInt result = iDefragRequest2.Result(); |
|
1664 TESTDEBUG(Kern::Printf("complete code %d", result)); |
|
1665 // Complete the request and close the handle to the driver |
|
1666 Kern::SemaphoreWait(*iDefragSemaphore); |
|
1667 |
|
1668 Kern::RequestComplete(iRequestThread2, iCompleteReq2, result); |
|
1669 iCompleteReq2 = NULL; |
|
1670 iRequestThread2->Close(NULL); |
|
1671 iRequestThread2 = NULL; |
|
1672 |
|
1673 Kern::SemaphoreSignal(*iDefragSemaphore); |
|
1674 |
|
1675 ++iCounter; |
|
1676 if (iCounter == 1) |
|
1677 iOrder = 2; |
|
1678 else if (iCounter == 2 && iOrder == 1) |
|
1679 iOrder = 12; |
|
1680 else if (iCounter == 2 && iOrder == 3) |
|
1681 iOrder = 32; |
|
1682 else if (iCounter == 3 && iOrder == 13) |
|
1683 iOrder = 132; |
|
1684 else if (iCounter == 3 && iOrder == 31) |
|
1685 iOrder = 312; |
|
1686 TESTDEBUG(Kern::Printf("order = %d", iOrder)); |
|
1687 TESTDEBUG(Kern::Printf("<DDefragChannel::DefragComplete")); |
|
1688 |
|
1689 // Close the handle on this channel - WARNING this channel may be |
|
1690 // deleted immmediately after this call so don't access any members |
|
1691 AsyncClose(); |
|
1692 } |
|
1693 |
|
1694 |
|
1695 // |
|
1696 // Defrag3CompleteDfc |
|
1697 // |
|
1698 // DFC callback called when a defrag operation has completed. |
|
1699 // This is used for a particular test case when 3 |
|
1700 // defrags are queued at the same time. |
|
1701 // |
|
1702 void DRamDefragFuncTestChannel::Defrag3CompleteDfc(TAny* aSelf) |
|
1703 { |
|
1704 // Just call non-static method |
|
1705 TESTDEBUG(Kern::Printf("Calling DefragCompleteDfc")); |
|
1706 ((DRamDefragFuncTestChannel*)aSelf)->Defrag3Complete(); |
|
1707 } |
|
1708 |
|
1709 // |
|
1710 // Defrag3Complete |
|
1711 // |
|
1712 // Invoked by the DFC callback which is called when a defrag |
|
1713 // operation has completed. This is used for a particular test case when 3 |
|
1714 // defrags are queued at the same time. |
|
1715 // |
|
1716 void DRamDefragFuncTestChannel::Defrag3Complete() |
|
1717 { |
|
1718 TESTDEBUG(Kern::Printf(">DDefragChannel::DefragComplete - Third Defrag")); |
|
1719 TInt result = iDefragRequest3.Result(); |
|
1720 TESTDEBUG(Kern::Printf("complete code %d", result)); |
|
1721 |
|
1722 Kern::SemaphoreWait(*iDefragSemaphore); |
|
1723 |
|
1724 Kern::RequestComplete(iRequestThread3, iCompleteReq3, result); |
|
1725 iCompleteReq3 = NULL; |
|
1726 iRequestThread3->Close(NULL); |
|
1727 iRequestThread3 = NULL; |
|
1728 |
|
1729 Kern::SemaphoreSignal(*iDefragSemaphore); |
|
1730 |
|
1731 |
|
1732 ++iCounter; |
|
1733 if (iCounter == 1) |
|
1734 iOrder = 3; |
|
1735 else if (iCounter == 2 && iOrder == 1) |
|
1736 iOrder = 13; |
|
1737 else if (iCounter == 2 && iOrder == 2) |
|
1738 iOrder = 23; |
|
1739 else if (iCounter == 3 && iOrder == 12) |
|
1740 iOrder = 123; |
|
1741 else if (iCounter == 3 && iOrder == 21) |
|
1742 iOrder = 213; |
|
1743 TESTDEBUG(Kern::Printf("order = %d", iOrder)); |
|
1744 TESTDEBUG(Kern::Printf("<DDefragChannel::DefragComplete")); |
|
1745 |
|
1746 // Close the handle on this channel - WARNING this channel may be |
|
1747 // deleted immmediately after this call so don't access any members |
|
1748 AsyncClose(); |
|
1749 } |
|
1750 |
|
1751 // |
|
1752 // ResetDriver |
|
1753 // |
|
1754 // Reset all the member variables in the driver |
|
1755 // |
|
1756 TInt DRamDefragFuncTestChannel::ResetDriver() |
|
1757 { |
|
1758 iDebug = 0; |
|
1759 iThreadCounter = 1; |
|
1760 iCounter = 0; |
|
1761 iOrder = 0; |
|
1762 FreeAllFixedPages(); |
|
1763 |
|
1764 return KErrNone; |
|
1765 } |