1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16
17 /*!
18 * ======== LoggerBuf ========
19 * A logger which stores `Log` events in a buffer.
20 *
21 * This module provides a logger which captures `{@link Log}` events to a
22 * buffer in realtime. The `Log` events stored in the buffer are
23 * unformatted; `Log` event formatting is deferred until some client reads
24 * the raw event data from the buffer. You can use
25 * `{@link #flush LoggerBuf_flush()}` to process the `Log` events stored
26 * in the buffer and stream the formatted output to stdout
27 * (via `{@link System#printf}`). Alternatively, you can read a raw event
28 * (via `{@link #getNextEntry}`) and send it to another client that
29 * has the resources to format the event for display.
30 *
31 * The implementation of this logger is fast with minimal stack usage
32 * making it appropriate for a realtime application.
33 * This logger writes all `Log` events to a circular buffer. As a
34 * result, the execution time of all `Log` methods bound to this type
35 * of logger are deterministic (and quite short) because there are no
36 * additional memory allocation calls after the circular buffer was
37 * allocated.
38 *
39 * If this logger is used in a preemptive environment, then an appropriate
40 * gate must be assigned to the module. For example, if events are generated
41 * from an interrupt context, then a gate that disables interrupts
42 * must be used.
43 *
44 * @p(code)
45 * var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
46 * LoggerBuf.common$.gate = ...some gate instance...
47 * @p
48 *
49 * If the buffer type is circular, the log buffer of size
50 * `{@link #numEntries}` contains the last `numEntries` of `Log` events. If
51 * the buffer type is fixed, the log buffer contains the first
52 * `numEntries` events.
53 *
54 * LoggerBuf supports routing of 'STATUS' events (errors and warnings) to a
55 * separate ILogger instance. This is helpful in preserving these critical
56 * events, which may otherwise be overwritten by lower priority events. This
57 * feature is disabled by default. See {@link #statusLogger}.
58 *
59 * LoggerBuf implements the {@link IFilterLogger} interface and
60 * optionally supports filtering of events based on their detail level. This
61 * feature is disabled by default. See {@link IFilterLogger}.
62 *
63 * @a(Examples)
64 * Configuration example: The following XDC configuration statements
65 * create a logger instance, assign it as the default logger for all
66 * modules, and enable `USER1` logging in all modules of the package
67 * `my.pkg`. See the `{@link Diags#setMaskMeta Diags.setMaskMeta()}` function
68 * for details on specifying the module names.
69 *
70 * @p(code)
71 * var Defaults = xdc.useModule('xdc.runtime.Defaults');
72 * var Diags = xdc.useModule('xdc.runtime.Diags');
73 * var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
74 *
75 * LoggerBuf.enableFlush = true;
76 * var LoggerBufParams = new LoggerBuf.Params();
77 * LoggerBufParams.exitFlush = true;
78 * Defaults.common$.logger = LoggerBuf.create(LoggerBufParams);
79 * Diags.setMaskMeta("my.pkg.%", Diags.USER1, Diags.RUNTIME_ON);
80 * @p
81 */
82
83 @ModuleStartup
84 @InstanceFinalize
85 @InstanceInitError
86 @Gated
87
88 module LoggerBuf inherits IFilterLogger {
89
90 /*!
91 * ======== BufType ========
92 * Type of log buffer
93 */
94 enum BufType {
95 BufType_CIRCULAR, /*! The log buffer wraps, overwriting old entries */
96 BufType_FIXED /*! The log buffer halts collection when full */
97 };
98
99 metaonly struct BasicView {
100 String label;
101 Int lastSerial;
102 Int numEntries;
103 String type;
104 Bool enabledFlag;
105 };
106
107 metaonly struct RecordView {
108 Int serial;
109 Long timestampRaw;
110 String modName;
111 String text;
112 Int eventId;
113 String eventName;
114 IArg arg0;
115 IArg arg1;
116 IArg arg2;
117 IArg arg3;
118 IArg arg4;
119 IArg arg5;
120 IArg arg6;
121 IArg arg7;
122 }
123
124 /*!
125 * ======== rovViewInfo ========
126 * @_nodoc
127 */
128 @Facet
129 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
130 xdc.rov.ViewInfo.create({
131 viewMap: [
132 ['Basic',
133 {
134 type: xdc.rov.ViewInfo.INSTANCE,
135 viewInitFxn: 'viewInitBasic',
136 structName: 'BasicView'
137 }
138 ],
139 ['Records',
140 {
141 type: xdc.rov.ViewInfo.INSTANCE_DATA,
142 viewInitFxn: 'viewInitRecords',
143 structName: 'RecordView'
144 }
145 ]
146 ]
147 });
148
149 /*!
150 * ======== StopModeData ========
151 * Data added to the RTA MetaData file to support stop mode RTA
152 */
153 @XmlDtd metaonly struct StopModeData {
154 String bufferSymbol;
155 Int bufferSize;
156 }
157
158 /*!
159 * ======== E_badLevel ========
160 * Error raised if get or setFilterLevel receives a bad level value
161 */
162 config Error.Id E_badLevel =
163 {msg: "E_badLevel: Bad filter level value: %d"};
164
165 /*!
166 * ======== TimestampProxy ========
167 * User supplied time-stamp proxy
168 *
169 * This proxy allows `LoggerBuf` to use a timestamp server different
170 * from the server used by `{@link xdc.runtime.Timestamp}`. However, if
171 * not supplied by a user, this proxy defaults to whichever timestamp
172 * server is used by `Timestamp`.
173 */
174 proxy TimestampProxy inherits ITimestampClient;
175
176 /*!
177 * ======== enableFlush ========
178 * Flush all logs at system exit
179 */
180 config Bool enableFlush = false;
181
182 /*!
183 * ======== statusLogger ========
184 * Route all 'STATUS' (error and warning) events to this logger.
185 *
186 * If a statusLogger is specified, all LoggerBuf instances will check to
187 * determine if any of the events they receive are errors or warnings (if
188 * their diags mask includes the STATUS category), and will log these
189 * events to the statusLogger.
190 *
191 * Error events are infrequent, but it's generally critical that they be
192 * seen. In a typical system, non-error events easily outnumber any error
193 * events, and the logger is likely to wrap, overwriting any error events.
194 * To protect these events from being overwritten and lost, they can be
195 * sent to their own separate logger to preserve them.
196 *
197 * The default value is null, indicating that the STATUS events will just
198 * be logged by the logger they were sent to.
199 */
200 config ILogger.Handle statusLogger = null;
201
202 /*!
203 * ======== level1Mask ========
204 * Mask of diags categories whose initial filtering level is Diags.LEVEL1
205 *
206 * See '{@link #level4Mask}' for details.
207 */
208 config Diags.Mask level1Mask = 0;
209
210 /*!
211 * ======== level2Mask ========
212 * Mask of diags categories whose initial filtering level is Diags.LEVEL2
213 *
214 * See '{@link #level4Mask}' for details.
215 */
216 config Diags.Mask level2Mask = 0;
217
218 /*!
219 * ======== level3Mask ========
220 * Mask of diags categories whose initial filtering level is Diags.LEVEL3
221 *
222 * See '{@link #level4Mask}' for details.
223 */
224 config Diags.Mask level3Mask = 0;
225
226 /*!
227 * ======== level4Mask ========
228 * Mask of diags categories whose initial filtering level is Diags.LEVEL4
229 *
230 * If `{@link IFilterLogger.filterByLevel}` is `true`, then all
231 * `LoggerBuf` instances will filter incoming events based on their
232 * event level.
233 *
234 * The `LoggerBuf` module allows for specifying a different filter level
235 * for every `Diags` bit. These filtering levels are module wide;
236 * `LoggerBuf` does not support specifying the levels on a per-instance
237 * basis.
238 *
239 * The `{@link IFilterLogger.setFilterLevel}` function can be used to
240 * change the filtering levels at runtime.
241 *
242 * The default filtering levels are assigned using the `level1Mask` -
243 * `level4Mask` config parameters. These are used to specify, for each of
244 * the four event levels, the set of bits which should filter at that
245 * level by default.
246 *
247 * The default filtering configuration sets the filter level to
248 * `Diags.LEVEL4` for all logging-related diags bits so that all events
249 * are logged by default.
250 */
251 config Diags.Mask level4Mask = Diags.ALL_LOGGING;
252
253 /*!
254 * ======== flushAll ========
255 * Flush logs of all instances that set `exitFlush` to true
256 *
257 * The user is responsible for making sure that no `LoggerBuf` instances
258 * are created or deleted during the execution of this function.
259 */
260 Void flushAll();
261
262 /*!
263 * ======== flushAllInternal ========
264 * @_nodoc
265 */
266 Void flushAllInternal(Int stat);
267
268 /*!
269 * ======== initDecoder ========
270 * @_nodoc
271 * Initialize the LoggerBufDecoder for use in the LoggerBuf 'Records' ROV
272 * view.
273 */
274 function initDecoder();
275
276 instance:
277 /*!
278 * ======== create ========
279 * Create a `LoggerBuf` logger
280 *
281 * @see LoggerBuf#Params
282 */
283 create();
284
285 /*!
286 * ======== numEntries ========
287 * Number of entries in buffer
288 *
289 * Each entry is large enough to store one `Log` event containing up to
290 * 4 optional arguments. Events containing more than 4 arguments (such
291 * as those from `{@link Log#write5}`) use 2 entries.
292 *
293 * `numEntries` must be a power of 2.
294 */
295 config Int numEntries = 64;
296
297 /*!
298 * ======== bufType ========
299 * Log buffer type
300 */
301 config BufType bufType = BufType_CIRCULAR;
302
303 /*!
304 * ======== exitFlush ========
305 * Flush log at system exit
306 *
307 * Only used when module parameter `{@link #enableFlush}` is `true`.
308 */
309 config Bool exitFlush = false;
310
311 /*!
312 * ======== bufSection ========
313 * Section name for the buffer managed by the static instance.
314 *
315 * The default section is the 'dataSection' in the platform.
316 */
317 metaonly config String bufSection = null;
318
319 /*!
320 * ======== bufHeap ========
321 * The heap that contains the `Log` buffer for dynamic instances.
322 *
323 * The default value `null` means the buffer will be allocated from
324 * the `{@link Memory#defaultHeapInstance}` heap.
325 */
326 config IHeap.Handle bufHeap = null;
327
328 /*!
329 * ======== reset ========
330 * Reset a log to empty state and enable it
331 *
332 * @a(WARNING) This method is not synchronized with other instance
333 * methods and, as a result, it must never be called when there is a
334 * chance that another instance method is currently in operation or
335 * when another method on this instance may preempt this call.
336 */
337 Void reset();
338
339 /*!
340 * ======== flush ========
341 * Read, clear, and output the contents of the log
342 *
343 * This method reads, clears, and "prints" each `Log` event (via
344 * `{@link System#printf}`) in the log.
345 */
346 Void flush();
347
348 /*!
349 * ======== getNextEntry ========
350 * Fills the passed `{@link Log#EventRec}` with the next entry in the log.
351 *
352 * This function is used to read and clear `Log` events from the
353 * buffer maintained by the `LoggerBuf` instance. The `Log` event can
354 * then be transmitted and displayed on a host.
355 *
356 * A read pointer is maintained in the `LoggerBuf` instance and
357 * points to the next record to read. Entries are not necessarily
358 * returned in chronological order, since buffers of type
359 * `{@link #BufType_CIRCULAR}` can wrap.
360 *
361 * @param(evtRec) pointer to a supplied `EventRec` object where the next
362 * entry in the log is copied to
363 *
364 * @a(returns)
365 * This function reports the number of entries actually read. The only
366 * values that can be returned are:
367 * @p(blist)
368 * - 0 no more entries to read
369 * - 1 or 2 read a complete entry written by `write4` or `write8`
370 * - -1 cleared an incomplete/overwritten entry, more entries to read
371 */
372 Int getNextEntry(Log.EventRec *evtRec);
373
374 internal:
375
376 Bool filterOutEvent(Diags.Mask mask);
377
378 const Int8 FULL = -1;
379 const Int8 WRAP = 0;
380
381 const Int8 NEXT = 1;
382
383 struct Entry {
384 Types.Timestamp64 tstamp;
385 Bits32 serial;
386 Types.Event evt;
387 IArg arg1;
388 IArg arg2;
389 IArg arg3;
390 IArg arg4;
391 };
392
393 struct Module_State {
394 Diags.Mask level1;
395 Diags.Mask level2;
396 Diags.Mask level3;
397 };
398
399 struct Instance_State {
400 IHeap.Handle bufHeap;
401 Entry entryArr[];
402 Entry *curEntry;
403 Entry *endEntry;
404 Entry *readEntry;
405 Bits32 serial;
406 Int16 numEntries;
407 Int8 advance;
408 Bool enabled;
409 Bool flush;
410 };
411
412 }
413 414 415
416