|
1 // leak.cpp |
|
2 // |
|
3 // Copyright (c) 2007 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "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 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include "leak.h" |
|
14 #include <fshell/common.mmh> |
|
15 |
|
16 const TInt KMinChunkSize = 4 * 1024; |
|
17 const TInt KMaxChunkSize = 512 * 1024 * 1024; |
|
18 |
|
19 CCommandBase* CCmdLeak::NewLC() |
|
20 { |
|
21 CCmdLeak* self = new(ELeave) CCmdLeak(); |
|
22 CleanupStack::PushL(self); |
|
23 self->BaseConstructL(); |
|
24 return self; |
|
25 } |
|
26 |
|
27 CCmdLeak::~CCmdLeak() |
|
28 { |
|
29 iChunk.Close(); |
|
30 if (iChunkHeap) |
|
31 { |
|
32 iChunkHeap->Reset(); |
|
33 iChunkHeap->Close(); |
|
34 } |
|
35 } |
|
36 |
|
37 CCmdLeak::CCmdLeak() |
|
38 { |
|
39 } |
|
40 |
|
41 const TDesC& CCmdLeak::Name() const |
|
42 { |
|
43 _LIT(KName, "leak"); |
|
44 return KName; |
|
45 } |
|
46 |
|
47 void CCmdLeak::DoRunL() |
|
48 { |
|
49 if ((iAmount < 0) || (iIncrementAmount < 0)) |
|
50 { |
|
51 User::Leave(KErrArgument); |
|
52 } |
|
53 |
|
54 if (iArguments.IsPresent(0)) |
|
55 { |
|
56 if (iIncrementAmount == 0) |
|
57 { |
|
58 iIncrementAmount = iAmount; |
|
59 } |
|
60 } |
|
61 else |
|
62 { |
|
63 iAmount = KMaxTInt; |
|
64 if (iIncrementAmount == 0) |
|
65 { |
|
66 iIncrementAmount = KMinChunkSize; |
|
67 } |
|
68 } |
|
69 |
|
70 if (iUseHeap) |
|
71 { |
|
72 iChunkHeap = UserHeap::ChunkHeap(NULL, KMinChunkSize, 256*1024*1024); |
|
73 if (!iChunkHeap) LeaveIfErr(KErrNoMemory, _L("Couldn't create chunk heap")); |
|
74 } |
|
75 else |
|
76 { |
|
77 if (iIncrementAmount & 4095) LeaveIfErr(KErrArgument, _L("increment-amount must be a multiple of 4096")); |
|
78 TInt err = iChunk.CreateLocal(KMinChunkSize, KMaxChunkSize); |
|
79 LeaveIfErr(err, _L("Failed to create local chunk")); |
|
80 } |
|
81 |
|
82 RIoConsoleWriteHandle stdout = Stdout(); |
|
83 stdout.SetCursorHeight(0); |
|
84 TInt err = KErrNone; |
|
85 do |
|
86 { |
|
87 err = LeakStep(Min(iIncrementAmount, iAmount - iCurrentLeak)); |
|
88 if (iVerbose) |
|
89 { |
|
90 Write(_L("\r")); |
|
91 stdout.ClearToEndOfLine(); |
|
92 Printf(_L("Allocated %d: %d"), iCurrentLeak, err); |
|
93 } |
|
94 if (err && iRetry && iIncrementAmount > 4) |
|
95 { |
|
96 // Keep going with a smaller increment |
|
97 err = KErrNone; |
|
98 iIncrementAmount /= 2; |
|
99 continue; |
|
100 } |
|
101 |
|
102 if (iRate > 0) |
|
103 { |
|
104 User::After(iRate * 1000); |
|
105 } |
|
106 } |
|
107 while ((err == KErrNone) && (iCurrentLeak < iAmount)); |
|
108 |
|
109 if (err == KErrNoMemory) |
|
110 { |
|
111 Printf(_L("Out of memory. ")); |
|
112 } |
|
113 else if (err) |
|
114 { |
|
115 Printf(_L("Error: %d. "), err); |
|
116 } |
|
117 |
|
118 Printf(_L("\r\nLeaked %d bytes. Press any key to exit (and free the memory).\r\n"), iCurrentLeak); |
|
119 |
|
120 RIoConsoleReadHandle stdin = Stdin(); |
|
121 stdin.ReadKey(); |
|
122 } |
|
123 |
|
124 void CCmdLeak::OptionsL(RCommandOptionList& aOptions) |
|
125 { |
|
126 _LIT(KOptVerbose, "verbose"); |
|
127 aOptions.AppendBoolL(iVerbose, KOptVerbose); |
|
128 |
|
129 _LIT(KOptIncrementAmount, "increment-amount"); |
|
130 aOptions.AppendIntL(iIncrementAmount, KOptIncrementAmount); |
|
131 |
|
132 _LIT(KOptRate, "rate"); |
|
133 aOptions.AppendUintL(iRate, KOptRate); |
|
134 |
|
135 _LIT(KOptUseHeap, "heap"); |
|
136 aOptions.AppendBoolL(iUseHeap, KOptUseHeap); |
|
137 |
|
138 _LIT(KOptRetry, "retry"); |
|
139 aOptions.AppendBoolL(iRetry, KOptRetry); |
|
140 } |
|
141 |
|
142 void CCmdLeak::ArgumentsL(RCommandArgumentList& aArguments) |
|
143 { |
|
144 _LIT(KArgAmount, "amount"); |
|
145 aArguments.AppendIntL(iAmount, KArgAmount); |
|
146 } |
|
147 |
|
148 |
|
149 #ifdef EXE_BUILD |
|
150 EXE_BOILER_PLATE(CCmdLeak) |
|
151 #endif |
|
152 |
|
153 TInt CCmdLeak::LeakStep(TInt aAmount) |
|
154 { |
|
155 TInt err = KErrNone; |
|
156 if (iChunkHeap) |
|
157 { |
|
158 TAny* cell = iChunkHeap->Alloc(aAmount); |
|
159 if (!cell) err = KErrNoMemory; |
|
160 } |
|
161 else |
|
162 { |
|
163 if (aAmount < 4096) err = KErrNoMemory; // implies we're retrying - unlike the others that keep retrying down to 4 bytes, we have to stop at page granularity |
|
164 else err = iChunk.Adjust(iCurrentLeak + aAmount); |
|
165 } |
|
166 |
|
167 if (!err) iCurrentLeak += aAmount; |
|
168 return err; |
|
169 } |