|
1 // Copyright (c) 2007-2010 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 "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 // Trace Core |
|
15 // |
|
16 |
|
17 #include <kernel/kernel.h> |
|
18 |
|
19 #include "TraceCoreMediaSWriter.h" |
|
20 #include "TraceCoreMediaIf.h" |
|
21 #include "TraceCoreConstants.h" |
|
22 #include "TraceCore.h" |
|
23 #include "TraceCoreSendReceive.h" |
|
24 #include "TraceCoreDebug.h" |
|
25 |
|
26 |
|
27 //- Internal definitions ---------------------------------------------------- |
|
28 #ifdef MEDIA_WRITER_STATISTICS |
|
29 |
|
30 /** |
|
31 * Collects statistics about the media writer |
|
32 */ |
|
33 class TMediaSWriterStatistics |
|
34 { |
|
35 public: |
|
36 TUint32 iTraces; // Number of traces received |
|
37 TUint32 iSent; // Number of traces sent |
|
38 TUint32 iFailed; // Number of traces failed to send |
|
39 TUint32 iMissed; // Number of traces missed due to not enough buffers |
|
40 TUint32 iSleepCount; // Number of times the threads have slept waiting for buffers |
|
41 TUint32 iCannotSleepCount; // Number of times a thread could not be slept when it should |
|
42 TUint32 iBlockCount; // Number of times a thread has been blocked waiting for buffers |
|
43 TUint32 iCannotBlockCount; // Number of times a thread could not be blocked when it should |
|
44 TUint32 iWaitDidNotHelp; // Number of waits that did not help |
|
45 TUint32 iMinFreeBuffers; // Minimum number of free buffers since boot |
|
46 TUint32 iInvalidContextTrace; // Number of IRQ / IDFC traces ignored |
|
47 TUint32 iIdlePings; // Statistics are written after some idle time |
|
48 TBool iStatisticsChanged; // Flags indicating change in statistics |
|
49 }; |
|
50 |
|
51 /** |
|
52 * Macro to wrap statistics-related code |
|
53 */ |
|
54 #define STATS( x ) x |
|
55 |
|
56 /** |
|
57 * Initializes the statistics structure |
|
58 */ |
|
59 TBool DTraceCoreMediaSWriter::InitStatistics() |
|
60 { |
|
61 iStatistics = new TMediaSWriterStatistics(); |
|
62 return iStatistics != NULL; |
|
63 } |
|
64 |
|
65 #else |
|
66 |
|
67 /** |
|
68 * Empty class for statistics if flag is not set |
|
69 */ |
|
70 class TMediaSWriterStatistics {}; |
|
71 |
|
72 #define STATS( x ) |
|
73 |
|
74 #endif |
|
75 |
|
76 |
|
77 /** |
|
78 * Max length of one trace |
|
79 */ |
|
80 const TUint32 KMaxBufLength = 256; |
|
81 |
|
82 /** |
|
83 * Number of traces that can be buffered |
|
84 */ |
|
85 const TUint32 KBufCount = 1; |
|
86 |
|
87 /** |
|
88 * Constructor |
|
89 */ |
|
90 EXPORT_C DTraceCoreMediaSWriter::DTraceCoreMediaSWriter() |
|
91 : DTraceCoreWriter( EWriterTypeUSBPhonet ) |
|
92 , iSendDfc( DTraceCoreMediaSWriter::SendDfc, this, DTraceCore::GetActivationQ(), KDefaultDfcPriority ) |
|
93 , iSendTimerActive( EFalse ) |
|
94 , iFirstFreeBuffer( NULL ) |
|
95 , iFirstReadyBuffer( NULL ) |
|
96 , iLastReadyBuffer( NULL ) |
|
97 , iTraceBuffers( NULL ) |
|
98 , iFreeBuffers( KBufCount ) |
|
99 , iSenderThread( NULL ) |
|
100 , iLastTraceSent( 0 ) |
|
101 , iStatistics( NULL ) |
|
102 { |
|
103 // No implementation in constructor |
|
104 } |
|
105 |
|
106 |
|
107 /** |
|
108 * Destructor |
|
109 */ |
|
110 EXPORT_C DTraceCoreMediaSWriter::~DTraceCoreMediaSWriter() |
|
111 { |
|
112 // Delete all trace buffers |
|
113 for ( TUint i = 0; i < KBufCount; i++ ) |
|
114 { |
|
115 delete[] iTraceBuffers[ i ].iBuffer; |
|
116 } |
|
117 |
|
118 delete[] iTraceBuffers; |
|
119 delete iStatistics; |
|
120 } |
|
121 |
|
122 |
|
123 /** |
|
124 * Registers this writer to TraceCore |
|
125 * |
|
126 * @return KErrNone if successful |
|
127 */ |
|
128 EXPORT_C TInt DTraceCoreMediaSWriter::Register() |
|
129 { |
|
130 // Media writer uses the media interface from SendReceive |
|
131 TInt retval( KErrGeneral ); |
|
132 |
|
133 // Get TraceCore |
|
134 DTraceCore* traceCore = DTraceCore::GetInstance(); |
|
135 if ( traceCore != NULL ) |
|
136 { |
|
137 |
|
138 // Get MediaWriter interface |
|
139 DTraceCoreMediaIf* writerIf = traceCore->GetSendReceive().GetMediaWriterIf(); |
|
140 if ( writerIf != NULL ) |
|
141 { |
|
142 // Allocates memory for the trace buffers |
|
143 TBool memOK = ETrue; |
|
144 STATS( memOK = InitStatistics() ); |
|
145 if(memOK) |
|
146 { |
|
147 iTraceBuffers = new TTraceBuffer[ KBufCount ]; |
|
148 } |
|
149 if (iTraceBuffers == NULL) |
|
150 { |
|
151 memOK=EFalse; |
|
152 } |
|
153 if ( memOK ) |
|
154 { |
|
155 for ( TUint i = 0; i < KBufCount && memOK; i++ ) |
|
156 { |
|
157 iTraceBuffers[ i ].iBuffer = new TUint8[ KMaxBufLength ]; |
|
158 if (iTraceBuffers[ i ].iBuffer == NULL ) |
|
159 { |
|
160 memOK = EFalse; |
|
161 } |
|
162 if ( memOK ) |
|
163 { |
|
164 // Initially all buffers are linked to iFirstFreeBuffer |
|
165 // Casting needed to work around armv5 "pointless comparison of unsigned integer with zero" warning |
|
166 if ( (TInt) i < (TInt) ( KBufCount - 1 ) ) |
|
167 { |
|
168 iTraceBuffers[ i ].iNext = &( iTraceBuffers[ i + 1 ] ); |
|
169 } |
|
170 } |
|
171 else |
|
172 { |
|
173 memOK = EFalse; |
|
174 } |
|
175 } |
|
176 } |
|
177 else |
|
178 { |
|
179 memOK = EFalse; |
|
180 } |
|
181 |
|
182 // Memory was allocated succesfully |
|
183 if ( memOK ) |
|
184 { |
|
185 iFastCounterBetweenTraces = NKern::FastCounterFrequency() / GetTraceFrequency(); |
|
186 iFirstFreeBuffer = iTraceBuffers; |
|
187 |
|
188 // Register to the TraceCore |
|
189 retval = DTraceCoreWriter::Register(); |
|
190 if ( retval == KErrNone ) |
|
191 { |
|
192 iMediaIf = writerIf; |
|
193 } |
|
194 } |
|
195 else |
|
196 { |
|
197 retval = KErrNoMemory; |
|
198 } |
|
199 } |
|
200 } |
|
201 TC_TRACE( ETraceLevelFlow, Kern::Printf("<DTraceCoreMediaSWriter::Register - %d", retval) ); |
|
202 return retval; |
|
203 } |
|
204 |
|
205 |
|
206 /** |
|
207 * Starts an entry |
|
208 * |
|
209 * @param aType the type of the trace entry |
|
210 * @return the entry ID that is passed to other Write-functions |
|
211 */ |
|
212 EXPORT_C TUint32 DTraceCoreMediaSWriter::WriteStart( TWriterEntryType aType ) |
|
213 { |
|
214 |
|
215 // Detaches the first free buffer from the free buffers list |
|
216 TInt context( NKern::CurrentContext() ); |
|
217 TTraceBuffer* freeBuf = NULL; |
|
218 |
|
219 if ( context == NKern::EThread || context == NKern::EIDFC ) |
|
220 { |
|
221 #ifndef __SMP__ |
|
222 // In non SMP env the __SPIN_LOCK macro is empty. We need Kern::Lock. |
|
223 NKern::Lock(); // Unlocked in WriteEnd |
|
224 #else |
|
225 //already locked by BTrace spin lock |
|
226 #endif |
|
227 |
|
228 freeBuf = iFirstFreeBuffer; |
|
229 |
|
230 if ( freeBuf != NULL ) |
|
231 { |
|
232 StartBuffer( aType, *freeBuf ); |
|
233 } |
|
234 } |
|
235 else |
|
236 { |
|
237 freeBuf = NULL; |
|
238 } |
|
239 |
|
240 return ( TUint32 )freeBuf; |
|
241 } |
|
242 |
|
243 |
|
244 /** |
|
245 * Ends an entry |
|
246 * |
|
247 * @param aEntryId the entry ID returned by WriteStart |
|
248 * @param aWriteEndingZero If ETrue, write ending zero. |
|
249 */ |
|
250 EXPORT_C void DTraceCoreMediaSWriter::WriteEnd( TUint32 aEntryId ) |
|
251 { |
|
252 |
|
253 if ( aEntryId != 0 ) |
|
254 { |
|
255 TTraceBuffer* buf = ( TTraceBuffer* )aEntryId; |
|
256 TBool drop = EndBuffer( *buf ); |
|
257 |
|
258 if( !drop ) //trace isn't dropped |
|
259 { |
|
260 iSendDfc.RawAdd(); |
|
261 } |
|
262 |
|
263 // Locked in WriteStart |
|
264 #ifndef __SMP__ |
|
265 // In non SMP the __SPIN_LOCK macro is empty. We need Kern::Unlock. |
|
266 NKern::Unlock(); // Locked in WriteStart |
|
267 #else |
|
268 //BTrace lock is used from outside of this method. |
|
269 #endif |
|
270 } |
|
271 } |
|
272 |
|
273 |
|
274 /** |
|
275 * Writes 8-bit data to given entry |
|
276 * |
|
277 * @param aEntryId the entry ID returned by WriteStart |
|
278 * @param aData the trace data |
|
279 */ |
|
280 EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint8 aData ) |
|
281 { |
|
282 if ( aEntryId != 0 ) |
|
283 { |
|
284 TTraceBuffer* buf = ( TTraceBuffer* )aEntryId; |
|
285 if ( buf->iLength < KMaxBufLength ) |
|
286 { |
|
287 *( buf->iBuffer + buf->iLength ) = aData; |
|
288 buf->iLength++; |
|
289 } |
|
290 } |
|
291 } |
|
292 |
|
293 |
|
294 /** |
|
295 * Writes 16-bit data to given entry |
|
296 * |
|
297 * @param aEntryId the entry ID returned by WriteStart |
|
298 * @param aData the trace data |
|
299 */ |
|
300 EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint16 aData ) |
|
301 { |
|
302 if ( aEntryId != 0 ) |
|
303 { |
|
304 TTraceBuffer* buf = ( TTraceBuffer* )aEntryId; |
|
305 if ( buf->iLength + sizeof ( TUint16 ) <= KMaxBufLength ) |
|
306 { |
|
307 *( ( TUint16* )( buf->iBuffer + buf->iLength ) ) = aData; |
|
308 buf->iLength += sizeof ( TUint16 ); |
|
309 } |
|
310 } |
|
311 } |
|
312 |
|
313 |
|
314 /** |
|
315 * Writes 32-bit data to given entry |
|
316 * |
|
317 * @param aEntryId the entry ID returned by WriteStart |
|
318 * @param aData the trace data |
|
319 */ |
|
320 EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint32 aData ) |
|
321 { |
|
322 if ( aEntryId != 0 ) |
|
323 { |
|
324 TTraceBuffer* buf = ( TTraceBuffer* )aEntryId; |
|
325 if ( buf->iLength + sizeof ( TUint32 ) <= KMaxBufLength ) |
|
326 { |
|
327 *( ( TUint32* )( buf->iBuffer + buf->iLength ) ) = SWAP_DATA( aData ); |
|
328 buf->iLength += sizeof ( TUint32 ); |
|
329 } |
|
330 } |
|
331 } |
|
332 |
|
333 |
|
334 /** |
|
335 * DFC for sending data |
|
336 * |
|
337 * @param aMediaWriter the media writer |
|
338 */ |
|
339 void DTraceCoreMediaSWriter::SendDfc( TAny* aMediaWriter ) |
|
340 { |
|
341 DTraceCoreMediaSWriter* writer = static_cast< DTraceCoreMediaSWriter* >( aMediaWriter ); |
|
342 writer->SendDfc(); |
|
343 } |
|
344 |
|
345 |
|
346 /** |
|
347 * Called from static DFC function to send a buffer |
|
348 */ |
|
349 void DTraceCoreMediaSWriter::SendDfc() |
|
350 { |
|
351 // Create and send note random values |
|
352 TBuf8<64> note; // CodForChk_Dis_Magic |
|
353 note.Append(0xAE); // Dont care, CodForChk_Dis_Magic |
|
354 note.Append(0xAE); // Dont care, CodForChk_Dis_Magic |
|
355 note.Append(0x00); // Lentght MSB, CodForChk_Dis_Magic |
|
356 note.Append(0x02); // Length LSB, CodForChk_Dis_Magic |
|
357 note.Append(0xED); // Dont care, CodForChk_Dis_Magic |
|
358 note.Append(0xED); // Dont care, CodForChk_Dis_Magic |
|
359 |
|
360 iMediaIf->SendTrace( note ); |
|
361 } |
|
362 |
|
363 // End of File |