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 * }
79 * @p
80 *
81 * All events logged by registered modules will be sent to the logger
82 * configured for the `Registry` module. For example, to configure the
83 * logger for use by all modules managed by `Registry`:
84 * @p(code)
85 * Registry.common$.logger = LoggerBuf.create();
86 * @p
87 *
88 * Since the registered modules are not known until runtime, it is not
89 * possible to statically configure the diagnostics masks for individual
90 * registered modules. However, it is possible to configure diagnostics
91 * categories to be permanently off or on for ALL registered modules. This
92 * is done by configuring the diagnostic mask for the `Registry` module.
93 * Diagnostic categories set to `{@link Diags#ALWAYS_OFF Diags.ALWAYS_OFF}`
94 * will be permanently off for all `Registry` modules. Categories set to
95 * `{@link Diags#ALWAYS_ON Diags.ALWAYS_ON}` will be permanently on for all
96 * modules managed by `Registry`.
97 *
98 * In order to enable runtime configuration of individual `Registry` module
99 * masks, all relevant diagnostic categories must be set to
100 * `{@link Diags#RUNTIME_OFF Diags.RUNTIME_OFF}` or
101 * `{@link Diags#RUNTIME_ON Diags.RUNTIME_ON}` in the `Registry` module's
102 * mask.
103 */
104 @CustomHeader
105 @DirectCall
106 module Registry
107 {
108 /*!
109 * ======== RegisteredModuleView ========
110 * @_nodoc
111 * View element for the 'Registered Modules' ROV view.
112 */
113 metaonly struct RegisteredModuleView {
114 String modName;
115 Int id;
116 String mask;
117 Ptr descAddr;
118 }
119
120 /*!
121 * ======== rovViewInfo ========
122 * @_nodoc
123 */
124 @Facet
125 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
126 xdc.rov.ViewInfo.create({
127 viewMap: [
128 ['Registered Modules',
129 {
130 type: xdc.rov.ViewInfo.MODULE_DATA,
131 viewInitFxn: 'viewInitRegisteredModules',
132 structName: 'RegisteredModuleView'
133 }
134 ]
135 ]
136 });
137
138 /*!
139 * ======== Result ========
140 * Status codes
141 */
142 enum Result {
143 SUCCESS, /*! The module was added successfully */
144 ALLOC_FAILED, /*! reserved */
145 ALREADY_ADDED, /*! The module has already been added or another
146 * module with the same name is present
147 */
148 ALL_IDS_USED /*! No more module ids available for new modules */
149 };
150
151 /*!
152 * ======== RegDesc ========
153 * Registry module descriptor
154 */
155 typedef Types.RegDesc Desc;
156
157 /*!
158 * ======== addModule ========
159 * Add a runtime module to the registry with the specified name
160 *
161 * The `desc` parameter and the `modName` string provided must both be
162 * permanent since the `Registry` will maintain references to both of
163 * these.
164 *
165 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
166 * structure.
167 * @param(modName) non-`NULL` string name of the module being registered.
168 *
169 * @a(returns)
170 * `Registry_addModule` returns one of the following
171 * `{@link #Result Result}` status values indicating success or the
172 * cause of failure:
173 * @p(blist)
174 * - `{@link #SUCCESS SUCCESS}`
175 * - `{@link #ALREADY_ADDED ALREADY_ADDED}`
176 * - `{@link #ALL_IDS_USED ALL_IDS_USED}` There are a total of 16,384 - 1
177 * module ids available for use by `Registry`.
178 * @p
179 */
180 Result addModule(Desc *desc, CString modName);
181
182 /*!
183 * ======== findByName ========
184 * Find the registered module with the given name
185 *
186 * @param(modName) non-`NULL` string name of a registered module
187 *
188 * @a(returns)
189 * If the name `modName` is registered via
190 * `{@link #addModule Registry_addModule()}`, this function
191 * returns the pointer to the registered `Registry_Desc` structure;
192 * otherwise it returns `NULL`.
193 */
194 Desc *findByName(CString modName);
195
196 /*!
197 * ======== findByNamePattern ========
198 * @_nodoc
199 * Find all registered modules matching the specified pattern.
200 *
201 * This API is intended for use by Diags_setMask.
202 *
203 * The name pattern can be an exact module name or it can contain '%'
204 * as a wildcard. The `len` parameter is the string length of the pattern.
205 *
206 * This function returns one module at a time, but can be called
207 * repeatedly to find all modules matching the pattern. On the first
208 * call, pass `NULL` as the `prev` parameter. In all following calls,
209 * pass the last returned descriptor. This function returns `NULL` when
210 * it can't find any more modules matching the name pattern.
211 */
212 Desc *findByNamePattern(CString namePat, UShort len, Desc *prev);
213
214 /*!
215 * ======== findById ========
216 * Find registered module's descriptor from its module ID
217 *
218 * @param(mid) any module id
219 *
220 * @a(returns)
221 * If the ID `mid` is registered via
222 * `{@link #addModule Registry_addModule()}`, this function
223 * returns the pointer to the registered `Registry_Desc` structure;
224 * otherwise it returns `NULL`.
225 */
226 Desc *findById(Types.ModuleId mid);
227
228 /*!
229 * ======== getMask ========
230 * Get the specified module's diagnostic mask
231 *
232 * @param(modName) non-`NULL` string name of a registered module
233 * @param(mask) non-`NULL` pointer to a mask to be initialized
234 * to the the current state of the diagnostics mask
235 * associated with `modName`
236 *
237 * @a(returns)
238 * The function returns `TRUE` if `name` identifies a registered module;
239 * otherwise, it return `FALSE`.
240 */
241 Bool getMask(CString name, Types.DiagsMask *mask);
242
243 /*!
244 * ======== isMember ========
245 * Determines if the specified module ID belongs to a registered module
246 *
247 * @param(mid) any module id
248 *
249 * @a(returns)
250 * This function returns `TRUE` if and only if the specified module id
251 * is a valid `Registry` module id. It does not search registered
252 * module ids, but simply checks if the id is within the range of valid
253 * `Registry` module ids.
254 */
255 Bool isMember(Types.ModuleId mid);
256
257 /*!
258 * ======== getNextModule ========
259 * Scan the current list of registered modules
260 *
261 * This function used to scan the list of all `Registry_Desc` structures
262 * currently being managed by the `Registry` module.
263 *
264 * @param(desc) optionally `NULL` pointer to a `Registry_Desc`
265 * structure. If `desc` is `NULL`, a pointer to the
266 * first structure is returned. If `desc` is non-`NULL`
267 * and equal to a previous return value of this function,
268 * a pointer to the "next" `Registry_Desc` structure
269 * is returned.
270 *
271 * @a(returns)
272 * This function returns a non-`NULL` pointer to one of the
273 * `Registry_Desc` structures added via `Registry_Desc` structures or
274 * `NULL` in the case that
275 * @p(blist)
276 * - there are no more module's in the list after `desc`, or
277 * - there are no modules registered
278 * @p
279 */
280 Desc *getNextModule(Desc *desc);
281
282 /*!
283 * ======== getModuleName ========
284 * Get the module name associated with a specified module descriptor
285 *
286 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
287 * structure.
288 *
289 * @a(returns)
290 * If the specified module descriptor has been initialized via a
291 * successful call to `{@link #addModule Registry_addModule()}`, this
292 * function returns the module name passed `Registry_addModule()`;
293 * otherwise, its return value is indeterminate.
294 */
295 CString getModuleName(Desc *desc);
296
297 /*!
298 * ======== getModuleId ========
299 * Get the module id associated with a specified module descriptor
300 *
301 * @param(desc) non-`NULL` pointer to a `{#Desc Registry_Desc}`
302 * structure.
303 *
304 * @a(returns)
305 * If the specified module descriptor has been initialized via a
306 * successful call to `{@link #addModule Registry_addModule()}`, this
307 * function returns the module id assigned by `Registry_addModule()`;
308 * otherwise, its return value is indeterminate.
309 */
310 Types.ModuleId getModuleId(Desc *desc);
311
312 internal:
313
314 Desc *findByNameInList(CString name, Desc *listHead);
315 Void newModule(Desc *desc, CString modName);
316 Bool matchPattern(CString pattern, UShort len, CString modName);
317
318
319 function isMemberRov(modId);
320 function lookupModIdRov(modId);
321
322 323 324
325 struct Module_State {
326 Desc *listHead;
327 Types.ModuleId curId;
328 }
329 }
330 331 332
333