|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "MemSpyDriverLogChanHeapDataKernel.h" |
|
19 |
|
20 // System includes |
|
21 #include <u32hal.h> |
|
22 #include <e32rom.h> |
|
23 #include <memspy/driver/memspydriverconstants.h> |
|
24 #include <memspy/driver/memspydriverobjectsshared.h> |
|
25 |
|
26 // Shared includes |
|
27 #include "MemSpyDriverOpCodes.h" |
|
28 #include "MemSpyDriverObjectsInternal.h" |
|
29 |
|
30 // User includes |
|
31 #include "MemSpyDriverHeap.h" |
|
32 #include "MemSpyDriverUtils.h" |
|
33 #include "MemSpyDriverDevice.h" |
|
34 #include "MemSpyDriverOSAdaption.h" |
|
35 #include "MemSpyDriverHeapWalker.h" |
|
36 #include "MemSpyDriverUserEventMonitor.h" |
|
37 #include "MemSpyDriverSuspensionManager.h" |
|
38 |
|
39 DMemSpyDriverLogChanHeapDataKernel::DMemSpyDriverLogChanHeapDataKernel( DMemSpyDriverDevice& aDevice, DThread& aThread ) |
|
40 : DMemSpyDriverLogChanHeapDataBase( aDevice, aThread ), iKernelHeap( aDevice.OSAdaption() ) |
|
41 { |
|
42 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::DMemSpyDriverLogChanHeapDataKernel() - this: 0x%08x", this )); |
|
43 } |
|
44 |
|
45 TInt DMemSpyDriverLogChanHeapDataKernel::Request( TInt aFunction, TAny* a1, TAny* a2 ) |
|
46 { |
|
47 TInt r = DMemSpyDriverLogChanHeapBase::Request( aFunction, a1, a2 ); |
|
48 if ( r == KErrNone ) |
|
49 { |
|
50 if ( aFunction != EMemSpyDriverOpCodeHeapKernelDataFetchCellList ) |
|
51 { |
|
52 ReleaseCellList(); |
|
53 } |
|
54 // |
|
55 switch( aFunction ) |
|
56 { |
|
57 case EMemSpyDriverOpCodeHeapKernelDataGetInfo: |
|
58 r = GetInfoData( (TMemSpyDriverInternalHeapRequestParameters*) a1 ); |
|
59 break; |
|
60 case EMemSpyDriverOpCodeHeapKernelDataGetIsDebugKernel: |
|
61 r = GetIsDebugKernel(a1); |
|
62 break; |
|
63 case EMemSpyDriverOpCodeHeapKernelDataFetchCellList: |
|
64 r = FetchCellList( (TDes8*) a1 ); |
|
65 break; |
|
66 case EMemSpyDriverOpCodeHeapKernelDataCopyHeap: |
|
67 r = MakeKernelHeapCopy(); |
|
68 break; |
|
69 case EMemSpyDriverOpCodeHeapKernelDataGetFull: |
|
70 r = DMemSpyDriverLogChanHeapDataBase::GetFullData( (TMemSpyDriverInternalHeapDataParams*) a1 ); |
|
71 break; |
|
72 case EMemSpyDriverOpCodeHeapKernelDataFreeHeapCopy: |
|
73 FreeKernelHeapCopy(); |
|
74 break; |
|
75 |
|
76 default: |
|
77 r = KErrNotSupported; |
|
78 break; |
|
79 } |
|
80 } |
|
81 // |
|
82 return r; |
|
83 } |
|
84 |
|
85 |
|
86 TBool DMemSpyDriverLogChanHeapDataKernel::IsHandler( TInt aFunction ) const |
|
87 { |
|
88 return ( aFunction > EMemSpyDriverOpCodeHeapKernelDataBase && aFunction < EMemSpyDriverOpCodeHeapKernelDataEnd ); |
|
89 } |
|
90 |
|
91 TInt DMemSpyDriverLogChanHeapDataKernel::GetInfoData( TMemSpyDriverInternalHeapRequestParameters* aParams ) |
|
92 { |
|
93 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData() - START" ) ); |
|
94 |
|
95 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &iHeapInfoParams, sizeof(TMemSpyDriverInternalHeapRequestParameters) ); |
|
96 if ( r != KErrNone ) |
|
97 { |
|
98 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoDataUser - params read error: %d", r)); |
|
99 } |
|
100 else |
|
101 { |
|
102 if (iHeapInfoParams.iUseKernelHeapCopy) |
|
103 { |
|
104 __ASSERT_ALWAYS( iKernelHeap.IsOpen(), MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapKernelCopyExpected ) ); |
|
105 r = DMemSpyDriverLogChanHeapDataKernel::GetInfoData(iKernelHeap); |
|
106 } |
|
107 else |
|
108 { |
|
109 RMemSpyDriverRHeapKernelInPlace rHeap(OSAdaption()); |
|
110 r = rHeap.OpenKernelHeap(); |
|
111 if ( r == KErrNone ) |
|
112 { |
|
113 r = DMemSpyDriverLogChanHeapDataKernel::GetInfoData(rHeap); |
|
114 } |
|
115 else |
|
116 { |
|
117 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData() - open err: %d", r ) ); |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData() - END - ret: %d", r) ); |
|
123 return r; |
|
124 } |
|
125 |
|
126 TInt DMemSpyDriverLogChanHeapDataKernel::GetInfoData(RMemSpyDriverRHeapBase& aHeap) |
|
127 { |
|
128 NKern::ThreadEnterCS(); |
|
129 |
|
130 TInt r = KErrNone; |
|
131 |
|
132 // This object holds all of the info we will accumulate for the client. |
|
133 TMemSpyHeapInfo masterHeapInfo; |
|
134 masterHeapInfo.SetType(aHeap.GetTypeFromHelper()); |
|
135 masterHeapInfo.SetTid( 2 ); |
|
136 masterHeapInfo.SetPid( 1 ); |
|
137 |
|
138 // This is the RHeap-specific object that contains all RHeap info |
|
139 TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap(); |
|
140 |
|
141 // We must walk the heap in order to build statistics |
|
142 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - calling heap walker constructor...")); |
|
143 RMemSpyDriverHeapWalker heapWalker(aHeap); |
|
144 if (iHeapInfoParams.iBuildFreeCellList || iHeapInfoParams.iBuildAllocCellList) |
|
145 { |
|
146 heapWalker.SetObserver( this ); |
|
147 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - collecting cells")); |
|
148 } |
|
149 else |
|
150 { |
|
151 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - not collecting cells")); |
|
152 } |
|
153 |
|
154 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - starting traversal..." )); |
|
155 |
|
156 #if defined( TRACE_TYPE_KERNELHEAP ) |
|
157 heapWalker.SetPrintDebug(); |
|
158 #endif |
|
159 if (r == KErrNone) r = heapWalker.Traverse(); |
|
160 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - finished traversal - err: %d", r )); |
|
161 |
|
162 TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); |
|
163 heapWalker.CopyStatsTo( rHeapStats ); |
|
164 |
|
165 // Get remaining meta data that isn't stored elsewhere |
|
166 TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); |
|
167 TFullName chunkName; |
|
168 aHeap.Chunk().FullName(chunkName); |
|
169 rHeapMetaData.SetChunkName(chunkName); |
|
170 rHeapMetaData.SetChunkSize( (TUint) aHeap.Chunk().Size() ); |
|
171 rHeapMetaData.SetChunkHandle( &aHeap.Chunk() ); |
|
172 rHeapMetaData.SetChunkBaseAddress( OSAdaption().DChunk().GetBase(aHeap.Chunk()) ); |
|
173 rHeapMetaData.SetDebugAllocator(aHeap.Helper()->AllocatorIsUdeb()); |
|
174 rHeapMetaData.SetUserThread( EFalse ); |
|
175 rHeapMetaData.SetSharedHeap( ETrue ); |
|
176 rHeapMetaData.iHeapSize = aHeap.Helper()->CommittedSize(); |
|
177 rHeapMetaData.iAllocatorAddress = (TAny*)aHeap.Helper()->AllocatorAddress(); |
|
178 rHeapMetaData.iMinHeapSize = aHeap.Helper()->MinCommittedSize(); |
|
179 rHeapMetaData.iMaxHeapSize = aHeap.Helper()->MaxCommittedSize(); |
|
180 |
|
181 PrintHeapInfo( masterHeapInfo ); |
|
182 |
|
183 // Write free cells if requested |
|
184 if ( r == KErrNone && (iHeapInfoParams.iBuildFreeCellList || iHeapInfoParams.iBuildAllocCellList)) |
|
185 { |
|
186 r = PrepareCellListTransferBuffer(); |
|
187 } |
|
188 |
|
189 if ( r >= KErrNone ) |
|
190 { |
|
191 // Write results back to user-side |
|
192 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData - writing to user-side...")); |
|
193 TMemSpyHeapInfo* kernelMasterInfo = iHeapInfoParams.iMasterInfo; |
|
194 const TInt error = Kern::ThreadRawWrite( &ClientThread(), kernelMasterInfo, &masterHeapInfo, sizeof(TMemSpyHeapInfo) ); |
|
195 if ( error < 0 ) |
|
196 { |
|
197 r = error; |
|
198 } |
|
199 } |
|
200 |
|
201 NKern::ThreadLeaveCS(); |
|
202 |
|
203 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetInfoData() - END - ret: %d", r) ); |
|
204 return r; |
|
205 } |
|
206 |
|
207 TInt DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel(TAny* aResult) |
|
208 { |
|
209 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel() - START") ); |
|
210 |
|
211 TInt r = KErrNone; |
|
212 TBool debugKernel = EFalse; |
|
213 |
|
214 NKern::ThreadEnterCS(); |
|
215 |
|
216 RMemSpyDriverRHeapKernelInPlace rHeap(OSAdaption()); |
|
217 r = rHeap.OpenKernelHeap(); |
|
218 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel() - open kernel heap returned: %d", r) ); |
|
219 |
|
220 if ( r == KErrNone ) |
|
221 { |
|
222 debugKernel = rHeap.Helper()->AllocatorIsUdeb(); |
|
223 |
|
224 // Tidy up |
|
225 rHeap.Close(); |
|
226 } |
|
227 |
|
228 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel() - debugKernel: %d", debugKernel) ); |
|
229 |
|
230 // Write back to user-land |
|
231 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel() - writing to user-side...") ); |
|
232 r = Kern::ThreadRawWrite( &ClientThread(), aResult, &debugKernel, sizeof(TBool) ); |
|
233 |
|
234 NKern::ThreadLeaveCS(); |
|
235 |
|
236 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetIsDebugKernel() - END - ret: %d", r) ); |
|
237 return r; |
|
238 } |
|
239 |
|
240 TInt DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap( RMemSpyDriverRHeapKernelFromCopy& aHeap ) |
|
241 { |
|
242 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - START") ); |
|
243 |
|
244 RAllocatorHelper kernelHeapHelper; |
|
245 TInt r = kernelHeapHelper.OpenKernelHeap(); |
|
246 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - open err: %d", r ) ); |
|
247 if ( r == KErrNone ) |
|
248 { |
|
249 DChunk* kernelChunk = kernelHeapHelper.OpenUnderlyingChunk(); |
|
250 if (kernelChunk) { |
|
251 // TODO can we lock just the kernel heap here to avoid the problem below? |
|
252 |
|
253 // Make a new chunk that we can copy the kernel heap into. We cannot lock the system the entire time |
|
254 // we need to do this, therefore there is no guarantee that the chunk will be large enough to hold the |
|
255 // (current) heap data at the time we need to make the copy. We oversize the chunk by 1mb in the "hope" |
|
256 // that it will be enough... :( |
|
257 TChunkCreateInfo info; |
|
258 info.iType = TChunkCreateInfo::ESharedKernelSingle; |
|
259 info.iMaxSize = kernelChunk->MaxSize() + ( 1024 * 1024 ); |
|
260 info.iOwnsMemory = ETrue; // Use memory from system's free pool |
|
261 info.iDestroyedDfc = NULL; |
|
262 #ifdef __EPOC32__ |
|
263 info.iMapAttr = (TInt)EMapAttrFullyBlocking; // Full caching |
|
264 #endif |
|
265 |
|
266 // Holds a copy of the client's heap chunk |
|
267 DChunk* heapCopyChunk; |
|
268 TLinAddr heapCopyChunkAddress; |
|
269 TUint32 heapCopyChunkMappingAttributes; |
|
270 r = Kern::ChunkCreate( info, heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); |
|
271 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - creating chunk returned: %d", r)); |
|
272 |
|
273 // Unfortunately we have to commit every page in the copied chunk irrespective of whether that's the case |
|
274 // with the kernel chunk due to mutex ordering enforced by the kernel. See the note about this below. |
|
275 // This results in waste but with the way the kernel heap currently works it's not too bad. |
|
276 // TODO fix this so it's more generic and doesn't rely on details of how the kernel heap works. |
|
277 r = Kern::ChunkCommit(heapCopyChunk, 0, info.iMaxSize); |
|
278 |
|
279 // Keep track of the pages we need to de-commit from the copy |
|
280 // We allocate enough space here so we don't attempt to resise |
|
281 TLinAddr* pageAddrsToDeCommit = new TLinAddr[info.iMaxSize / KPageSize]; |
|
282 TUint pageAddrsToDeCommitIndex = 0; |
|
283 |
|
284 TBool cleanupCopyChunk = EFalse; |
|
285 if ( r == KErrNone ) |
|
286 { |
|
287 HBuf8* data = HBuf8::New(KPageSize); |
|
288 if (data) |
|
289 { |
|
290 TAny* dataPtr = (TAny*) data->Ptr(); |
|
291 |
|
292 r = kernelHeapHelper.TryLock(); |
|
293 TInt actualKernelChunkSize = kernelChunk->Size(); |
|
294 |
|
295 if ( r == KErrNone ) |
|
296 { |
|
297 |
|
298 // We now attempt to copy the kernel heap page by page |
|
299 // This is because the kernel chunk is disconnected and hence can have pages |
|
300 // in the middle of the heap that havent' been committed yet. |
|
301 // TODO can we make this more efficient? |
|
302 TInt err = KErrNone; |
|
303 TUint8* kernChunkAddr = kernelChunk->Base(); |
|
304 TUint8* copyChunkAddr = (TUint8*) heapCopyChunkAddress; |
|
305 while(err == KErrNone && |
|
306 kernChunkAddr < kernelChunk->Base() + kernelChunk->MaxSize()) |
|
307 { |
|
308 XTRAP(err, XT_DEFAULT, memcpy(dataPtr, kernChunkAddr, KPageSize)); |
|
309 if (!err) |
|
310 { |
|
311 // It'd be nice if we could just commit the pages of the copy chunk to match |
|
312 // the commited pages in the kernel heap here but that violates the following |
|
313 // mutex ordering: |
|
314 // mutex KernHeap order 8 [from kernelHeapHelper.TryLock()] vs |
|
315 // mutex MemoryObjectMutex1 order 9 [from Kern::ChunkCommit()] |
|
316 memcpy(copyChunkAddr, dataPtr, KPageSize); |
|
317 } |
|
318 else |
|
319 { |
|
320 // This page in the kernel heap wasn't committed so we can continue onto the next |
|
321 err = KErrNone; |
|
322 // but we do need to remember this so ... |
|
323 pageAddrsToDeCommit[pageAddrsToDeCommitIndex++] = (TLinAddr) copyChunkAddr; |
|
324 } |
|
325 kernChunkAddr += KPageSize; |
|
326 copyChunkAddr += KPageSize; |
|
327 } |
|
328 kernelHeapHelper.TryUnlock(); |
|
329 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - copied kernel heap data" )); |
|
330 |
|
331 // Now remove the bits we didn't actually need to commit |
|
332 for(TUint i=0; i < pageAddrsToDeCommitIndex; i++) |
|
333 { |
|
334 r = heapCopyChunk->Decommit(pageAddrsToDeCommit[i], KPageSize); |
|
335 if (r != KErrNone) |
|
336 { |
|
337 break; |
|
338 } |
|
339 } |
|
340 if (r != KErrNone) |
|
341 { |
|
342 TInt oversizedEndLength = heapCopyChunk->Size() - actualKernelChunkSize; |
|
343 r = heapCopyChunk->Decommit(actualKernelChunkSize, oversizedEndLength); |
|
344 } |
|
345 |
|
346 if (r == KErrNone) |
|
347 { |
|
348 // Transfer ownership of the copy heap chunk to the heap object. |
|
349 TInt offset = (TInt) heapCopyChunkAddress - (TInt) kernelChunk->Base(); |
|
350 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - heapCopyChunkAddress: 0x%08x, kernel chunk base: 0x%08x", |
|
351 heapCopyChunkAddress, kernelChunk->Base())); |
|
352 r = aHeap.AssociateWithKernelChunk( kernelChunk, heapCopyChunk, heapCopyChunkAddress, offset ); |
|
353 } |
|
354 else |
|
355 { |
|
356 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - failed to decommit all the unnecessary pages from the copy chunk - %d", r )); |
|
357 cleanupCopyChunk = ETrue; |
|
358 } |
|
359 } |
|
360 else |
|
361 { |
|
362 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - failed to lock the kernel heap" )); |
|
363 cleanupCopyChunk = ETrue; |
|
364 } |
|
365 |
|
366 delete data; |
|
367 } |
|
368 else |
|
369 { |
|
370 TRACE_KH( Kern::Printf("Failed to allocate a 4K buffer" ) ); |
|
371 r = KErrNoMemory; |
|
372 cleanupCopyChunk = ETrue; |
|
373 } |
|
374 } |
|
375 else |
|
376 { |
|
377 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - copy chunk create error: %d", r ) ); |
|
378 cleanupCopyChunk = ETrue; |
|
379 } |
|
380 |
|
381 if (cleanupCopyChunk) |
|
382 { |
|
383 NKern::ThreadEnterCS(); |
|
384 Kern::ChunkClose( heapCopyChunk ); |
|
385 heapCopyChunk = NULL; |
|
386 NKern::ThreadLeaveCS(); |
|
387 } |
|
388 |
|
389 delete[] pageAddrsToDeCommit; |
|
390 pageAddrsToDeCommit = NULL; |
|
391 } |
|
392 else |
|
393 { |
|
394 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - failed to open the kernel chunk" ) ); |
|
395 } |
|
396 } |
|
397 else |
|
398 { |
|
399 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - failed to open the kernel heap: %d", r ) ); |
|
400 } |
|
401 |
|
402 kernelHeapHelper.Close(); |
|
403 |
|
404 if ( r != KErrNone ) |
|
405 { |
|
406 aHeap.Close(); // also deals with the chunk |
|
407 } |
|
408 |
|
409 |
|
410 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::OpenKernelHeap(CP) - END - ret: %d", r ) ); |
|
411 return r; |
|
412 } |
|
413 |
|
414 TInt DMemSpyDriverLogChanHeapDataKernel::MakeKernelHeapCopy() |
|
415 { |
|
416 // First phase is to |
|
417 // a) Open kernel heap |
|
418 // b) Make a copy of the heap data |
|
419 // |
|
420 // The driver leaves kernel context with the copy of the kernel heap still associated with MemSpy's process. |
|
421 // The second driver call will copy the chunk data to user side and release the kernel side chunk. |
|
422 |
|
423 iKernelHeap.Reset(); |
|
424 NKern::ThreadEnterCS(); |
|
425 |
|
426 TInt r = OpenKernelHeap( iKernelHeap ); |
|
427 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullDataInit() - open err: %d", r)); |
|
428 |
|
429 NKern::ThreadLeaveCS(); |
|
430 |
|
431 TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullDataInit() - END - ret: %d", r)); |
|
432 return r; |
|
433 } |
|
434 |
|
435 void DMemSpyDriverLogChanHeapDataKernel::FreeKernelHeapCopy() |
|
436 { |
|
437 iKernelHeap.Close(); |
|
438 } |
|
439 |
|
440 TInt DMemSpyDriverLogChanHeapDataKernel::GetFullData( TMemSpyDriverInternalHeapDataParams& aParams ) |
|
441 { |
|
442 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullData() - START") ); |
|
443 |
|
444 TInt r = OpenTempObject( aParams.iTid, EThread ); |
|
445 if ( r != KErrNone ) |
|
446 { |
|
447 Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullData() - END - thread not found"); |
|
448 return r; |
|
449 } |
|
450 // Don't need to check if the kernel heap contains DRM data unlike for user heaps |
|
451 |
|
452 DThread* thread = (DThread*) TempObject(); |
|
453 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullData - thread: %O", thread) ); |
|
454 |
|
455 r = DoGetFullData(aParams, thread, iKernelHeap); |
|
456 |
|
457 CloseTempObject(); |
|
458 |
|
459 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataKernel::GetFullData() - END - ret: %d", r) ); |
|
460 return r; |
|
461 } |