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