1 /*
2 * Copyright (c) 2012-2015 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 xdc.useModule('ti.sdo.ipc.interfaces.ITransport');
71 xdc.useModule('ti.sdo.ipc.interfaces.IMessageQTransport');
72 xdc.useModule('ti.sdo.ipc.interfaces.INetworkTransport');
74 /* Plug the SetupTransportProxy for the MessageQ transport */
75 if (MessageQ.SetupTransportProxy == null) {
76 try {
77 MessageQ.SetupTransportProxy =
78 xdc.useModule(Settings.getMessageQSetupDelegate());
79 }
80 catch (e) {
81 /* Plug in the generic shared memory transport */
82 MessageQ.SetupTransportProxy =
83 xdc.useModule('ti.sdo.ipc.transports.TransportShmSetup');
84 }
85 }
86 }
88 /*
89 * ======== module$static$init ========
90 * Initialize module values.
91 */
92 function module$static$init(state, mod)
93 {
94 /* initialize the NameServer param to be used now or later */
95 MessageQ.nameSrvPrms.maxRuntimeEntries = mod.maxRuntimeEntries;
96 MessageQ.nameSrvPrms.tableSection = mod.tableSection;
97 MessageQ.nameSrvPrms.maxNameLen = mod.maxNameLen;
99 /*
100 * Get the current number of created static instances of this module.
101 * Note: if user creates a static instance after this point and
102 * expects to use NameServer, this is a problem.
103 */
104 var instCount = this.$instances.length;
106 /* create NameServer here only if no static instances are created */
107 if (instCount == 0) {
108 state.nameServer = NameServer.create("MessageQ", MessageQ.nameSrvPrms);
109 }
110 else {
111 state.nameServer = null;
112 }
114 /*
115 * If no growth allowed, pre-allocate the max length
116 * Also pre-allocate if numReservedEntries is not zero.
117 * maxRuntimeEntries < numReservedEntries is caught in validate.
118 */
119 state.numQueues = this.$instances.length;
120 if (mod.maxRuntimeEntries != NameServer.ALLOWGROWTH) {
121 state.numQueues += mod.maxRuntimeEntries;
122 }
123 else if (mod.numReservedEntries != 0){
124 state.numQueues += mod.numReservedEntries;
125 }
127 state.queues.length = state.numQueues;
128 state.canFreeQueues = false;
129 state.freeHookFxn = mod.freeHookFxn;
130 state.putHookFxn = mod.putHookFxn;
132 if (mod.nameTableGate == null) {
133 state.gate = null;
134 }
135 else {
136 state.gate = mod.nameTableGate;
137 }
139 var messsageQParams = new this.Params;
141 /* Initial the seqNum used for tracing */
142 state.seqNum = 0;
144 /* Set the length of the heaps array */
145 state.numHeaps = mod.numHeaps;
146 state.heaps.length = state.numHeaps;
148 /* Initialize the heaps array to null */
149 for (var i = 0; i < state.heaps.length; i++) {
150 state.heaps[i] = null;
151 }
153 /*
154 * Sort the static heaps by heap id into the heaps array
155 */
156 for (var i = 0; i < mod.staticHeaps.length; i++) {
158 /* Make sure the id is not too big */
159 if (mod.staticHeaps[i].heapId >= state.numHeaps) {
160 MessageQ.$logError("Out of range heapId ("
161 + mod.staticHeaps[i].heapId + "). Max heapId is "
162 + (mod.numHeaps - 1) + " (MessageQ.numHeaps - 1).", this);
163 }
165 /* Make sure the same id is not used twice */
166 if (state.heaps[mod.staticHeaps[i].heapId] != null) {
167 MessageQ.$logError("Cannot register multiple heaps to heapId "
168 + mod.staticHeaps[i].heapId + ".", this);
169 }
171 state.heaps[mod.staticHeaps[i].heapId] = mod.staticHeaps[i].heap;
172 }
174 if (MultiProc.procAddrMode == MultiProc.ProcAddrMode_Global) {
175 /* global address mode: need transport handle for every processor */
176 state.transports.length = MultiProc.numProcessors;
177 }
178 else if (MultiProc.procAddrMode == MultiProc.ProcAddrMode_Cluster) {
179 /* cluster address mode: need transport only for cluster members */
180 state.transports.length = MultiProc.numProcsInCluster;
181 }
182 else {
183 MessageQ.$logError("Unknown MultiProc.procAddrMode", this);
184 }
186 for (var i = 0; i < state.transports.length; i++) {
187 state.transports[i][0] = null;
188 state.transports[i][1] = null;
189 }
191 /* sort the static transports by processor id into the transport array */
192 if (MultiProc.procAddrMode == MultiProc.ProcAddrMode_Global) {
193 for (var i = 0; i < mod.staticTransports.length; i++) {
194 /* make sure the procId is not too big */
195 if (mod.staticTransports[i].procId >= MultiProc.numProcessors) {
196 MessageQ.$logError("MessageQ Out of range procId ("
197 + mod.staticTransports[i].procId + "). Max procId is "
198 + (MultiProc.numProcessors) + " (MultiProc."
199 + "numProcessors).", this);
200 }
202 /* make sure the same id is not used twice */
203 if (state.transports[mod.staticTransports[i].procId] != null) {
204 MessageQ.$logError("Cannot register multiple transports to "
205 + "same remote processor ("
206 + mod.staticTransports[i].procId + ").", this);
207 }
209 state.transports[mod.staticTransports[i].procId] =
210 mod.staticTransports[i].transport;
211 }
212 }
213 else if (MultiProc.procAddrMode == MultiProc.ProcAddrMode_Cluster) {
214 for (var i = 0; i < mod.staticTransports.length; i++) {
215 var clusterId = mod.staticTransports[i].procId
216 - MultiProc.baseIdOfCluster;
218 /* validate clusterId */
219 if (clusterId >= MultiProc.numProcsInCluster) {
220 MessageQ.$logError("procId=" + mod.staticTransports[i].procId
221 + " is not in cluster", this);
222 }
224 /* make sure the same id is not used twice */
225 if (state.transports[clusterId] != null) {
226 MessageQ.$logError("Cannot register multiple transports to "
227 + "same remote processor ("
228 + mod.staticTransports[i].procId + ").", this);
229 }
231 state.transports[clusterId] = mod.staticTransports[i].transport;
232 }
233 }
234 else {
235 MessageQ.$logError("Unknown MultiProc.procAddrMode", this);
236 }
238 /* initialize the registered transport array */
239 for (var i = 0; i < state.regTrans.length; i++) {
240 state.regTrans[i].transport = null;
241 state.regTrans[i].type = mod.TransportType_Invalid;
242 }
243 }
245 /*
246 * ======== registerHeapMeta ========
247 */
248 function registerHeapMeta(heap, heapId)
249 {
250 var entry = new this.HeapEntry();
251 entry.heap = heap;
252 entry.heapId = heapId;
253 this.staticHeaps.$add(entry);
254 }
256 /*
257 * ======== registerTransportMeta ========
258 */
259 function registerTransportMeta(transport, procId, priority)
260 {
261 var entry = new this.transportEntry();
262 entry.transport = transport;
263 entry.procId = procId;
264 this.staticTransports.$add(entry);
265 }
267 /*
268 * ======== viewInitQueues ========
269 */
270 function viewInitQueues(view, obj)
271 {
272 var Program = xdc.useModule('xdc.rov.Program');
273 var NameServer = xdc.useModule('ti.sdo.utils.NameServer');
274 var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
275 var modCfg = Program.getModuleConfig('ti.sdo.ipc.MessageQ');
277 /* view.name */
278 try {
279 view.name = NameServer.getName$view("MessageQ", obj.queue);
280 if (view.name == null) {
281 view.name = "<null>";
282 }
283 }
284 catch(e) {
285 Program.displayError(view, "name",
286 "Error retrieving name from NameServer: " + e);
287 }
289 /* view.queueId */
290 view.queueId = obj.queue & 0xffff;
292 /* view.reserved */
293 if ((view.queueId - 128) < modCfg.numReservedEntries) {
294 view.reserved = true;
295 }
296 else {
297 view.reserved = false;
298 }
299 }
301 /*
302 * ======== viewInitMessages ========
303 */
304 function viewInitMessages(view, obj)
305 {
306 var Program = xdc.useModule('xdc.rov.Program');
307 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
308 var NameServer = xdc.useModule('ti.sdo.utils.NameServer');
310 /* view.label */
311 try {
312 view.label = NameServer.getName$view("MessageQ", obj.queue);
313 if (view.label == null) {
314 view.label = "<null>";
315 }
316 }
317 catch(e) {
318 Program.displayError(view, "label",
319 "Error retrieving name from NameServer: " + e);
320 return;
321 }
323 /* Retrieve the ROV view for the embedded high priority message list. */
324 addMsgsFromList(view, obj.highList);
326 /* Retrieve the ROV view for the embedded normal priority message list. */
327 addMsgsFromList(view, obj.normalList);
328 }
330 /*
331 * ======== addMsgsFromList ========
332 * Scans the provided list object and adds the messages on it to the view.
333 */
334 function addMsgsFromList(view, list)
335 {
336 var Program = xdc.useModule('xdc.rov.Program');
338 /* Scan the list to retrieve the addresses of the messages. */
339 try {
340 var listView = Program.scanObjectView("ti.sdo.utils.List", list,
341 "Basic");
342 }
343 /* If there was a problem scanning the list, report it. */
344 catch (e) {
345 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
346 /*
347 * If there was a problem, report it using the first field, and
348 * return.
349 */
350 Program.displayError(msgView, 'seqNum', String(e));
351 view.elements.$add(msgView);
352 return;
353 }
355 try {
356 /* Fetch each of the message headers on the list. */
357 for each (var addr in listView.elems) {
358 var msgView = getMsgView(Number(addr));
359 view.elements.$add(msgView);
360 }
361 }
362 catch (e) {
363 /*
364 * If there were any problems retrieving the view, add an element
365 * to report the error.
366 */
367 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
368 Program.displayError(msgView, 'seqNum', String(e));
369 view.elements.$add(msgView);
370 }
371 }
373 /*
374 * ======== getMsgView ========
375 * Returns a view structure representing the message at the given address.
376 */
377 function getMsgView(addr)
378 {
379 var Program = xdc.useModule('xdc.rov.Program');
380 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
382 /* Create a new message view to populate. */
383 var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
385 /* Fetch the message header from the given address. */
386 try {
387 var msgHeader = Program.fetchStruct(MessageQ.MsgHeader$fetchDesc,
388 Number(addr));
389 }
390 catch (e) {
391 /*
392 * If there was a problem, report it using the first field, and
393 * return the view.
394 */
395 Program.displayError(msgView, 'seqNum', String(e));
396 return (msgView);
397 }
399 /* Display the messages sequence number and size. */
400 msgView.seqNum = msgHeader.seqNum;
401 msgView.msgSize = msgHeader.msgSize;
403 /* The flags field contains the message priority. */
404 var priority = msgHeader.flags & MessageQ.PRIORITYMASK;
405 getPriority(msgView, priority);
407 /* The flags field also contains the trace enabled bit. */
408 msgView.traceEnabled = msgHeader.flags & MessageQ.TRACEMASK;
410 /* The flags field also contains the version bits. */
411 msgView.version = (msgHeader.flags & MessageQ.VERSIONMASK) >> 13;
413 /* Display the message ID set by the user. */
414 msgView.msgId = msgHeader.msgId;
416 /*
417 * Scan in the MultiProc view so we have the mapping from processor id
418 * to processor name.
419 */
420 try {
421 var multiProcView = Program.scanModuleView('ti.sdo.utils.MultiProc',
422 'Module');
423 }
424 catch (e) {
425 /*
426 * If there was a problem scanning the MultiProc view, display the
427 * error, but keep processing anyway.
428 */
429 Program.displayError(msgView, 'srcProc', String(e));
430 }
432 /* Lookup the names of the destination, reply, and source processors. */
433 msgView.srcProc = multiProcView.nameList[msgHeader.srcProc];
435 /* If a reply queue hasn't been specified, display "N/A" */
436 if (msgHeader.replyId == 0xFFFF) {
437 msgView.replyProc = "N/A";
438 msgView.replyId = "N/A";
439 }
440 /* Otherwise display the reply queue. */
441 else {
442 msgView.replyProc = multiProcView.nameList[msgHeader.replyProc];
443 // TODO - Should this display the name of the MessageQ?
444 msgView.replyId = String(msgHeader.replyId);
445 }
447 /* Display the heap that the message was allocated from. */
448 msgView.heap = getHeapNameFromId(msgHeader.heapId);
450 return (msgView);
451 }
453 /*
454 * ======== getPriority ========
455 * Fills in the message views 'priority' field given the priority value.
456 */
457 function getPriority(msgView, priority)
458 {
459 var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
460 var Program = xdc.useModule('xdc.rov.Program');
462 switch (priority) {
463 case MessageQ.NORMALPRI:
464 msgView.priority = "(" + MessageQ.NORMALPRI + ") Normal";
465 break;
466 case MessageQ.HIGHPRI:
467 msgView.priority = "(" + MessageQ.HIGHPRI + ") High";
468 break;
469 case MessageQ.RESERVEDPRI:
470 msgView.priority = "(" + MessageQ.RESERVEDPRI + ") Reserved";
471 break;
472 case MessageQ.URGENTPRI:
473 msgView.priority = "(" + MessageQ.URGENTPRI + ") Urgent";
474 break;
475 default:
476 Program.displayError(msgView, 'priority',
477 'Message has invalid priority: ' + priority);
478 }
479 }
481 /*
482 * ======== getHeapNameFromId ========
483 * This function takes the heap Id from a message (the heap ids are assigned
484 * by MessageQ) and retrieves a name for the heap.
485 */
486 function getHeapNameFromId(heapId)
487 {
488 var Program = xdc.useModule('xdc.rov.Program');
490 /* The module state contains the list of heaps. */
491 var modView = Program.scanModuleView('ti.sdo.ipc.MessageQ', 'Module');
493 /* Get the string representation of the address. */
494 if ((heapId == -1) || (heapId == 65535)) {
495 var heapAddr = "[static]";
496 }
497 else {
498 var heapAddr = String(modView.heaps[heapId]);
499 }
501 return (heapId + " (" + heapAddr + ")");
502 }
504 /*
505 * ======== viewInitModule ========
506 */
507 function viewInitModule(view, mod)
508 {
509 var Program = xdc.useModule('xdc.rov.Program');
511 /* Scan in the array of heaps. */
512 try {
513 view.heaps = Program.fetchArray(mod.heaps$fetchDesc, mod.heaps,
514 mod.numHeaps);
515 }
516 catch (e) {
517 Program.displayError(view, 'heaps', "Problem retrieving array of " +
518 "heaps: " + e);
519 }
521 /* Display the handle to the module's gate. */
522 view.gate = mod.gate;
524 /*
525 * Display the module's sequence number, which is the next value
526 * that will be used.
527 */
528 view.nextSeqNum = mod.seqNum;
530 /* Display the freeHookFxn if there is one. */
531 if (Number(mod.freeHookFxn) != 0 ) {
532 view.freeHookFxn = Program.lookupFuncName(Number(mod.freeHookFxn));
533 }
534 }
536 function module$validate()
537 {
538 if ((MessageQ.maxRuntimeEntries != NameServer.ALLOWGROWTH) &&
539 (MessageQ.maxRuntimeEntries < MessageQ.numReservedEntries)) {
540 MessageQ.$logFatal(
541 "If MessageQ.maxRuntimeEntries is not NameServer.ALLOWGROWTH, " +
542 "it cannot be less than MessageQ.numReservedEntries.",
543 MessageQ);
544 }
545 }