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