1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16
17 /*!
18 * ======== Registry ========
19 * Register modules that are not statically configured
20 *
21 * This module provides a mechanism by which legacy C code can have its own
22 * module logging support, including having a name and its own diags mask.
23 *
24 * Without the `Registry`, all logging done by legacy C code is handled by the
25 * `xdc.runtime.Main` module. This means that all `{@link Log}` events will
26 * be marked as coming from "`xdc.runtime.Main`", and there is only a single
27 * diagnostics mask for the runtime control of logging across all legacy C
28 * code. The `Registry` module allows legacy C code to have the same granular
29 * control over logging as statically defined RTSC modules.
30 *
31 * To use the `Registry` module, legacy code must define the symbol
32 * `Registry_CURDESC` to be the name of an externally declared
33 * `Registery_Desc` structure. This symbol must be defined before the
34 * inclusion of any `xdc/runtime` header files. If any `xdc/runtime` header
35 * files are included before the definition of this symbol, the `Registry`
36 * module may not function properly.
37 *
38 * Note: by defining this symbol on the compile line, rather than in the
39 * file, one can easily compile code to be used in one of two environments:
40 * @p(nlist)
41 * - a fixed configuration environment where modules are registered
42 * via `{@link #addModule Registry_addModule()}`, or
43 *
44 * - a "normal" configurable environment in which this code is
45 * assumed to be part of the `{@link Main}` module.
46 * @p
47 * The `Registry_Desc` structure must then be registered by calling
48 * `{@link #addModule Registry_addModule()}`. The structure is typically
49 * registered and initialized within `main()`.
50 *
51 * For example:
52 *
53 * @p(code)
54 * //Define the required symbol, Registry_CURDESC, to this file's
55 * //Registry_Desc object
56 * #define Registry_CURDESC mainDesc
57 * #include <xdc/runtime/Registry.h>
58 *
59 * //Declare the Registry_Desc object, the name is unimportant
60 * Registry_Desc mainDesc;
61 *
62 * Int main(Int argc, String argv[]) {
63 *
64 * //Register this file as a module "main"
65 * Registry_addModule(&mainDesc, "main");
66 * @p
67 *
68 * Once registered, the legacy code may call `{@link Log}` APIs without any
69 * other change and the formatted `Log` events will show as coming from the
70 * registered modules. Also, the logging by the legacy code is now filtered
71 * by its own diagnostic mask. The bits of this mask can be set using
72 * `{@link Diags#setMask Diags_setMask}`.
73 *
74 * Continuing the previous example:
75 * @p(code)
76 * //Initialize the legacy code's diags mask to enable USER1.
77 * Diags_setMask("main=1");
78 * @p
79 *
80 * All events logged by registered modules will be sent to the logger
81 * configured for the `Registry` module. For example, to configure the
82 * logger for use by all modules managed by `Registry`:
83 * @p(code)
84 * Registry.common$.logger = LoggerBuf.create();
85 * @p
86 *
87 * Since the registered modules are not known until runtime, it is not
88 * possible to statically configure the diagnostics masks for individual
89 * registered modules. However, it is possible to configure diagnostics
90 * categories to be permanently off or on for ALL registered modules. This
91 * is done by configuring the diagnostic mask for the `Registry` module.
92 * Diagnostic categories set to `{@link Diags#ALWAYS_OFF Diags.ALWAYS_OFF}`
93 * will be permanently off for all `Registry` modules. Categories set to
94 * `{@link Diags#ALWAYS_ON Diags.ALWAYS_ON}` will be permanently on for all
95 * modules managed by `Registry`.
96 *
97 * In order to enable runtime configuration of individual `Registry` module
98 * masks, all relevant diagnostic categories must be set to
99 * `{@link Diags#RUNTIME_OFF Diags.RUNTIME_OFF}` or
100 * `{@link Diags#RUNTIME_ON Diags.RUNTIME_ON}` in the `Registry` module's
101 * mask.
102 */
103 @CustomHeader
104 @DirectCall
105 @RomConsts
106
107 module Registry
108 {
109 /*!
110 * ======== RegisteredModuleView ========
111 * @_nodoc
112 * View element for the 'Registered Modules' ROV view.
113 */
114 metaonly struct RegisteredModuleView {
115 String modName;
116 Int id;
117 String mask;
118 Ptr descAddr;
119 }
120
121 /*!
122 * ======== rovViewInfo ========
123 * @_nodoc
124 */
125 @Facet
126 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
127 xdc.rov.ViewInfo.create({
128 viewMap: [
129 ['Registered Modules',
130 {
131 type: xdc.rov.ViewInfo.MODULE_DATA,
132 viewInitFxn: 'viewInitRegisteredModules',
133 structName: 'RegisteredModuleView'
134 }
135 ]
136 ]
137 });
138
139 /*!
140 * ======== Result ========
141 * Status codes
142 */
143 enum Result {
144 SUCCESS, /*! The module was added successfully */
145 ALLOC_FAILED, /*! reserved */
146 ALREADY_ADDED, /*! The module has already been added or another
147 * module with the same name is present
148 */
149 ALL_IDS_USED /*! No more module ids available for new modules */
150 };
151
152 /*!
153 * ======== RegDesc ========
154 * Registry module descriptor
155 */
156 typedef Types.RegDesc Desc;
157
158 /*!
159 * ======== addModule ========
160 * Add a runtime module to the registry with the specified name
161 *
162 * The `desc` parameter and the `modName` string provided must both be
163 * permanent since the `Registry` will maintain references to both of
164 * these.
165 *
166 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
167 * structure.
168 * @param(modName) non-`NULL` string name of the module being registered.
169 *
170 * @a(returns)
171 * `Registry_addModule` returns one of the following
172 * `{@link #Result Result}` status values indicating success or the
173 * cause of failure:
174 * @p(blist)
175 * - `{@link #SUCCESS SUCCESS}`
176 * - `{@link #ALREADY_ADDED ALREADY_ADDED}`
177 * - `{@link #ALL_IDS_USED ALL_IDS_USED}` There are a total of 16,384 - 1
178 * module ids available for use by `Registry`.
179 * @p
180 */
181 Result addModule(Desc *desc, CString modName);
182
183 /*!
184 * ======== findByName ========
185 * Find the registered module with the given name
186 *
187 * @param(modName) non-`NULL` string name of a registered module
188 *
189 * @a(returns)
190 * If the name `modName` is registered via
191 * `{@link #addModule Registry_addModule()}`, this function
192 * returns the pointer to the registered `Registry_Desc` structure;
193 * otherwise it returns `NULL`.
194 */
195 Desc *findByName(CString modName);
196
197 /*!
198 * ======== findByNamePattern ========
199 * @_nodoc
200 * Find all registered modules matching the specified pattern.
201 *
202 * This API is intended for use by Diags_setMask.
203 *
204 * The name pattern can be an exact module name or it can contain '%'
205 * as a wildcard. The `len` parameter is the string length of the pattern.
206 *
207 * This function returns one module at a time, but can be called
208 * repeatedly to find all modules matching the pattern. On the first
209 * call, pass `NULL` as the `prev` parameter. In all following calls,
210 * pass the last returned descriptor. This function returns `NULL` when
211 * it can't find any more modules matching the name pattern.
212 */
213 Desc *findByNamePattern(CString namePat, Int len, Desc *prev);
214
215 /*!
216 * ======== findById ========
217 * Find registered module's descriptor from its module ID
218 *
219 * @param(mid) any module id
220 *
221 * @a(returns)
222 * If the ID `mid` is registered via
223 * `{@link #addModule Registry_addModule()}`, this function
224 * returns the pointer to the registered `Registry_Desc` structure;
225 * otherwise it returns `NULL`.
226 */
227 Desc *findById(Types.ModuleId mid);
228
229 /*!
230 * ======== getMask ========
231 * Get the specified module's diagnostic mask
232 *
233 * @param(modName) non-`NULL` string name of a registered module
234 * @param(mask) non-`NULL` pointer to a mask to be initialized
235 * to the the current state of the diagnostics mask
236 * associated with `modName`
237 *
238 * @a(returns)
239 * The function returns `TRUE` if `name` identifies a registered module;
240 * otherwise, it return `FALSE`.
241 */
242 Bool getMask(CString name, Types.DiagsMask *mask);
243
244 /*!
245 * ======== isMember ========
246 * Determines if the specified module ID belongs to a registered module
247 *
248 * @param(mid) any module id
249 *
250 * @a(returns)
251 * This function returns `TRUE` if and only if the specified module id
252 * is a valid `Registry` module id. It does not search registered
253 * module ids, but simply checks if the id is within the range of valid
254 * `Registry` module ids.
255 */
256 Bool isMember(Types.ModuleId mid);
257
258 /*!
259 * ======== getNextModule ========
260 * Scan the current list of registered modules
261 *
262 * This function used to scan the list of all `Registry_Desc` structures
263 * currently being managed by the `Registry` module.
264 *
265 * @param(desc) optionally `NULL` pointer to a `Registry_Desc`
266 * structure. If `desc` is `NULL`, a pointer to the
267 * first structure is returned. If `desc` is non-`NULL`
268 * and equal to a previous return value of this function,
269 * a pointer to the "next" `Registry_Desc` structure
270 * is returned.
271 *
272 * @a(returns)
273 * This function returns a non-`NULL` pointer to one of the
274 * `Registry_Desc` structures added via `Registry_Desc` structures or
275 * `NULL` in the case that
276 * @p(blist)
277 * - there are no more module's in the list after `desc`, or
278 * - there are no modules registered
279 * @p
280 */
281 Desc *getNextModule(Desc *desc);
282
283 /*!
284 * ======== getModuleName ========
285 * Get the module name associated with a specified module descriptor
286 *
287 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
288 * structure.
289 *
290 * @a(returns)
291 * If the specified module descriptor has been initialized via a
292 * successful call to `{@link #addModule Registry_addModule()}`, this
293 * function returns the module name passed `Registry_addModule()`;
294 * otherwise, its return value is indeterminate.
295 */
296 CString getModuleName(Desc *desc);
297
298 /*!
299 * ======== getModuleId ========
300 * Get the module id associated with a specified module descriptor
301 *
302 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
303 * structure.
304 *
305 * @a(returns)
306 * If the specified module descriptor has been initialized via a
307 * successful call to `{@link #addModule Registry_addModule()}`, this
308 * function returns the module id assigned by `Registry_addModule()`;
309 * otherwise, its return value is indeterminate.
310 */
311 Types.ModuleId getModuleId(Desc *desc);
312
313 internal:
314
315 Desc *findByNameInList(CString name, Desc *listHead);
316 Void newModule(Desc *desc, CString modName);
317 Bool matchPattern(CString pattern, Int len, CString modName);
318
319
320 function isMemberRov(modId);
321 function lookupModIdRov(modId);
322
323 324 325
326 struct Module_State {
327 Desc *listHead;
328 Types.ModuleId curId;
329 }
330 }
331 332 333
334