SDOCM00118574 Remove interface hack from transport package
[ipc/ipcdev.git] / packages / ti / sdo / ipc / MessageQ.xs
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     }
245 /*
246  *  ======== registerHeapMeta ========
247  */
248 function registerHeapMeta(heap, heapId)
250     var entry = new this.HeapEntry();
251     entry.heap = heap;
252     entry.heapId = heapId;
253     this.staticHeaps.$add(entry);
256 /*
257  *  ======== registerTransportMeta ========
258  */
259 function registerTransportMeta(transport, procId, priority)
261     var entry = new this.transportEntry();
262     entry.transport = transport;
263     entry.procId    = procId;
264     this.staticTransports.$add(entry);
267 /*
268  *  ======== viewInitQueues ========
269  */
270 function viewInitQueues(view, obj)
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     }
301 /*
302  *  ======== viewInitMessages ========
303  */
304 function viewInitMessages(view, obj)
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);
330 /*
331  *  ======== addMsgsFromList ========
332  *  Scans the provided list object and adds the messages on it to the view.
333  */
334 function addMsgsFromList(view, list)
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     }
373 /*
374  *  ======== getMsgView ========
375  *  Returns a view structure representing the message at the given address.
376  */
377 function getMsgView(addr)
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);
453 /*
454  *  ======== getPriority ========
455  *  Fills in the message views 'priority' field given the priority value.
456  */
457 function getPriority(msgView, priority)
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     }
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)
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 + ")");
504 /*
505  *  ======== viewInitModule ========
506  */
507 function viewInitModule(view, mod)
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     }
536 function module$validate()
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     }