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