1    /*
     2     * Copyright (c) 2012-2015 Texas Instruments Incorporated - https://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.xdc ========
    34     *
    35     */
    36    
    37    package ti.sdo.ipc;
    38    
    39    import xdc.runtime.IHeap;
    40    import xdc.runtime.Assert;
    41    import xdc.runtime.Error;
    42    import xdc.runtime.Diags;
    43    import xdc.runtime.Log;
    44    import xdc.runtime.IGateProvider;
    45    import xdc.runtime.knl.ISync;
    46    
    47    import ti.sysbios.syncs.SyncSem;
    48    
    49    import ti.sdo.ipc.interfaces.ITransport;
    50    import ti.sdo.ipc.interfaces.IMessageQTransport;
    51    import ti.sdo.utils.NameServer;
    52    import ti.sdo.utils.List;
    53    
    54    import xdc.rov.ViewInfo;
    55    
    56    /*!
    57     *  ======== MessageQ ========
    58     *  Message-passing with queuing
    59     *
    60     *  The MessageQ module supports the structured sending and receiving of
    61     *  variable length messages. This module can be used for homogeneous
    62     *  (DSP to DSP)  or heterogeneous (Arm to DSP) multi-processor messaging.
    63     *
    64     *  MessageQ provides more sophisticated messaging than other modules. It is
    65     *  typically used for complex situations such as multi-processor messaging.
    66     *
    67     *  The following are key features of the MessageQ module:
    68     *  @p(blist)
    69     *  -Writers and readers can be relocated to another processor with no
    70     *   runtime code changes.
    71     *  -Timeouts are allowed when receiving messages.
    72     *  -Readers can determine the writer and reply back.
    73     *  -Receiving a message is deterministic when the timeout is zero.
    74     *  -Messages can reside on any message queue.
    75     *  -Supports zero-copy transfers.
    76     *  -Can send and receive from any type of thread.
    77     *  -Notification mechanism is specified by application.
    78     *  -Allows QoS (quality of service) on message buffer pools. For example,
    79     *   using specific buffer pools for specific message queues.
    80     *  @p
    81     *
    82     *  Messages are sent and received by being placed on and removed from a
    83     *  message queue. A reader is a thread that gets (reads) messages from a
    84     *  message queue. A writer is a thread that puts (writes) a message to a
    85     *  message queue. Each message queue has one reader and can have many writers.
    86     *  A thread may read from or write to multiple message queues.
    87     *
    88     *  Conceptually, the reader thread owns a message queue. The reader thread
    89     *  creates a message queue. The writer threads open a created message queue
    90     *  to get access to them.
    91     *
    92     *  Message queues are identified by a system-wide unique name. Internally,
    93     *  MessageQ uses the {@link ti.sdo.utils.NameServer} module for managing
    94     *  these names. The names are used for opening a message queue.
    95     *
    96     *  Messages must be allocated from the MessageQ module. Once a message is
    97     *  allocated, it can be sent to any message queue. Once a message is sent, the
    98     *  writer loses ownership of the message and should not attempt to modify the
    99     *  message. Once the reader receives the message, it owns the message. It
   100     *  may either free the message or re-use the message.
   101     *
   102     *  Messages in a message queue can be of variable length. The only
   103     *  requirement is that the first field in the definition of a message must be a
   104     *  {@link #MsgHeader} structure. For example:
   105     *  @p(code)
   106     *  typedef struct MyMsg {
   107     *      MessageQ_MsgHeader header;
   108     *      ...
   109     *  } MyMsg;
   110     *  @p
   111     *
   112     *  The MessageQ API uses the MessageQ_MsgHeader internally. Your application
   113     *  should not modify or directly access the fields in the MessageQ_MsgHeader.
   114     *
   115     *  All messages sent via the MessageQ module must be allocated from a
   116     *  {@link xdc.runtime.IHeap} implementation. The heap can also be used for
   117     *  other memory allocation not related to MessageQ.
   118     *
   119     *  An application can use multiple heaps. The purpose of having multiple
   120     *  heaps is to allow an application to regulate its message usage. For
   121     *  example, an application can allocate critical messages from one heap of fast
   122     *  on-chip memory and non-critical messages from another heap of slower
   123     *  external memory.
   124     *
   125     *  The {@link #registerHeap} and {@link #registerHeapMeta} are APIs used to
   126     *  assign a MessageQ heapId to a heap. When allocating a message, the heapId
   127     *  is used, not the heap handle. This heapId is actually placed into the
   128     *  message (part of the {@link #MsgHeader}). Care must be taken when assigning
   129     *  heapIds. Refer to the {@link #registerHeap} and {@link #registerHeapMeta}
   130     *  descriptions for more details.
   131     *
   132     *  MessageQ also supports the usage of messages that are not allocated via the
   133     *  {@link #alloc} function. Please refer to the {@link #staticMsgInit}
   134     *  function description for more details.
   135     *
   136     *  MessageQ supports reads/writes of different thread models. This is
   137     *  accomplished by having the creator of the message queue specify a
   138     *  {@link xdc.runtime.knl.ISync#Object} via the {@link #synchronizer}
   139     *  configuration parameter. The {@link xdc.runtime.knl.ISync#signal}
   140     *  portion of the ISync instance is called whenever the {@link #put}
   141     *  is called. The {@link xdc.runtime.knl.ISync#wait} portion is
   142     *  called in the {@link #get} if and only if there are no messages.
   143     *
   144     *  Since ISyncs are binary, the reader must drain the message queue of all
   145     *  messages before waiting for another signal. For example, if the reader
   146     *  was a SYSBIOS Swi, the {@link xdc.runtime.knl.ISync} instance
   147     *  could be a SyncSwi. If a {@link #put} was called, the Swi_post() would
   148     *  be called. The Swi would run and it must call {@link #get} until no
   149     *  messages are returned.
   150     *
   151     *  In a multiple processor system, MessageQ communicates to other
   152     *  processors via {@link ti.sdo.ipc.interfaces.IMessageQTransport} instances.
   153     *  MessageQ supports a high priority and a normal priority transport between
   154     *  any two processors. The IMessageQTransport instances are created via the
   155     *  {@link #SetupTransportProxy}. The instances are responsible for
   156     *  registering themselves with MessageQ. This is accomplished via the
   157     *  {@link #registerTransport} function.
   158     *
   159     *  @a(Note)
   160     *  This modules reflects upon the {@link ti.sdo.utils.MultiProc#procAddrMode}
   161     *  configuration parameter. Some internal data structure allocations are
   162     *  optimized for the given processor address mode. For example, when using
   163     *  {@link ti.sdo.utils.MultiProc#ProcAddrMode_Global}, a message can be
   164     *  addressed to any processor using only the destination queueId. However,
   165     *  when using {@link ti.sdo.utils.MultiProc#ProcAddrMode_Cluster}, only
   166     *  the processors within your cluster can be addressed using only the
   167     *  destination queueId. For processors outside the cluster, you must also
   168     *  specify the Transport ID.
   169     */
   170    
   171    @ModuleStartup
   172    @InstanceInitError
   173    @InstanceFinalize
   174    
   175    module MessageQ
   176    {
   177        /*!
   178         *  ======== QueuesView ========
   179         *  @_nodoc
   180         */
   181        metaonly struct QueuesView {
   182            String  name;
   183            UInt    queueId;
   184        }
   185    
   186        /*!
   187         *  ======== MessagesView ========
   188         *  @_nodoc
   189         */
   190        metaonly struct MessagesView {
   191            Int          seqNum;
   192            Int          msgSize;
   193            String       priority;
   194            String       srcProc;
   195            String       replyProc;
   196            String       replyId;
   197            Int          msgId;
   198            String       heap;
   199            Bool         traceEnabled;
   200            Int          version;
   201        }
   202    
   203        /*!
   204         *  ======== ModuleView ========
   205         *  @_nodoc
   206         */
   207        metaonly struct ModuleView {
   208            String               heaps[];
   209            String               gate;
   210            UInt16               nextSeqNum;
   211            String               freeHookFxn[];
   212        }
   213    
   214        /*!
   215         *  ======== rovViewInfo ========
   216         *  @_nodoc
   217         */
   218        @Facet
   219        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
   220            xdc.rov.ViewInfo.create({
   221                viewMap: [
   222                    ['Queues',
   223                        {
   224                            type: xdc.rov.ViewInfo.INSTANCE,
   225                            viewInitFxn: 'viewInitQueues',
   226                            structName: 'QueuesView'
   227                        }
   228                    ],
   229                    ['Messages',
   230                        {
   231                            type: xdc.rov.ViewInfo.INSTANCE_DATA,
   232                            viewInitFxn: 'viewInitMessages',
   233                            structName: 'MessagesView'
   234                        }
   235                    ],
   236                    ['Module',
   237                        {
   238                            type: xdc.rov.ViewInfo.MODULE,
   239                            viewInitFxn: 'viewInitModule',
   240                            structName: 'ModuleView'
   241                        }
   242                    ]
   243                ]
   244            });
   245    
   246        /*!
   247         *  ======== LM_setTrace ========
   248         *  Logged when setting the trace flag on a message
   249         *
   250         *  This is logged when tracing on a message is set via
   251         *  {@link #setMsgTrace}.
   252         */
   253        config Log.Event LM_setTrace = {
   254            mask: Diags.USER1,
   255            msg: "LM_setTrace: Message 0x%x (seqNum = %d, srcProc = %d) traceFlag = %d"
   256        };
   257    
   258        /*!
   259         *  ======== LM_alloc ========
   260         *  Logged when allocating a message
   261         *
   262         *  When the {@link #traceFlag} is true, all message allocations
   263         *  are logged.
   264         */
   265        config Log.Event LM_alloc = {
   266            mask: Diags.USER1,
   267            msg: "LM_alloc: Message 0x%x (seqNum = %d, srcProc = %d) was allocated"
   268        };
   269    
   270        /*!
   271         *  ======== LM_staticMsgInit ========
   272         *  Logged when statically initializing a message
   273         *
   274         *  When the {@link #traceFlag} is true, all messages that
   275         *  are statically initialized via {@link #staticMsgInit} are logged.
   276         */
   277        config Log.Event LM_staticMsgInit = {
   278            mask: Diags.USER1,
   279            msg: "LM_staticMsgInit: Message 0x%x (seqNum = %d, srcProc = %d) was set in MessageQ_staticMsgInit"
   280        };
   281    
   282        /*!
   283         *  ======== LM_free ========
   284         *  Logged when freeing a message
   285         *
   286         *  When the {@link #traceFlag} is true, all freeing of messages
   287         *  are logged. If an individual message's tracing was enabled
   288         *  via {@link #setMsgTrace}, the MessageQ_free is also logged.
   289         */
   290        config Log.Event LM_free = {
   291            mask: Diags.USER1,
   292            msg: "LM_free: Message 0x%x (seqNum = %d, srcProc = %d) was freed"
   293        };
   294    
   295        /*!
   296         *  ======== LM_putLocal ========
   297         *  Logged when a message is placed onto a local queue
   298         *
   299         *  When the {@link #traceFlag} is true, all putting of messages
   300         *  are logged. If an individual message's tracing was enabled
   301         *  via {@link #setMsgTrace}, the MessageQ_put is also logged.
   302         */
   303        config Log.Event LM_putLocal = {
   304            mask: Diags.USER1,
   305            msg: "LM_putLocal: Message 0x%x (seqNum = %d, srcProc = %d) was placed onto queue 0x%x"
   306        };
   307    
   308        /*!
   309         *  ======== LM_putRemote ========
   310         *  Logged when a message is given to a transport
   311         *
   312         *  When the {@link #traceFlag} is true, all putting of messages
   313         *  to a transport are logged. If an individual message's tracing
   314         *  was enabled  via {@link #setMsgTrace}, the MessageQ_put is
   315         *  also logged.
   316         */
   317        config Log.Event LM_putRemote = {
   318            mask: Diags.USER1,
   319            msg: "LM_putRemote: Message 0x%x (seqNum = %d, srcProc = %d) was given to processor %d transport"
   320        };
   321    
   322        /*!
   323         *  ======== LM_rcvByTransport ========
   324         *  Logged when a transport receives an incoming message
   325         *
   326         *  When the {@link #traceFlag} is true, all incoming messages
   327         *  are logged. If an individual message's tracing
   328         *  was enabled  via {@link #setMsgTrace}, the receiving of a message is
   329         *  also logged.
   330         */
   331        config Log.Event LM_rcvByTransport = {
   332            mask: Diags.USER1,
   333            msg: "LM_rcvByTransport: Message 0x%x (seqNum = %d, srcProc = %d) was received"
   334        };
   335    
   336        /*!
   337         *  ======== LM_get ========
   338         *  Logged when a message is received off the queue
   339         *
   340         *  When the {@link #traceFlag} is true, all getting of messages
   341         *  are logged. If an individual message's tracing
   342         *  was enabled  via {@link #setMsgTrace}, the MessageQ_get is
   343         *  also logged.
   344         */
   345        config Log.Event LM_get = {
   346            mask: Diags.USER1,
   347            msg: "LM_get: Message 0x%x (seqNum = %d, srcProc = %d) was received by queue 0x%x"
   348        };
   349    
   350        /*!
   351         *  ======== FreeHookFxn ========
   352         *  Function prototype for the MessageQ_free callback
   353         *
   354         *  @param(Bits16)  heapId of message that was freed
   355         *  @param(Bits16)  msgId of message that was freed
   356         */
   357        typedef Void (*FreeHookFxn)(Bits16, Bits16);
   358    
   359        /*!
   360         *  ======== PutHookFxn ========
   361         *  Function prototype for the MessageQ_put callback
   362         *
   363         *  @param(Bits32)  queueId of the destination message queue
   364         *  @param(Ptr)     pointer to a message header structure
   365         */
   366        typedef Void (*PutHookFxn)(Bits32, Ptr);
   367    
   368        /*! MessageQ ID */
   369        typedef UInt32 QueueId;
   370    
   371        /*!
   372         *  ======== SetupTransportProxy ========
   373         *  MessageQ transport setup proxy
   374         */
   375        proxy SetupTransportProxy inherits ti.sdo.ipc.interfaces.ITransportSetup;
   376    
   377        /*!
   378         *  Message priority values. These must match the values defined in
   379         *  ti/ipc/MessageQ.h but are needed here for ROV.
   380         */
   381        const UInt NORMALPRI   = 0;
   382        const UInt HIGHPRI     = 1;
   383        const UInt RESERVEDPRI = 2;
   384        const UInt URGENTPRI   = 3;
   385    
   386        /*!
   387         *  Denotes any queueId is acceptable
   388         *
   389         *  This constant is the default for the {@link #queueId} parameter.
   390         *  This value must match ti/ipc/MessageQ.h but is needed to initialize
   391         *  queueId.
   392         */
   393        const Bits16 ANY = ~(0);
   394    
   395        /*!
   396         *  Assert raised when calling API with wrong handle
   397         *
   398         *  Some APIs can only be called with an opened handle (e.g.
   399         *  {@link #close}. Some can only be called with a created handle
   400         *  (e.g. {@link #get}).
   401         */
   402        config Assert.Id A_invalidContext  = {
   403            msg: "A_invalidContext: Cannot call with an open/create handle"
   404        };
   405    
   406        /*!
   407         *  Assert raised when attempting to free a static message
   408         */
   409        config Assert.Id A_cannotFreeStaticMsg  = {
   410            msg: "A_cannotFreeStaticMsg: Cannot call MessageQ_free with static msg"
   411        };
   412    
   413        /*!
   414         *  Assert raised when an invalid message is supplied
   415         */
   416        config Assert.Id A_invalidMsg  = {
   417            msg: "A_invalidMsg: Invalid message"
   418        };
   419    
   420        /*!
   421         *  Assert raised when an invalid queueId is supplied
   422         */
   423        config Assert.Id A_invalidQueueId  = {
   424            msg: "A_invalidQueueId: Invalid queueId is used"
   425        };
   426    
   427        /*!
   428         *  Assert raised when using an invalid heapId
   429         */
   430        config Assert.Id A_heapIdInvalid  = {
   431            msg: "A_heapIdInvalid: heapId is invalid"
   432        };
   433    
   434        /*!
   435         *  Assert raised when using an invalid procId
   436         */
   437        config Assert.Id A_procIdInvalid  = {
   438            msg: "A_procIdInvalid: procId is invalid"
   439        };
   440    
   441        /*!
   442         *  Assert raised for an invalid MessageQ object
   443         */
   444        config Assert.Id A_invalidObj  = {
   445            msg: "A_invalidObj: an invalid obj is used"
   446        };
   447    
   448        /*!
   449         *  Assert raised for an invalid parameter
   450         */
   451        config Assert.Id A_invalidParam  = {
   452            msg: "A_invalidParam: an invalid parameter was passed in"
   453        };
   454    
   455        /*!
   456         *  Assert raised when attempting to send a message to a core
   457         *  where a transport has not been registered.
   458         */
   459        config Assert.Id A_unregisteredTransport  = {
   460            msg: "A_unregisteredTransport: transport is not registered"
   461        };
   462    
   463        /*!
   464         *  Assert raised when attempting to unblock a remote MessageQ or one that
   465         *  has been configured with a non-blocking synchronizer
   466         */
   467        config Assert.Id A_invalidUnblock  = {
   468            msg: "A_invalidUnblock: Trying to unblock a remote MessageQ or a queue with non-blocking synchronizer"
   469        };
   470    
   471        /*!
   472         *  Error raised if all the message queue objects are taken
   473         */
   474        config Error.Id E_maxReached  = {
   475            msg: "E_maxReached: All objects in use. MessageQ.maxRuntimeEntries is %d"
   476        };
   477    
   478        /*!
   479         *  Error raised when heapId has not been registered
   480         */
   481        config Error.Id E_unregisterHeapId  = {
   482            msg: "E_unregisterHeapId: Heap id %d not registered"
   483        };
   484    
   485        /*!
   486         *  Error raised in a create call when a name fails to be added
   487         *  to the NameServer table.  This can be because the name already
   488         *  exists, the table has reached its max length, or out of memory.
   489         */
   490        config Error.Id E_nameFailed  = {
   491            msg: "E_nameFailed: '%s' name failed to be added to NameServer"
   492        };
   493    
   494        /*!
   495         *  Error raised if the requested queueIndex is not available
   496         */
   497        config Error.Id E_indexNotAvailable  = {
   498            msg: "E_indexNotAvailable: queueIndex %d not available"
   499        };
   500    
   501        /*!
   502         *  Trace setting
   503         *
   504         *  This flag allows the configuration of the default module trace
   505         *  settings.
   506         */
   507        config Bool traceFlag = false;
   508    
   509        /*!
   510         *  Number of heapIds in the system
   511         *
   512         *  This allows MessageQ to pre-allocate the heaps table.
   513         *  The heaps table is used when registering heaps.
   514         *
   515         *  There is no default heap, so unless the system is only using
   516         *  {@link #staticMsgInit}, the application must register a heap.
   517         */
   518        config UInt16 numHeaps = 8;
   519    
   520        /*!
   521         *  Maximum number of MessageQs that can be dynamically created
   522         */
   523        config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
   524    
   525        /*!
   526         *  Number of reserved MessageQ indexes
   527         *
   528         *  An application can request the first N message queue indexes be
   529         *  reserved to be used by MessageQ_create2. MessageQ_create will
   530         *  not use these slots. The application can use any index less than
   531         *  the value of numReservedEntries for the queueIndex field in the
   532         *  MessageQ_Params2 structure.
   533         *
   534         *  numReservedEntries must be equal or less than
   535         *  {@link #maxRuntimeEntries}.
   536         */
   537        config UInt numReservedEntries = 0;
   538    
   539        /*!
   540         *  Gate used to make the name table thread safe
   541         *
   542         *  This gate is used when accessing the name table during
   543         *  a {@link #create}, {@link #delete}, and {@link #open}.
   544         *
   545         *  This gate is also used to protect MessageQ when growing
   546         *  internal tables in the {@link #create}.
   547         *
   548         *  The table is in local memory, not shared memory. So a
   549         *  single processor gate will work.
   550         *
   551         *  The default will be {@link xdc.runtime.knl.GateThread}
   552         *  instance.
   553         */
   554        config IGateProvider.Handle nameTableGate = null;
   555    
   556        /*!
   557         *  Maximum length for Message queue names
   558         */
   559        config UInt maxNameLen = 32;
   560    
   561        /*!
   562         *  Section name is used to place the names table
   563         */
   564        metaonly config String tableSection = null;
   565    
   566        /*!
   567         *  ======== freeHookFxn ========
   568         *  Free function in MessageQ_free after message was freed back to the heap
   569         */
   570        config FreeHookFxn freeHookFxn = null;
   571    
   572        /*!
   573         *  ======== putHookFxn ========
   574         *  Put function hook
   575         */
   576        config PutHookFxn putHookFxn = null;
   577    
   578        /*!
   579         *  ======== registerHeapMeta ========
   580         *  Statically register a heap with MessageQ
   581         *
   582         *  Build error if heapId is in use.
   583         *
   584         *  @param(heap)        Heap to register
   585         *  @param(heapId)      heapId associated with the heap
   586         */
   587        metaonly Void registerHeapMeta(IHeap.Handle heap, UInt16 heapId);
   588    
   589         /*!
   590         *  ======== registerTransportMeta ========
   591         *  Statically register a transport with MessageQ
   592         *
   593         *  Build error if remote processor already has a transport
   594         *  registered.
   595         *
   596         *  @param(transport)   transport to register
   597         *  @param(procId)      procId that transport communicaties with
   598         *  @param(priority)    priority of transport
   599         */
   600         metaonly Void registerTransportMeta(IMessageQTransport.Handle transport,
   601                 UInt16 procId, UInt priority);
   602    
   603        /*!
   604         *  ======== registerTransport ========
   605         *  Register a transport with MessageQ
   606         *
   607         *  This API is called by the transport when it is created.
   608         *
   609         *  @param(transport)   transport to register
   610         *  @param(procId)      MultiProc id that transport communicates with
   611         *  @param(priority)    priority of transport
   612         *
   613         *  @b(returns)         Whether the register was successful.
   614         */
   615        Bool registerTransport(IMessageQTransport.Handle transport, UInt16 procId,
   616            UInt priority);
   617    
   618        /*!
   619         *  ======== unregisterTransport ========
   620         *  Unregister a transport with MessageQ
   621         *
   622         *  @param(procId)      unregister transport that communicates with
   623         *                      this remote processor
   624         *  @param(priority)    priority of transport
   625         */
   626        Void unregisterTransport(UInt16 procId, UInt priority);
   627    
   628    instance:
   629    
   630        /*!
   631         *  ISync handle used to signal IO completion
   632         *
   633         *  The ISync instance is used in the {@link #get} and {@link #put}.
   634         *  The {@link xdc.runtime.knl.ISync#signal} is called as part
   635         *  of the {@link #put} call.  The {@link xdc.runtime.knl.ISync#wait} is
   636         *  called in the {@link #get} if there are no messages present.
   637         */
   638        config ISync.Handle synchronizer = null;
   639    
   640        /*!
   641         *  Requested MessageQ_QueueIndex
   642         *
   643         *  This parameter allows an application to specify the queueIndex to
   644         *  be used for a message queue. To use this functionality, the
   645         *  MessageQ.numReservedEntries static configuration parameter must be
   646         *  set to a specific value.
   647         *
   648         *  The default is {@link #ANY}. This means do that you are not asking for
   649         *  an explicit index. MessageQ will find the first available one which is
   650         *  equal or greater than MessageQ.numReservedEntries.
   651         */
   652        config UInt16 queueIndex = ANY;
   653    
   654        /*! @_nodoc
   655         *  ======== create ========
   656         *  Create a message queue
   657         *
   658         *  @param(name)         Name of the message queue.
   659         */
   660        create(String name);
   661    
   662    internal:
   663        /*
   664         *  The following describes the usage of the flag field
   665         *  ---------------------------------
   666         *  |V V V|T|  reserved   |t t t|P P|
   667         *  ---------------------------------
   668         *   F E D C B A 9 8 7 6 5 4 3 2 1 0
   669         *
   670         *  [15:13] V = version
   671         *  [12]    T = trace flag
   672         *  [11:5]  reserved
   673         *  [4:2]   t = transport Id, zero = default
   674         *  [1:0]   P = priority
   675         */
   676    
   677        /*! Mask to extract version setting */
   678        const UInt VERSIONMASK = 0xE000;
   679    
   680        /*! Version setting */
   681        const UInt HEADERVERSION = 0x2000;
   682    
   683        /*! Mask to extract Trace setting */
   684        const UInt TRACEMASK = 0x1000;
   685    
   686        /*! Shift for Trace setting */
   687        const UInt TRACESHIFT = 12;
   688    
   689        /*!
   690         *  Mask to extract priority setting.
   691         *  This is needed here for ROV but must match
   692         *  the value defined in ti/ipc/MessageQ.h
   693         */
   694        const UInt PRIORITYMASK = 0x3;
   695    
   696        /*! Mask to extract priority setting */
   697        const UInt TRANSPORTPRIORITYMASK = 0x1;
   698    
   699         /*! return code for Instance_init */
   700        const Int PROXY_FAILURE = 1;
   701    
   702        /*
   703         *  Used to denote a message that was initialized
   704         *  with the MessageQ_staticMsgInit function.
   705         */
   706        const UInt16 STATICMSG = 0xFFFF;
   707    
   708        /*! Required first field in every message */
   709        @Opaque struct MsgHeader {
   710            Bits32       reserved0;         /* reserved for List.elem->next */
   711            Bits32       reserved1;         /* reserved for List.elem->prev */
   712            Bits32       msgSize;           /* message size                 */
   713            Bits16       flags;             /* bitmask of different flags   */
   714            Bits16       msgId;             /* message id                   */
   715            Bits16       dstId;             /* destination queue id         */
   716            Bits16       dstProc;           /* destination processor id     */
   717            Bits16       replyId;           /* reply queue id               */
   718            Bits16       replyProc;         /* reply processor id           */
   719            Bits16       srcProc;           /* proc who initialized the msg */
   720            Bits16       heapId;            /* heap id                      */
   721            Bits16       seqNum;            /* sequence number              */
   722            Bits16       reserved;          /* reserved                     */
   723        };
   724    
   725        struct HeapEntry {
   726            IHeap.Handle  heap;
   727            UInt16        heapId;
   728        };
   729    
   730        struct TransportEntry {
   731            IMessageQTransport.Handle  transport;
   732            UInt16             procId;
   733        };
   734    
   735        enum TransportType {
   736            TransportType_IMessageQTransport,
   737            TransportType_INetworkTransport,
   738            TransportType_Invalid
   739        };
   740    
   741        struct RegisteredTransport {
   742            ITransport.Handle transport;
   743            TransportType type;
   744        };
   745    
   746        /*!
   747         *  ======== nameSrvPrms ========
   748         *  This Params object is used for temporary storage of the
   749         *  module wide parameters that are for setting the NameServer instance.
   750         */
   751        metaonly config NameServer.Params nameSrvPrms;
   752    
   753        /*!
   754         *  Statically registered heaps
   755         *
   756         *  This configuration parameter allows the static registeration
   757         *  of heaps. The index of the array corresponds to the heapId.
   758         */
   759        metaonly config HeapEntry staticHeaps[];
   760    
   761        /*!
   762         *  Statically registered transports
   763         *
   764         *  This configuration parameter allows the static registeration
   765         *  of transports. The index of the array corresponds to the procId.
   766         */
   767        metaonly config TransportEntry staticTransports[];
   768    
   769        /*!
   770         *  Allows for the number of dynamically created message queues to grow.
   771         */
   772        UInt16 grow(Object *obj, Error.Block *eb);
   773    
   774        struct Instance_State {
   775            QueueId         queue;        /* Unique id                     */
   776            ISync.Handle    synchronizer; /* completion synchronizer       */
   777            List.Object     normalList;   /* Embedded List objects         */
   778            List.Object     highList;     /* Embedded List objects         */
   779            Ptr             nsKey;        /* unique NameServer key         */
   780            SyncSem.Handle  syncSemHandle;/* for use in finalize           */
   781            Bool            unblocked;    /* Whether MessageQ is unblocked */
   782        };
   783    
   784        struct Module_State {
   785            IMessageQTransport.Handle transports[length][2];
   786            Handle               queues[];
   787            IHeap.Handle         heaps[];
   788            IGateProvider.Handle gate;
   789            UInt16               numQueues;
   790            UInt16               numHeaps;
   791            NameServer.Handle    nameServer;
   792            FreeHookFxn          freeHookFxn;
   793            PutHookFxn           putHookFxn;
   794            Bool                 canFreeQueues;
   795            UInt16               seqNum;
   796            RegisteredTransport  regTrans[8];
   797        };
   798    }