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