1    /* --COPYRIGHT--,BSD
     2     * Copyright (c) $(CPYYEAR), 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     * --/COPYRIGHT--*/
    32    /*
    33     *  ======== MessageQ.xdc ========
    34     *
    35     *! Revision History
    36     *! ================
    37     *! 26-Feb-2010 skp     Fixed SDOCM00067176 (QueueId defined in MessageQ.xdc)
    38     *! 16-Feb-2010 jv      Fix a couple of issues from SDOCM00066822 here.
    39     *! 04-Feb-2010 skp     Removed 'name' from Instance state
    40     *! 07-Aug-2008 skp     cdoc cleanup
    41     *! 04-Jun-2008 agd     cdoc cleanup
    42     *! 14-Dec-2007 connell updated call context table
    43     *! 06-Jun-2007 toddm   nodoc'd the whole module. Not supported in BIOS 6.0.
    44     *! 11-May-2007 agd     Addressed SDSCM00016616
    45     *! 16-Apr-2007 cmcc    Added calling context table
    46     *! 29-Sep-2006 toddm   Added error block into MessageQ_alloc
    47     *! 10-Apr-2006 toddm   created
    48     */
    49    
    50    package ti.sdo.ipc;
    51    
    52    import xdc.runtime.IHeap;
    53    import xdc.runtime.Assert;
    54    import xdc.runtime.Error;
    55    import xdc.runtime.Diags;
    56    import xdc.runtime.Log;
    57    import xdc.runtime.IGateProvider;
    58    import xdc.runtime.knl.ISync;
    59    
    60    import ti.sysbios.syncs.SyncSem;
    61    
    62    import ti.sdo.ipc.interfaces.IMessageQTransport;
    63    import ti.sdo.utils.NameServer;
    64    import ti.sdo.utils.List;
    65    
    66    import xdc.rov.ViewInfo;
    67    
    68    /*!
    69     *  ======== MessageQ ======== 
    70     *  Message-passing with queuing
    71     *
    72     *  The MessageQ module supports the structured sending and receiving of 
    73     *  variable length messages. This module can be used for homogeneous
    74     *  (DSP to DSP)  or heterogeneous (Arm to DSP) multi-processor messaging. 
    75     * 
    76     *  MessageQ provides more sophisticated messaging than other modules. It is
    77     *  typically used for complex situations such as multi-processor messaging. 
    78     * 
    79     *  The following are key features of the MessageQ module:
    80     *  @p(blist)
    81     *  -Writers and readers can be relocated to another processor with no
    82     *   runtime code changes.
    83     *  -Timeouts are allowed when receiving messages.
    84     *  -Readers can determine the writer and reply back.
    85     *  -Receiving a message is deterministic when the timeout is zero.
    86     *  -Messages can reside on any message queue.
    87     *  -Supports zero-copy transfers.
    88     *  -Can send and receive from any type of thread.
    89     *  -Notification mechanism is specified by application.
    90     *  -Allows QoS (quality of service) on message buffer pools. For example,
    91     *   using specific buffer pools for specific message queues.
    92     *  @p
    93     *
    94     *  Messages are sent and received by being placed on and removed from a
    95     *  message queue. A reader is a thread that gets (reads) messages from a
    96     *  message queue. A writer is a thread that puts (writes) a message to a
    97     *  message queue. Each message queue has one reader and can have many writers.
    98     *  A thread may read from or write to multiple message queues.
    99     *
   100     *  Conceptually, the reader thread owns a message queue. The reader thread
   101     *  creates a message queue. The writer threads open a created message queue
   102     *  to get access to them.
   103     *
   104     *  Message queues are identified by a system-wide unique name. Internally, 
   105     *  MessageQ uses the {@link ti.sdo.utils.NameServer} module for managing 
   106     *  these names. The names are used for opening a message queue.
   107     * 
   108     *  Messages must be allocated from the MessageQ module. Once a message is
   109     *  allocated, it can be sent to any message queue. Once a message is sent, the
   110     *  writer loses ownership of the message and should not attempt to modify the
   111     *  message. Once the reader receives the message, it owns the message. It
   112     *  may either free the message or re-use the message.
   113     *
   114     *  Messages in a message queue can be of variable length. The only
   115     *  requirement is that the first field in the definition of a message must be a
   116     *  {@link #MsgHeader} structure. For example:
   117     *  @p(code)
   118     *  typedef struct MyMsg {
   119     *      MessageQ_MsgHeader header;
   120     *      ...
   121     *  } MyMsg;
   122     *  @p
   123     *
   124     *  The MessageQ API uses the MessageQ_MsgHeader internally. Your application
   125     *  should not modify or directly access the fields in the MessageQ_MsgHeader.
   126     *
   127     *  All messages sent via the MessageQ module must be allocated from a 
   128     *  {@link xdc.runtime.IHeap} implementation. The heap can also be used for
   129     *  other memory allocation not related to MessageQ.
   130     *
   131     *  An application can use multiple heaps. The purpose of having multiple
   132     *  heaps is to allow an application to regulate its message usage. For
   133     *  example, an application can allocate critical messages from one heap of fast
   134     *  on-chip memory and non-critical messages from another heap of slower
   135     *  external memory.
   136     *
   137     *  The {@link #registerHeap} and {@link #registerHeapMeta} are APIs used to
   138     *  assign a MessageQ heapId to a heap. When allocating a message, the heapId
   139     *  is used, not the heap handle. This heapId is actually placed into the 
   140     *  message (part of the {@link #MsgHeader}). Care must be taken when assigning
   141     *  heapIds. Refer to the {@link #registerHeap} and {@link #registerHeapMeta}
   142     *  descriptions for more details.
   143     *
   144     *  MessageQ also supports the usage of messages that are not allocated via the
   145     *  {@link #alloc} function. Please refer to the {@link #staticMsgInit}
   146     *  function description for more details.
   147     *
   148     *  MessageQ supports reads/writes of different thread models. This is
   149     *  accomplished by having the creator of the message queue specify a 
   150     *  {@link xdc.runtime.knl.ISync#Object} via the {@link #synchronizer}
   151     *  configuration parameter. The {@link xdc.runtime.knl.ISync#signal} 
   152     *  portion of the ISync instance is called whenever the {@link #put}
   153     *  is called. The {@link xdc.runtime.knl.ISync#wait} portion is 
   154     *  called in the {@link #get} if and only if there are no messages.
   155     *
   156     *  Since ISyncs are binary, the reader must drain the message queue of all
   157     *  messages before waiting for another signal. For example, if the reader 
   158     *  was a SYSBIOS Swi, the {@link xdc.runtime.knl.ISync} instance 
   159     *  could be a SyncSwi. If a {@link #put} was called, the Swi_post() would 
   160     *  be called. The Swi would run and it must call {@link #get} until no 
   161     *  messages are returned.
   162     * 
   163     *  In a multiple processor system, MessageQ communicates to other
   164     *  processors via {@link ti.sdo.ipc.interfaces.IMessageQTransport} instances.  
   165     *  MessageQ supports a high priority and a normal priority transport between 
   166     *  any two processors. The IMessageQTransport instances are created via the
   167     *  {@link #SetupTransportProxy}. The instances are responsible for
   168     *  registering themselves with MessageQ. This is accomplished via the
   169     * {@link #registerTransport} function.
   170     */
   171    
   172    @ModuleStartup 
   173    @InstanceInitError
   174    @InstanceFinalize
   175    
   176    module MessageQ
   177    {
   178        /*!
   179         *  ======== QueuesView ========
   180         *  @_nodoc
   181         */
   182        metaonly struct QueuesView {
   183            String  name;
   184            UInt    queueId;
   185        }
   186        
   187        /*!
   188         *  ======== MessagesView ========
   189         *  @_nodoc
   190         */
   191        metaonly struct MessagesView {
   192            Int          seqNum;
   193            Int          msgSize;
   194            String       priority;
   195            String       srcProc;        
   196            String       replyProc;
   197            String       replyId;
   198            Int          msgId;          
   199            String       heap;
   200            Bool         traceEnabled;
   201            Int          version;
   202        }
   203    
   204        /*!
   205         *  ======== ModuleView ========
   206         *  @_nodoc
   207         */
   208        metaonly struct ModuleView {        
   209            String               heaps[];        
   210            String               gate;
   211            UInt16               nextSeqNum;
   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        /*! MessageQ ID */
   351        typedef UInt32 QueueId;
   352        
   353        /*!
   354         *  ======== SetupTransportProxy ========
   355         *  MessageQ transport setup proxy
   356         */
   357        proxy SetupTransportProxy inherits ti.sdo.ipc.interfaces.ITransportSetup;
   358        
   359        /*!
   360         *  Message priority values. These must match the values defined in
   361         *  ti/ipc/MessageQ.h but are needed here for ROV.
   362         */
   363        const UInt NORMALPRI   = 0;
   364        const UInt HIGHPRI     = 1;
   365        const UInt RESERVEDPRI = 2;
   366        const UInt URGENTPRI   = 3;
   367        
   368        /*!
   369         *  Assert raised when calling API with wrong handle
   370         *
   371         *  Some APIs can only be called with an opened handle (e.g. 
   372         *  {@link #close}. Some can only be called with a created handle
   373         *  (e.g. {@link #get}).
   374         */
   375        config Assert.Id A_invalidContext  = {
   376            msg: "A_invalidContext: Cannot call with an open/create handle"
   377        };
   378                
   379        /*!
   380         *  Assert raised when attempting to free a static message
   381         */
   382        config Assert.Id A_cannotFreeStaticMsg  = {
   383            msg: "A_cannotFreeStaticMsg: Cannot call MessageQ_free with static msg"
   384        };
   385        
   386        /*!
   387         *  Assert raised when an invalid message is supplied
   388         */
   389        config Assert.Id A_invalidMsg  = {
   390            msg: "A_invalidMsg: Invalid message"
   391        };
   392    
   393        /*!
   394         *  Assert raised when an invalid queueId is supplied
   395         */
   396        config Assert.Id A_invalidQueueId  = {
   397            msg: "A_invalidQueueId: Invalid queueId is used"
   398        };
   399    
   400        /*!
   401         *  Assert raised when using an invalid heapId
   402         */
   403        config Assert.Id A_heapIdInvalid  = {
   404            msg: "A_heapIdInvalid: heapId is invalid"
   405        };
   406        
   407        /*!
   408         *  Assert raised when using an invalid procId
   409         */
   410        config Assert.Id A_procIdInvalid  = {
   411            msg: "A_procIdInvalid: procId is invalid"
   412        };
   413        
   414        /*!
   415         *  Assert raised for an invalid MessageQ object 
   416         */
   417        config Assert.Id A_invalidObj  = {
   418            msg: "A_invalidObj: an invalid obj is used"
   419        };
   420    
   421        /*!
   422         *  Assert raised for an invalid parameter 
   423         */
   424        config Assert.Id A_invalidParam  = {
   425            msg: "A_invalidParam: an invalid parameter was passed in"
   426        };
   427    
   428        /*!
   429         *  Assert raised when attempting to send a message to a core
   430         *  where a transport has not been registered.
   431         */
   432        config Assert.Id A_unregisteredTransport  = {
   433            msg: "A_unregisteredTransport: transport is not registered"
   434        };
   435        
   436        /*!
   437         *  Assert raised when attempting to unblock a remote MessageQ or one that
   438         *  has been configured with a non-blocking synchronizer
   439         */
   440        config Assert.Id A_invalidUnblock  = {
   441            msg: "A_invalidUnblock: Trying to unblock a remote MessageQ or a queue with non-blocking synchronizer"
   442        };
   443        
   444        /*!
   445         *  Error raised if all the message queue objects are taken
   446         */
   447        config Error.Id E_maxReached  = {
   448            msg: "E_maxReached: All objects in use. MessageQ.maxRuntimeEntries is %d"
   449        };
   450        
   451        /*!
   452         *  Error raised when heapId has not been registered
   453         */
   454        config Error.Id E_unregisterHeapId  = {
   455            msg: "E_unregisterHeapId: Heap id %d not registered"
   456        };
   457    
   458        /*!
   459         *  Error raised in a create call when a name fails to be added
   460         *  to the NameServer table.  This can be because the name already
   461         *  exists, the table has reached its max length, or out of memory.
   462         */
   463        config Error.Id E_nameFailed  = {
   464            msg: "E_nameFailed: '%s' name failed to be added to NameServer"
   465        };
   466    
   467        /*!
   468         *  Trace setting
   469         *
   470         *  This flag allows the configuration of the default module trace 
   471         *  settings.     
   472         */
   473        config Bool traceFlag = false;    
   474        
   475        /*!
   476         *  Number of heapIds in the system
   477         *
   478         *  This allows MessageQ to pre-allocate the heaps table.
   479         *  The heaps table is used when registering heaps.
   480         *
   481         *  There is no default heap, so unless the system is only using
   482         *  {@link #staticMsgInit}, the application must register a heap.
   483         */
   484        config UInt16 numHeaps = 8;
   485        
   486        /*! 
   487         *  Maximum number of MessageQs that can be dynamically created
   488         */
   489        config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
   490        
   491        /*! 
   492         *  Gate used to make the name table thread safe
   493         *
   494         *  This gate is used when accessing the name table during 
   495         *  a {@link #create}, {@link #delete}, and {@link #open}.
   496         *
   497         *  This gate is also used to protect MessageQ when growing
   498         *  internal tables in the {@link #create}.
   499         *
   500         *  The table is in local memory, not shared memory. So a
   501         *  single processor gate will work.
   502         *
   503         *  The default will be {@link xdc.runtime.knl.GateThread}
   504         *  instance.
   505         */
   506        config IGateProvider.Handle nameTableGate = null;
   507        
   508        /*! 
   509         *  Maximum length for Message queue names
   510         */
   511        config UInt maxNameLen = 32;
   512    
   513        /*! 
   514         *  Section name is used to place the names table
   515         */
   516        metaonly config String tableSection = null;
   517        
   518        /*!
   519         *  ======== registerHeapMeta ========
   520         *  Statically register a heap with MessageQ
   521         *
   522         *  Build error if heapId is in use.
   523         *
   524         *  @param(heap)        Heap to register
   525         *  @param(heapId)      heapId associated with the heap
   526         */
   527        metaonly Void registerHeapMeta(IHeap.Handle heap, UInt16 heapId);
   528         
   529         /*!
   530         *  ======== registerTransportMeta ========
   531         *  Statically register a transport with MessageQ
   532         *
   533         *  Build error if remote processor already has a transport
   534         *  registered.
   535         *
   536         *  @param(transport)   transport to register
   537         *  @param(procId)      procId that transport communicaties with
   538         *  @param(priority)    priority of transport
   539         */
   540         metaonly Void registerTransportMeta(IMessageQTransport.Handle transport, UInt16 procId, UInt priority);
   541         
   542        /*!
   543         *  ======== registerTransport ========
   544         *  Register a transport with MessageQ
   545         *
   546         *  This API is called by the transport when it is created.
   547         *
   548         *  @param(transport)   transport to register
   549         *  @param(procId)      MultiProc id that transport communicates with
   550         *  @param(priority)    priority of transport
   551         *
   552         *  @b(returns)         Whether the register was successful.
   553         */
   554        Bool registerTransport(IMessageQTransport.Handle transport, UInt16 procId,
   555            UInt priority);
   556    
   557        /*!
   558         *  ======== unregisterTransport ========
   559         *  Unregister a transport with MessageQ
   560         *
   561         *  @param(procId)      unregister transport that communicates with
   562         *                      this remote processor
   563         *  @param(priority)    priority of transport
   564         */
   565        Void unregisterTransport(UInt16 procId, UInt priority);
   566        
   567    instance:
   568      
   569        /*! 
   570         *  ISync handle used to signal IO completion 
   571         *
   572         *  The ISync instance is used in the {@link #get} and {@link #put}.
   573         *  The {@link xdc.runtime.knl.ISync#signal} is called as part
   574         *  of the {@link #put} call.  The {@link xdc.runtime.knl.ISync#wait} is 
   575         *  called in the {@link #get} if there are no messages present.
   576         */
   577        config ISync.Handle synchronizer = null;
   578        
   579        /*! @_nodoc
   580         *  ======== create ========
   581         *  Create a message queue
   582         *
   583         *  @param(name)         Name of the message queue.
   584         */
   585        create(String name);   
   586        
   587    internal:
   588        /* 
   589         *  The following describes the usage of the flag field     
   590         *  ---------------------------------
   591         *  |V V V|T|     reserved      |P P|
   592         *  ---------------------------------
   593         *   E D C B A 0 9 8 7 6 5 4 3 2 1 0
   594         *     
   595         *  V = version
   596         *  P = priority
   597         *  T = trace flag
   598         */
   599    
   600        /*! Mask to extract version setting */
   601        const UInt VERSIONMASK = 0xE000;
   602        
   603        /*! Version setting */
   604        const UInt HEADERVERSION = 0x2000;
   605        
   606        /*! Mask to extract Trace setting */
   607        const UInt TRACEMASK = 0x1000;
   608        
   609        /*! Shift for Trace setting */
   610        const UInt TRACESHIFT = 12;
   611           
   612        /*!
   613         *  Mask to extract priority setting.
   614         *  This is needed here for ROV but must match
   615         *  the value defined in ti/ipc/MessageQ.h
   616         */
   617        const UInt PRIORITYMASK = 0x3;
   618        
   619        /*! Mask to extract priority setting */
   620        const UInt TRANSPORTPRIORITYMASK = 0x1;
   621            
   622         /*! return code for Instance_init */
   623        const Int PROXY_FAILURE = 1;
   624    
   625        /* 
   626         *  Used to denote a message that was initialized 
   627         *  with the MessageQ_staticMsgInit function.
   628         */
   629        const UInt16 STATICMSG = 0xFFFF;
   630    
   631        /*! Required first field in every message */
   632        @Opaque struct MsgHeader {
   633            Bits32       reserved0;         /* reserved for List.elem->next */
   634            Bits32       reserved1;         /* reserved for List.elem->prev */
   635            Bits32       msgSize;           /* message size                 */
   636            Bits16       flags;             /* bitmask of different flags   */
   637            Bits16       msgId;             /* message id                   */
   638            Bits16       dstId;             /* destination processor id     */
   639            Bits16       dstProc;           /* destination processor        */
   640            Bits16       replyId;           /* reply id                     */
   641            Bits16       replyProc;         /* reply processor              */
   642            Bits16       srcProc;           /* source processor             */
   643            Bits16       heapId;            /* heap id                      */
   644            Bits16       seqNum;            /* sequence number              */
   645            Bits16       reserved;          /* reserved                     */
   646        };
   647        
   648        struct HeapEntry {
   649            IHeap.Handle  heap;
   650            UInt16        heapId;
   651        };
   652        
   653        struct TransportEntry {
   654            IMessageQTransport.Handle  transport;
   655            UInt16             procId;
   656        };
   657        
   658        /*! 
   659         *  ======== nameSrvPrms ========
   660         *  This Params object is used for temporary storage of the
   661         *  module wide parameters that are for setting the NameServer instance.
   662         */
   663        metaonly config NameServer.Params nameSrvPrms;
   664        
   665        /*! 
   666         *  Statically registered heaps
   667         *
   668         *  This configuration parameter allows the static registeration
   669         *  of heaps. The index of the array corresponds to the heapId.     
   670         */
   671        metaonly config HeapEntry staticHeaps[];
   672        
   673        /*! 
   674         *  Statically registered transports
   675         *
   676         *  This configuration parameter allows the static registeration
   677         *  of transports. The index of the array corresponds to the procId.     
   678         */
   679        metaonly config TransportEntry staticTransports[];
   680        
   681        /*!
   682         *  Allows for the number of dynamically created message queues to grow.
   683         */
   684        UInt16 grow(Object *obj, Error.Block *eb);
   685      
   686        struct Instance_State {
   687            QueueId         queue;        /* Unique id                     */
   688            ISync.Handle    synchronizer; /* completion synchronizer       */
   689            List.Object     normalList;   /* Embedded List objects         */
   690            List.Object     highList;     /* Embedded List objects         */
   691            Ptr             nsKey;        /* unique NameServer key         */
   692            SyncSem.Handle  syncSemHandle;/* for use in finalize           */
   693            Bool            unblocked;    /* Whether MessageQ is unblocked */
   694        };
   695      
   696        struct Module_State {        
   697            IMessageQTransport.Handle transports[][2];
   698            Handle               queues[];        
   699            IHeap.Handle         heaps[];        
   700            IGateProvider.Handle gate;
   701            UInt16               numQueues;
   702            UInt16               numHeaps;        
   703            NameServer.Handle    nameServer;
   704            Bool                 canFreeQueues;
   705            UInt16               seqNum;
   706        };
   707    }