6e760bd070e85d2667c2259e55851df3df97ff58
[ipc/ipcdev.git] / packages / ti / sdo / ipc / MessageQ.xs
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
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 */
45 var sharedCreateId = new Array();
47 /*
48  *  ======== module$meta$init ========
49  */
50 function module$meta$init(name)
51 {
52     /* Only process during "cfg" phase */
53     if (xdc.om.$name != "cfg") {
54         return;
55     }
57     /* Initialize the shared CreateId array */
58     var MultiProc = xdc.module('ti.sdo.utils.MultiProc');
59     sharedCreateId.length != MultiProc.numProcessors;
61     for (var i = 0; i < sharedCreateId.length; i++) {
62         sharedCreateId[i] = 1;
63     }
64 }
66 /*
67  *  ======== module$use ========
68  */
69 function module$use()
70 {
71     MessageQ   = this;
72     Settings   = xdc.useModule('ti.sdo.ipc.family.Settings');
73     List       = xdc.useModule("ti.sdo.utils.List");
74     MultiProc  = xdc.useModule("ti.sdo.utils.MultiProc");
75     NameServer = xdc.useModule('ti.sdo.utils.NameServer');
76     GateThread = xdc.useModule("xdc.runtime.knl.GateThread");
77     SyncSem    = xdc.useModule("ti.sysbios.syncs.SyncSem");
79     /* Plug the SetupTransportProxy for the MessageQ transport */
80     if (MessageQ.SetupTransportProxy == null) {
81         try {
82             MessageQ.SetupTransportProxy =
83                 xdc.useModule(Settings.getMessageQSetupDelegate());
84         }
85         catch (e) {
86             /* Plug in the generic shared memory transport */
87             MessageQ.SetupTransportProxy =
88                 xdc.useModule('ti.sdo.ipc.transports.TransportShmSetup');
89         }
90     }
91 }
93 /*
94  *  ======== module$static$init ========
95  *  Initialize module values.
96  */
97 function module$static$init(mod, params)
98 {
99     /* initialize the NameServer param to be used now or later */
100     MessageQ.nameSrvPrms.maxRuntimeEntries = params.maxRuntimeEntries;
101     MessageQ.nameSrvPrms.tableSection      = params.tableSection;
102     MessageQ.nameSrvPrms.maxNameLen        = params.maxNameLen;
104     /*
105      *  Get the current number of created static instances of this module.
106      *  Note: if user creates a static instance after this point and
107      *        expects to use NameServer, this is a problem.
108      */
109      var instCount = this.$instances.length;
111     /* create NameServer here only if no static instances are created */
112     if (instCount == 0) {
113         mod.nameServer = NameServer.create("MessageQ",
114                                            MessageQ.nameSrvPrms);
115     }
116     else {
117         mod.nameServer = null;
118     }
120     /*
121      *  If no growth allowed, pre-allocate the max length
122      *  Also pre-allocate if numReservedEntries is not zero.
123      *  maxRuntimeEntries < numReservedEntries is caught in validate.
124      */
125     mod.numQueues = this.$instances.length;
126     if (params.maxRuntimeEntries != NameServer.ALLOWGROWTH) {
127         mod.numQueues += params.maxRuntimeEntries;
128     }
129     else if (params.numReservedEntries != 0){
130         mod.numQueues += params.numReservedEntries;
131     }
133     mod.queues.length = mod.numQueues;
134     mod.canFreeQueues = false;
135     mod.freeHookFxn   = params.freeHookFxn;
137     if (params.nameTableGate == null) {
138          mod.gate = null;
139     }
140     else {
141         mod.gate = params.nameTableGate;
142     }
144     var messsageQParams = new this.Params;
146     /* Initial the seqNum used for tracing */
147     mod.seqNum     = 0;
149     /* Set the length of the heaps array */
150     mod.numHeaps     = params.numHeaps;
151     mod.heaps.length = mod.numHeaps;
153     /* Initialize the heaps array to null */
154     for (var i = 0; i < mod.heaps.length; i++) {
155             mod.heaps[i] = null;
156     }
158     /*
159      *  Sort the static heaps by heap id into the heaps array
160      */
161     for (var i = 0; i < params.staticHeaps.length; i++) {
163         /* Make sure the id is not too big */
164         if (params.staticHeaps[i].heapId >= mod.numHeaps) {
165             MessageQ.$logError("Out of range heapId (" +
166                                 params.staticHeaps[i].heapId +
167                                 "). Max heapId is " + (params.numHeaps - 1) +
168                                 " (MessageQ.numHeaps - 1).", this);
169         }
171         /* Make sure the same id is not used twice */
172         if (mod.heaps[params.staticHeaps[i].heapId] != null) {
173             MessageQ.$logError("Cannot register multiple heaps to heapId " +
174                                 params.staticHeaps[i].heapId + ".", this);
175         }
177         mod.heaps[params.staticHeaps[i].heapId] = params.staticHeaps[i].heap;
178     }
180     /* Set the length of the transport array */
181     mod.transports.length = MultiProc.numProcessors;
183     /* Initialize all the transports to null */
184     for (var i = 0; i < mod.transports.length; i++) {
185         mod.transports[i][0] = null;
186         mod.transports[i][1] = null;
187     }
189     /*
190      *  Sort the static Transports by processor id into the
191      *  transport array
192      */
193     for (var i = 0; i < params.staticTransports.length; i++) {
195         /* Make sure the procId is not too big */
196         if (params.staticTransports[i].procId >= MultiProc.numProcessors) {
197             MessageQ.$logError("MessageQ Out of range procId (" +
198                                 params.staticTransports[i].procId +
199                                 "). Max procId is " +
200                                 (MultiProc.numProcessors) +
201                                 " (MultiProc.numProcessors).", this);
202         }
204         /* Make sure the same id is not used twice */
205         if (mod.transports[params.staticTransports[i].procId] != null) {
206             MessageQ.$logError("Cannot register multiple transports to one" +
207                                " remote processor " +
208                                params.staticTransports[i].procId + ".", this);
209         }
211         mod.transports[params.staticTransports[i].procId] =
212             params.staticTransports[i].transport;
213     }
216 /*
217  *  ======== registerHeapMeta ========
218  */
219 function registerHeapMeta(heap, heapId)
221     var entry = new this.HeapEntry();
222     entry.heap = heap;
223     entry.heapId = heapId;
224     this.staticHeaps.$add(entry);
227 /*
228  *  ======== registerTransportMeta ========
229  */
230 function registerTransportMeta(transport, procId, priority)
232     var entry = new this.transportEntry();
233     entry.transport = transport;
234     entry.procId    = procId;
235     this.staticTransports.$add(entry);
238 /*
239  *  ======== viewInitQueues ========
240  */
241 function viewInitQueues(view, obj)
243     var Program         = xdc.useModule('xdc.rov.Program');
244     var NameServer      = xdc.useModule('ti.sdo.utils.NameServer');
245     var SharedRegion    = xdc.useModule('ti.sdo.ipc.SharedRegion');
247     /* view.name */
248     try {
249         view.name = NameServer.getName$view("MessageQ", obj.queue);
250     }
251     catch(e) {
252         Program.displayError(view, "name",
253             "Error retrieving name from NameServer: " + e);
254     }
256     /* view.queueId */
257     view.queueId = obj.queue & 0xffff;
261 /*
262  *  ======== viewInitMessages ========
263  */
264 function viewInitMessages(view, obj)
266     var Program = xdc.useModule('xdc.rov.Program');
267     var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
268     var NameServer = xdc.useModule('ti.sdo.utils.NameServer');
270     print("viewInitMessages called");
272     /* view.label */
273     try {
274         view.label = NameServer.getName$view("MessageQ", obj.queue);
275     }
276     catch(e) {
277         Program.displayError(view, "label",
278             "Error retrieving name from NameServer: " + e);
279         return;
280     }
282     /* Retrieve the ROV view for the embedded high priority message list. */
283     addMsgsFromList(view, obj.highList);
285     /* Retrieve the ROV view for the embedded normal priority message list. */
286     addMsgsFromList(view, obj.normalList);
289 /*
290  *  ======== addMsgsFromList ========
291  *  Scans the provided list object and adds the messages on it to the view.
292  */
293 function addMsgsFromList(view, list)
295     var Program = xdc.useModule('xdc.rov.Program');
297     print("Calling addMsgsFromList");
299     /* Scan the list to retrieve the addresses of the messages. */
300     try {
301         var listView = Program.scanObjectView("ti.sdo.utils.List", list,
302             "Basic");
303     }
304     /* If there was a problem scanning the list, report it. */
305     catch (e) {
306         var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
307         /*
308          * If there was a problem, report it using the first field, and
309          * return.
310          */
311         Program.displayError(msgView, 'seqNum', String(e));
312         view.elements.$add(msgView);
313         return;
314     }
316     try {
317         /* Fetch each of the message headers on the list. */
318         for each (var addr in listView.elems) {
319             print("Trying to call getMsgView for 0x" + Number(addr).toString(16));
320             var msgView = getMsgView(Number(addr));
322             view.elements.$add(msgView);
323         }
324     }
325     catch (e) {
326         /*
327          * If there were any problems retrieving the view, add an element
328          * to report the error.
329          */
330         var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
331         Program.displayError(msgView, 'seqNum', String(e));
332         view.elements.$add(msgView);
333     }
336 /*
337  *  ======== getMsgView ========
338  *  Returns a view structure representing the message at the given address.
339  */
340 function getMsgView(addr)
342     var Program = xdc.useModule('xdc.rov.Program');
343     var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
345     print("getting message view: 0x" + Number(addr).toString(16));
347     /* Create a new message view to populate. */
348     var msgView = Program.newViewStruct('ti.sdo.ipc.MessageQ', 'Messages');
350     /* Fetch the message header from the given address. */
351     try {
352         var msgHeader = Program.fetchStruct(MessageQ.MsgHeader$fetchDesc,
353                                             Number(addr));
354     }
355     catch (e) {
356         /*
357          * If there was a problem, report it using the first field, and
358          * return the view.
359          */
360         Program.displayError(msgView, 'seqNum', String(e));
361         return (msgView);
362     }
364     /* Display the messages sequence number and size. */
365     msgView.seqNum = msgHeader.seqNum;
366     msgView.msgSize = msgHeader.msgSize;
368     /* The flags field contains the message priority. */
369     var priority = msgHeader.flags & MessageQ.PRIORITYMASK;
370     getPriority(msgView, priority);
372     /* The flags field also contains the trace enabled bit. */
373     msgView.traceEnabled = msgHeader.flags & MessageQ.TRACEMASK;
375     /* The flags field also contains the version bits. */
376     msgView.version = (msgHeader.flags & MessageQ.VERSIONMASK) >> 13;
378     /* Display the message ID set by the user. */
379     msgView.msgId = msgHeader.msgId;
381     /*
382      * Scan in the MultiProc view so we have the mapping from processor id
383      * to processor name.
384      */
385     try {
386         var multiProcView = Program.scanModuleView('ti.sdo.utils.MultiProc',
387                                                    'Module');
388     }
389     catch (e) {
390         /*
391          * If there was a problem scanning the MultiProc view, display the
392          * error, but keep processing anyway.
393          */
394         Program.displayError(msgView, 'srcProc', String(e));
395     }
397     /* Lookup the names of the destination, reply, and source processors. */
398     msgView.srcProc = multiProcView.nameList[msgHeader.srcProc];
400     /* If a reply queue hasn't been specified, display "N/A" */
401     if (msgHeader.replyId == 0xFFFF) {
402         msgView.replyProc = "N/A";
403         msgView.replyId = "N/A";
404     }
405     /* Otherwise display the reply queue. */
406     else {
407         msgView.replyProc = multiProcView.nameList[msgHeader.replyProc];
408         // TODO - Should this display the name of the MessageQ?
409         msgView.replyId = String(msgHeader.replyId);
410     }
412     /* Display the heap that the message was allocated from. */
413     msgView.heap = getHeapNameFromId(msgHeader.heapId);
415     return (msgView);
418 /*
419  *  ======== getPriority ========
420  *  Fills in the message views 'priority' field given the priority value.
421  */
422 function getPriority(msgView, priority)
424     var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
425     var Program = xdc.useModule('xdc.rov.Program');
427     switch (priority) {
428         case MessageQ.NORMALPRI:
429             msgView.priority = "(" + MessageQ.NORMALPRI + ") Normal";
430             break;
431         case MessageQ.HIGHPRI:
432             msgView.priority = "(" + MessageQ.HIGHPRI + ") High";
433             break;
434         case MessageQ.RESERVEDPRI:
435             msgView.priority = "(" + MessageQ.RESERVEDPRI + ") Reserved";
436             break;
437         case MessageQ.URGENTPRI:
438             msgView.priority = "(" + MessageQ.URGENTPRI + ") Urgent";
439             break;
440         default:
441             Program.displayError(msgView, 'priority',
442                                  'Message has invalid priority: ' + priority);
443     }
446 /*
447  *  ======== getHeapNameFromId ========
448  *  This function takes the heap Id from a message (the heap ids are assigned
449  *  by MessageQ) and retrieves a name for the heap.
450  */
451 function getHeapNameFromId(heapId)
453     var Program = xdc.useModule('xdc.rov.Program');
455     /* The module state contains the list of heaps. */
456     var modView = Program.scanModuleView('ti.sdo.ipc.MessageQ', 'Module');
458     /* Get the string representation of the address. */
459     if ((heapId == -1) || (heapId == 65535)) {
460         var heapAddr = "[static]";
461     }
462     else {
463         var heapAddr = String(modView.heaps[heapId]);
464     }
466     return (heapId + " (" + heapAddr + ")");
469 /*
470  *  ======== viewInitModule ========
471  */
472 function viewInitModule(view, mod)
474     var Program = xdc.useModule('xdc.rov.Program');
476     /* Scan in the array of heaps. */
477     try {
478         view.heaps = Program.fetchArray(mod.heaps$fetchDesc, mod.heaps,
479                                           mod.numHeaps);
480     }
481     catch (e) {
482         Program.displayError(view, 'heaps', "Problem retrieving array of " +
483                              "heaps: " + e);
484     }
486     /* Display the handle to the module's gate. */
487     view.gate = mod.gate;
489     /*
490      * Display the module's sequence number, which is the next value
491      * that will be used.
492      */
493     view.nextSeqNum = mod.seqNum;
495     /* Display the freeHookFxn if there is one. */
496     if (Number(mod.freeHookFxn) != 0 ) {
497         view.freeHookFxn = Program.lookupFuncName(Number(mod.freeHookFxn));
498     }
501 function module$validate()
503     if ((MessageQ.maxRuntimeEntries != NameServer.ALLOWGROWTH) &&
504         (MessageQ.maxRuntimeEntries < MessageQ.numReservedEntries)) {
505         MessageQ.$logFatal(
506             "If MessageQ.maxRuntimeEntries is not NameServer.ALLOWGROWTH, " +
507             "it cannot be less than MessageQ.numReservedEntries.",
508             MessageQ);
509     }