8417abf9c12dae820fc0b038948a6ce61f3676fd
1 /*
2 * Copyright (c) 2012-2014 Texas Instruments Incorporated - http://www.ti.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== MessageQ.xs ========
34 *
35 */
37 var MultiProc = null;
38 var NameServer = null;
39 var MessageQ = null;
40 var GateThread = null;
41 var Settings = null;
42 var SyncSem = null;
44 var instCount = 0; /* use to determine if processing last instance */
46 /*
47 * ======== module$meta$init ========
48 */
49 function module$meta$init(name)
50 {
51 /* Only process during "cfg" phase */
52 if (xdc.om.$name != "cfg") {
53 return;
54 }
55 }
57 /*
58 * ======== module$use ========
59 */
60 function module$use()
61 {
62 MessageQ = this;
63 Settings = xdc.useModule('ti.sdo.ipc.family.Settings');
64 List = xdc.useModule("ti.sdo.utils.List");
65 MultiProc = xdc.useModule("ti.sdo.utils.MultiProc");
66 NameServer = xdc.useModule('ti.sdo.utils.NameServer');
67 GateThread = xdc.useModule("xdc.runtime.knl.GateThread");
68 SyncSem = xdc.useModule("ti.sysbios.syncs.SyncSem");
70 /* Plug the SetupTransportProxy for the MessageQ transport */
71 if (MessageQ.SetupTransportProxy == null) {
72 try {
73 MessageQ.SetupTransportProxy =
74 xdc.useModule(Settings.getMessageQSetupDelegate());
75 }
76 catch (e) {
77 /* Plug in the generic shared memory transport */
78 MessageQ.SetupTransportProxy =
79 xdc.useModule('ti.sdo.ipc.transports.TransportShmSetup');
80 }
81 }
82 }
84 /*
85 * ======== module$static$init ========
86 * Initialize module values.
87 */
88 function module$static$init(mod, params)
89 {
90 /* initialize the NameServer param to be used now or later */
91 MessageQ.nameSrvPrms.maxRuntimeEntries = params.maxRuntimeEntries;
92 MessageQ.nameSrvPrms.tableSection = params.tableSection;
93 MessageQ.nameSrvPrms.maxNameLen = params.maxNameLen;
95 /*
96 * Get the current number of created static instances of this module.
97 * Note: if user creates a static instance after this point and
98 * expects to use NameServer, this is a problem.
99 */
100 var instCount = this.$instances.length;
102 /* create NameServer here only if no static instances are created */
103 if (instCount == 0) {
104 mod.nameServer = NameServer.create("MessageQ",
105 MessageQ.nameSrvPrms);
106 }
107 else {
108 mod.nameServer = null;
109 }
111 /*
112 * If no growth allowed, pre-allocate the max length
113 * Also pre-allocate if numReservedEntries is not zero.
114 * maxRuntimeEntries < numReservedEntries is caught in validate.
115 */
116 mod.numQueues = this.$instances.length;
117 if (params.maxRuntimeEntries != NameServer.ALLOWGROWTH) {
118 mod.numQueues += params.maxRuntimeEntries;
119 }
120 else if (params.numReservedEntries != 0){
121 mod.numQueues += params.numReservedEntries;
122 }
124 mod.queues.length = mod.numQueues;
125 mod.canFreeQueues = false;
126 mod.freeHookFxn = params.freeHookFxn;
128 if (params.nameTableGate == null) {
129 mod.gate = null;
130 }
131 else {
132 mod.gate = params.nameTableGate;
133 }
135 var messsageQParams = new this.Params;
137 /* Initial the seqNum used for tracing */
138 mod.seqNum = 0;
140 /* Set the length of the heaps array */
141 mod.numHeaps = params.numHeaps;
142 mod.heaps.length = mod.numHeaps;
144 /* Initialize the heaps array to null */
145 for (var i = 0; i < mod.heaps.length; i++) {
146 mod.heaps[i] = null;
147 }
149 /*
150 * Sort the static heaps by heap id into the heaps array
151 */
152 for (var i = 0; i < params.staticHeaps.length; i++) {
154 /* Make sure the id is not too big */
155 if (params.staticHeaps[i].heapId >= mod.numHeaps) {
156 MessageQ.$logError("Out of range heapId (" +
157 params.staticHeaps[i].heapId +
158 "). Max heapId is " + (params.numHeaps - 1) +
159 " (MessageQ.numHeaps - 1).", this);
160 }
162 /* Make sure the same id is not used twice */
163 if (mod.heaps[params.staticHeaps[i].heapId] != null) {
164 MessageQ.$logError("Cannot register multiple heaps to heapId " +
165 params.staticHeaps[i].heapId + ".", this);
166 }
168 mod.heaps[params.staticHeaps[i].heapId] = params.staticHeaps[i].heap;
169 }
171 /* Set the length of the transport array */
172 mod.transports.length = MultiProc.numProcessors;
174 /* Initialize all the transports to null */
175 for (var i = 0; i < mod.transports.length; i++) {
176 mod.transports[i][0] = null;
177 mod.transports[i][1] = null;
178 }
180 /*
181 * Sort the static Transports by processor id into the
182 * transport array
183 */
184 for (var i = 0; i < params.staticTransports.length; i++) {
186 /* Make sure the procId is not too big */
187 if (params.staticTransports[i].procId >= MultiProc.numProcessors) {
188 MessageQ.$logError("MessageQ Out of range procId (" +
189 params.staticTransports[i].procId +
190 "). Max procId is " +
191 (MultiProc.numProcessors) +
192 " (MultiProc.numProcessors).", this);
193 }
195 /* Make sure the same id is not used twice */
196 if (mod.transports[params.staticTransports[i].procId] != null) {
197 MessageQ.$logError("Cannot register multiple transports to one" +
198 " remote processor " +
199 params.staticTransports[i].procId + ".", this);
200 }
202 mod.transports[params.staticTransports[i].procId] =
203 params.staticTransports[i].transport;
204 }
205 }
207 /*
208 * ======== registerHeapMeta ========
209 */
210 function registerHeapMeta(heap, heapId)
211 {
212 var entry = new this.HeapEntry();
213 entry.heap = heap;
214 entry.heapId = heapId;
215 this.staticHeaps.$add(entry);
216 }
218 /*
219 * ======== registerTransportMeta ========
220 */
221 function registerTransportMeta(transport, procId, priority)
222 {
223 var entry = new this.transportEntry();
224 entry.transport = transport;
225 entry.procId = procId;
226 this.staticTransports.$add(entry);
227 }
229 /*
230 * ======== viewInitQueues ========
231 */
232 function viewInitQueues(view, obj)
233 {
234 var Program = xdc.useModule('xdc.rov.Program');
235 var NameServer = xdc.useModule('ti.sdo.utils.NameServer');
236 var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
238 /* view.name */
239 try {
240 view.name = NameServer.getName$view("MessageQ", obj.queue);
241 }
242 catch(e) {
243 Program.displayError(view, "name",
244 "Error retrieving name from NameServer: " + e);
245 }
247 /* view.queueId */
248 view.queueId = obj.queue & 0xffff;
250 }
252 /*
253 * ======== viewInitMessages ========
254 */
255 function viewInitMessages(view, obj)
256 {
257 var Program = xdc.useModule('xdc.rov.Program');
258 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
259 var NameServer = xdc.useModule('ti.sdo.utils.NameServer');
261 print("viewInitMessages called");
263 /* view.label */
264 try {
265 view.label = NameServer.getName$view("MessageQ", obj.queue);
266 }
267 catch(e) {
268 Program.displayError(view, "label",
269 "Error retrieving name from NameServer: " + e);
270 return;
271 }
273 /* Retrieve the ROV view for the embedded high priority message list. */
274 addMsgsFromList(view, obj.highList);
276 /* Retrieve the ROV view for the embedded normal priority message list. */
277 addMsgsFromList(view, obj.normalList);
278 }
280 /*
281 * ======== addMsgsFromList ========
282 * Scans the provided list object and adds the messages on it to the view.
283 */
284 function addMsgsFromList(view, list)
285 {
286 var Program = xdc.useModule('xdc.rov.Program');
288 print("Calling addMsgsFromList");
290 /* Scan the list to retrieve the addresses of the messages. */
291 try {
292 var listView = Program.scanObjectView("ti.sdo.utils.List", list,
293 "Basic");
294 }
295 /* If there was a problem scanning the list, report it. */
296 catch (e) {
297 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
298 /*
299 * If there was a problem, report it using the first field, and
300 * return.
301 */
302 Program.displayError(msgView, 'seqNum', String(e));
303 view.elements.$add(msgView);
304 return;
305 }
307 try {
308 /* Fetch each of the message headers on the list. */
309 for each (var addr in listView.elems) {
310 print("Trying to call getMsgView for 0x" + Number(addr).toString(16));
311 var msgView = getMsgView(Number(addr));
313 view.elements.$add(msgView);
314 }
315 }
316 catch (e) {
317 /*
318 * If there were any problems retrieving the view, add an element
319 * to report the error.
320 */
321 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
322 Program.displayError(msgView, 'seqNum', String(e));
323 view.elements.$add(msgView);
324 }
325 }
327 /*
328 * ======== getMsgView ========
329 * Returns a view structure representing the message at the given address.
330 */
331 function getMsgView(addr)
332 {
333 var Program = xdc.useModule('xdc.rov.Program');
334 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
336 print("getting message view: 0x" + Number(addr).toString(16));
338 /* Create a new message view to populate. */
339 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
341 /* Fetch the message header from the given address. */
342 try {
343 var msgHeader = Program.fetchStruct(MessageQ.MsgHeader$fetchDesc,
344 Number(addr));
345 }
346 catch (e) {
347 /*
348 * If there was a problem, report it using the first field, and
349 * return the view.
350 */
351 Program.displayError(msgView, 'seqNum', String(e));
352 return (msgView);
353 }
355 /* Display the messages sequence number and size. */
356 msgView.seqNum = msgHeader.seqNum;
357 msgView.msgSize = msgHeader.msgSize;
359 /* The flags field contains the message priority. */
360 var priority = msgHeader.flags & MessageQ.PRIORITYMASK;
361 getPriority(msgView, priority);
363 /* The flags field also contains the trace enabled bit. */
364 msgView.traceEnabled = msgHeader.flags & MessageQ.TRACEMASK;
366 /* The flags field also contains the version bits. */
367 msgView.version = (msgHeader.flags & MessageQ.VERSIONMASK) >> 13;
369 /* Display the message ID set by the user. */
370 msgView.msgId = msgHeader.msgId;
372 /*
373 * Scan in the MultiProc view so we have the mapping from processor id
374 * to processor name.
375 */
376 try {
377 var multiProcView = Program.scanModuleView('ti.sdo.utils.MultiProc',
378 'Module');
379 }
380 catch (e) {
381 /*
382 * If there was a problem scanning the MultiProc view, display the
383 * error, but keep processing anyway.
384 */
385 Program.displayError(msgView, 'srcProc', String(e));
386 }
388 /* Lookup the names of the destination, reply, and source processors. */
389 msgView.srcProc = multiProcView.nameList[msgHeader.srcProc];
391 /* If a reply queue hasn't been specified, display "N/A" */
392 if (msgHeader.replyId == 0xFFFF) {
393 msgView.replyProc = "N/A";
394 msgView.replyId = "N/A";
395 }
396 /* Otherwise display the reply queue. */
397 else {
398 msgView.replyProc = multiProcView.nameList[msgHeader.replyProc];
399 // TODO - Should this display the name of the MessageQ?
400 msgView.replyId = String(msgHeader.replyId);
401 }
403 /* Display the heap that the message was allocated from. */
404 msgView.heap = getHeapNameFromId(msgHeader.heapId);
406 return (msgView);
407 }
409 /*
410 * ======== getPriority ========
411 * Fills in the message views 'priority' field given the priority value.
412 */
413 function getPriority(msgView, priority)
414 {
415 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
416 var Program = xdc.useModule('xdc.rov.Program');
418 switch (priority) {
419 case MessageQ.NORMALPRI:
420 msgView.priority = "(" + MessageQ.NORMALPRI + ") Normal";
421 break;
422 case MessageQ.HIGHPRI:
423 msgView.priority = "(" + MessageQ.HIGHPRI + ") High";
424 break;
425 case MessageQ.RESERVEDPRI:
426 msgView.priority = "(" + MessageQ.RESERVEDPRI + ") Reserved";
427 break;
428 case MessageQ.URGENTPRI:
429 msgView.priority = "(" + MessageQ.URGENTPRI + ") Urgent";
430 break;
431 default:
432 Program.displayError(msgView, 'priority',
433 'Message has invalid priority: ' + priority);
434 }
435 }
437 /*
438 * ======== getHeapNameFromId ========
439 * This function takes the heap Id from a message (the heap ids are assigned
440 * by MessageQ) and retrieves a name for the heap.
441 */
442 function getHeapNameFromId(heapId)
443 {
444 var Program = xdc.useModule('xdc.rov.Program');
446 /* The module state contains the list of heaps. */
447 var modView = Program.scanModuleView('ti.sdo.ipc.MessageQ', 'Module');
449 /* Get the string representation of the address. */
450 if ((heapId == -1) || (heapId == 65535)) {
451 var heapAddr = "[static]";
452 }
453 else {
454 var heapAddr = String(modView.heaps[heapId]);
455 }
457 return (heapId + " (" + heapAddr + ")");
458 }
460 /*
461 * ======== viewInitModule ========
462 */
463 function viewInitModule(view, mod)
464 {
465 var Program = xdc.useModule('xdc.rov.Program');
467 /* Scan in the array of heaps. */
468 try {
469 view.heaps = Program.fetchArray(mod.heaps$fetchDesc, mod.heaps,
470 mod.numHeaps);
471 }
472 catch (e) {
473 Program.displayError(view, 'heaps', "Problem retrieving array of " +
474 "heaps: " + e);
475 }
477 /* Display the handle to the module's gate. */
478 view.gate = mod.gate;
480 /*
481 * Display the module's sequence number, which is the next value
482 * that will be used.
483 */
484 view.nextSeqNum = mod.seqNum;
486 /* Display the freeHookFxn if there is one. */
487 if (Number(mod.freeHookFxn) != 0 ) {
488 view.freeHookFxn = Program.lookupFuncName(Number(mod.freeHookFxn));
489 }
490 }
492 function module$validate()
493 {
494 if ((MessageQ.maxRuntimeEntries != NameServer.ALLOWGROWTH) &&
495 (MessageQ.maxRuntimeEntries < MessageQ.numReservedEntries)) {
496 MessageQ.$logFatal(
497 "If MessageQ.maxRuntimeEntries is not NameServer.ALLOWGROWTH, " +
498 "it cannot be less than MessageQ.numReservedEntries.",
499 MessageQ);
500 }
501 }