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