]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - src/ti/sdo/ipc/MessageQ.xdc
Rename: Renamed packages to src to allow application of ipc-j tree commits.
[ipc/ipcdev.git] / src / ti / sdo / ipc / MessageQ.xdc
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  */
37 package ti.sdo.ipc;
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;
47 import ti.sysbios.syncs.SyncSem;
49 import ti.sdo.ipc.interfaces.IMessageQTransport;
50 import ti.sdo.utils.NameServer;
51 import ti.sdo.utils.List;
53 import xdc.rov.ViewInfo;
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  */
159 @ModuleStartup
160 @InstanceInitError
161 @InstanceFinalize
163 module MessageQ
165     /*!
166      *  ======== QueuesView ========
167      *  @_nodoc
168      */
169     metaonly struct QueuesView {
170         String  name;
171         UInt    queueId;
172     }
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     }
191     /*!
192      *  ======== ModuleView ========
193      *  @_nodoc
194      */
195     metaonly struct ModuleView {
196         String               heaps[];
197         String               gate;
198         UInt16               nextSeqNum;
199     }
201     /*!
202      *  ======== rovViewInfo ========
203      *  @_nodoc
204      */
205     @Facet
206     metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
207         xdc.rov.ViewInfo.create({
208             viewMap: [
209                 ['Queues',
210                     {
211                         type: xdc.rov.ViewInfo.INSTANCE,
212                         viewInitFxn: 'viewInitQueues',
213                         structName: 'QueuesView'
214                     }
215                 ],
216                 ['Messages',
217                     {
218                         type: xdc.rov.ViewInfo.INSTANCE_DATA,
219                         viewInitFxn: 'viewInitMessages',
220                         structName: 'MessagesView'
221                     }
222                 ],
223                 ['Module',
224                     {
225                         type: xdc.rov.ViewInfo.MODULE,
226                         viewInitFxn: 'viewInitModule',
227                         structName: 'ModuleView'
228                     }
229                 ]
230             ]
231         });
233     /*!
234      *  ======== LM_setTrace ========
235      *  Logged when setting the trace flag on a message
236      *
237      *  This is logged when tracing on a message is set via
238      *  {@link #setMsgTrace}.
239      */
240     config Log.Event LM_setTrace = {
241         mask: Diags.USER1,
242         msg: "LM_setTrace: Message 0x%x (seqNum = %d, srcProc = %d) traceFlag = %d"
243     };
245     /*!
246      *  ======== LM_alloc ========
247      *  Logged when allocating a message
248      *
249      *  When the {@link #traceFlag} is true, all message allocations
250      *  are logged.
251      */
252     config Log.Event LM_alloc = {
253         mask: Diags.USER1,
254         msg: "LM_alloc: Message 0x%x (seqNum = %d, srcProc = %d) was allocated"
255     };
257     /*!
258      *  ======== LM_staticMsgInit ========
259      *  Logged when statically initializing a message
260      *
261      *  When the {@link #traceFlag} is true, all messages that
262      *  are statically initialized via {@link #staticMsgInit} are logged.
263      */
264     config Log.Event LM_staticMsgInit = {
265         mask: Diags.USER1,
266         msg: "LM_staticMsgInit: Message 0x%x (seqNum = %d, srcProc = %d) was set in MessageQ_staticMsgInit"
267     };
269     /*!
270      *  ======== LM_free ========
271      *  Logged when freeing a message
272      *
273      *  When the {@link #traceFlag} is true, all freeing of messages
274      *  are logged. If an individual message's tracing was enabled
275      *  via {@link #setMsgTrace}, the MessageQ_free is also logged.
276      */
277     config Log.Event LM_free = {
278         mask: Diags.USER1,
279         msg: "LM_free: Message 0x%x (seqNum = %d, srcProc = %d) was freed"
280     };
282     /*!
283      *  ======== LM_putLocal ========
284      *  Logged when a message is placed onto a local queue
285      *
286      *  When the {@link #traceFlag} is true, all putting of messages
287      *  are logged. If an individual message's tracing was enabled
288      *  via {@link #setMsgTrace}, the MessageQ_put is also logged.
289      */
290     config Log.Event LM_putLocal = {
291         mask: Diags.USER1,
292         msg: "LM_putLocal: Message 0x%x (seqNum = %d, srcProc = %d) was placed onto queue 0x%x"
293     };
295     /*!
296      *  ======== LM_putRemote ========
297      *  Logged when a message is given to a transport
298      *
299      *  When the {@link #traceFlag} is true, all putting of messages
300      *  to a transport are logged. If an individual message's tracing
301      *  was enabled  via {@link #setMsgTrace}, the MessageQ_put is
302      *  also logged.
303      */
304     config Log.Event LM_putRemote = {
305         mask: Diags.USER1,
306         msg: "LM_putRemote: Message 0x%x (seqNum = %d, srcProc = %d) was given to processor %d transport"
307     };
309     /*!
310      *  ======== LM_rcvByTransport ========
311      *  Logged when a transport receives an incoming message
312      *
313      *  When the {@link #traceFlag} is true, all incoming messages
314      *  are logged. If an individual message's tracing
315      *  was enabled  via {@link #setMsgTrace}, the receiving of a message is
316      *  also logged.
317      */
318     config Log.Event LM_rcvByTransport = {
319         mask: Diags.USER1,
320         msg: "LM_rcvByTransport: Message 0x%x (seqNum = %d, srcProc = %d) was received"
321     };
323     /*!
324      *  ======== LM_get ========
325      *  Logged when a message is received off the queue
326      *
327      *  When the {@link #traceFlag} is true, all getting of messages
328      *  are logged. If an individual message's tracing
329      *  was enabled  via {@link #setMsgTrace}, the MessageQ_get is
330      *  also logged.
331      */
332     config Log.Event LM_get = {
333         mask: Diags.USER1,
334         msg: "LM_get: Message 0x%x (seqNum = %d, srcProc = %d) was received by queue 0x%x"
335     };
337     /*! MessageQ ID */
338     typedef UInt32 QueueId;
340     /*!
341      *  ======== SetupTransportProxy ========
342      *  MessageQ transport setup proxy
343      */
344     proxy SetupTransportProxy inherits ti.sdo.ipc.interfaces.ITransportSetup;
346     /*!
347      *  Message priority values. These must match the values defined in
348      *  ti/ipc/MessageQ.h but are needed here for ROV.
349      */
350     const UInt NORMALPRI   = 0;
351     const UInt HIGHPRI     = 1;
352     const UInt RESERVEDPRI = 2;
353     const UInt URGENTPRI   = 3;
355     /*!
356      *  Assert raised when calling API with wrong handle
357      *
358      *  Some APIs can only be called with an opened handle (e.g.
359      *  {@link #close}. Some can only be called with a created handle
360      *  (e.g. {@link #get}).
361      */
362     config Assert.Id A_invalidContext  = {
363         msg: "A_invalidContext: Cannot call with an open/create handle"
364     };
366     /*!
367      *  Assert raised when attempting to free a static message
368      */
369     config Assert.Id A_cannotFreeStaticMsg  = {
370         msg: "A_cannotFreeStaticMsg: Cannot call MessageQ_free with static msg"
371     };
373     /*!
374      *  Assert raised when an invalid message is supplied
375      */
376     config Assert.Id A_invalidMsg  = {
377         msg: "A_invalidMsg: Invalid message"
378     };
380     /*!
381      *  Assert raised when an invalid queueId is supplied
382      */
383     config Assert.Id A_invalidQueueId  = {
384         msg: "A_invalidQueueId: Invalid queueId is used"
385     };
387     /*!
388      *  Assert raised when using an invalid heapId
389      */
390     config Assert.Id A_heapIdInvalid  = {
391         msg: "A_heapIdInvalid: heapId is invalid"
392     };
394     /*!
395      *  Assert raised when using an invalid procId
396      */
397     config Assert.Id A_procIdInvalid  = {
398         msg: "A_procIdInvalid: procId is invalid"
399     };
401     /*!
402      *  Assert raised for an invalid MessageQ object
403      */
404     config Assert.Id A_invalidObj  = {
405         msg: "A_invalidObj: an invalid obj is used"
406     };
408     /*!
409      *  Assert raised for an invalid parameter
410      */
411     config Assert.Id A_invalidParam  = {
412         msg: "A_invalidParam: an invalid parameter was passed in"
413     };
415     /*!
416      *  Assert raised when attempting to send a message to a core
417      *  where a transport has not been registered.
418      */
419     config Assert.Id A_unregisteredTransport  = {
420         msg: "A_unregisteredTransport: transport is not registered"
421     };
423     /*!
424      *  Assert raised when attempting to unblock a remote MessageQ or one that
425      *  has been configured with a non-blocking synchronizer
426      */
427     config Assert.Id A_invalidUnblock  = {
428         msg: "A_invalidUnblock: Trying to unblock a remote MessageQ or a queue with non-blocking synchronizer"
429     };
431     /*!
432      *  Error raised if all the message queue objects are taken
433      */
434     config Error.Id E_maxReached  = {
435         msg: "E_maxReached: All objects in use. MessageQ.maxRuntimeEntries is %d"
436     };
438     /*!
439      *  Error raised when heapId has not been registered
440      */
441     config Error.Id E_unregisterHeapId  = {
442         msg: "E_unregisterHeapId: Heap id %d not registered"
443     };
445     /*!
446      *  Error raised in a create call when a name fails to be added
447      *  to the NameServer table.  This can be because the name already
448      *  exists, the table has reached its max length, or out of memory.
449      */
450     config Error.Id E_nameFailed  = {
451         msg: "E_nameFailed: '%s' name failed to be added to NameServer"
452     };
454     /*!
455      *  Trace setting
456      *
457      *  This flag allows the configuration of the default module trace
458      *  settings.
459      */
460     config Bool traceFlag = false;
462     /*!
463      *  Number of heapIds in the system
464      *
465      *  This allows MessageQ to pre-allocate the heaps table.
466      *  The heaps table is used when registering heaps.
467      *
468      *  There is no default heap, so unless the system is only using
469      *  {@link #staticMsgInit}, the application must register a heap.
470      */
471     config UInt16 numHeaps = 8;
473     /*!
474      *  Maximum number of MessageQs that can be dynamically created
475      */
476     config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
478     /*!
479      *  Gate used to make the name table thread safe
480      *
481      *  This gate is used when accessing the name table during
482      *  a {@link #create}, {@link #delete}, and {@link #open}.
483      *
484      *  This gate is also used to protect MessageQ when growing
485      *  internal tables in the {@link #create}.
486      *
487      *  The table is in local memory, not shared memory. So a
488      *  single processor gate will work.
489      *
490      *  The default will be {@link xdc.runtime.knl.GateThread}
491      *  instance.
492      */
493     config IGateProvider.Handle nameTableGate = null;
495     /*!
496      *  Maximum length for Message queue names
497      */
498     config UInt maxNameLen = 32;
500     /*!
501      *  Section name is used to place the names table
502      */
503     metaonly config String tableSection = null;
505     /*!
506      *  ======== registerHeapMeta ========
507      *  Statically register a heap with MessageQ
508      *
509      *  Build error if heapId is in use.
510      *
511      *  @param(heap)        Heap to register
512      *  @param(heapId)      heapId associated with the heap
513      */
514     metaonly Void registerHeapMeta(IHeap.Handle heap, UInt16 heapId);
516      /*!
517      *  ======== registerTransportMeta ========
518      *  Statically register a transport with MessageQ
519      *
520      *  Build error if remote processor already has a transport
521      *  registered.
522      *
523      *  @param(transport)   transport to register
524      *  @param(procId)      procId that transport communicaties with
525      *  @param(priority)    priority of transport
526      */
527      metaonly Void registerTransportMeta(IMessageQTransport.Handle transport, UInt16 procId, UInt priority);
529     /*!
530      *  ======== registerTransport ========
531      *  Register a transport with MessageQ
532      *
533      *  This API is called by the transport when it is created.
534      *
535      *  @param(transport)   transport to register
536      *  @param(procId)      MultiProc id that transport communicates with
537      *  @param(priority)    priority of transport
538      *
539      *  @b(returns)         Whether the register was successful.
540      */
541     Bool registerTransport(IMessageQTransport.Handle transport, UInt16 procId,
542         UInt priority);
544     /*!
545      *  ======== unregisterTransport ========
546      *  Unregister a transport with MessageQ
547      *
548      *  @param(procId)      unregister transport that communicates with
549      *                      this remote processor
550      *  @param(priority)    priority of transport
551      */
552     Void unregisterTransport(UInt16 procId, UInt priority);
554 instance:
556     /*!
557      *  ISync handle used to signal IO completion
558      *
559      *  The ISync instance is used in the {@link #get} and {@link #put}.
560      *  The {@link xdc.runtime.knl.ISync#signal} is called as part
561      *  of the {@link #put} call.  The {@link xdc.runtime.knl.ISync#wait} is
562      *  called in the {@link #get} if there are no messages present.
563      */
564     config ISync.Handle synchronizer = null;
566     /*! @_nodoc
567      *  ======== create ========
568      *  Create a message queue
569      *
570      *  @param(name)         Name of the message queue.
571      */
572     create(String name);
574 internal:
575     /*
576      *  The following describes the usage of the flag field
577      *  ---------------------------------
578      *  |V V V|T|     reserved      |P P|
579      *  ---------------------------------
580      *   E D C B A 0 9 8 7 6 5 4 3 2 1 0
581      *
582      *  V = version
583      *  P = priority
584      *  T = trace flag
585      */
587     /*! Mask to extract version setting */
588     const UInt VERSIONMASK = 0xE000;
590     /*! Version setting */
591     const UInt HEADERVERSION = 0x2000;
593     /*! Mask to extract Trace setting */
594     const UInt TRACEMASK = 0x1000;
596     /*! Shift for Trace setting */
597     const UInt TRACESHIFT = 12;
599     /*!
600      *  Mask to extract priority setting.
601      *  This is needed here for ROV but must match
602      *  the value defined in ti/ipc/MessageQ.h
603      */
604     const UInt PRIORITYMASK = 0x3;
606     /*! Mask to extract priority setting */
607     const UInt TRANSPORTPRIORITYMASK = 0x1;
609      /*! return code for Instance_init */
610     const Int PROXY_FAILURE = 1;
612     /*
613      *  Used to denote a message that was initialized
614      *  with the MessageQ_staticMsgInit function.
615      */
616     const UInt16 STATICMSG = 0xFFFF;
618     /*! Required first field in every message */
619     @Opaque struct MsgHeader {
620         Bits32       reserved0;         /* reserved for List.elem->next */
621         Bits32       reserved1;         /* reserved for List.elem->prev */
622         Bits32       msgSize;           /* message size                 */
623         Bits16       flags;             /* bitmask of different flags   */
624         Bits16       msgId;             /* message id                   */
625         Bits16       dstId;             /* destination processor id     */
626         Bits16       dstProc;           /* destination processor        */
627         Bits16       replyId;           /* reply id                     */
628         Bits16       replyProc;         /* reply processor              */
629         Bits16       srcProc;           /* source processor             */
630         Bits16       heapId;            /* heap id                      */
631         Bits16       seqNum;            /* sequence number              */
632         Bits16       reserved;          /* reserved                     */
633     };
635     struct HeapEntry {
636         IHeap.Handle  heap;
637         UInt16        heapId;
638     };
640     struct TransportEntry {
641         IMessageQTransport.Handle  transport;
642         UInt16             procId;
643     };
645     /*!
646      *  ======== nameSrvPrms ========
647      *  This Params object is used for temporary storage of the
648      *  module wide parameters that are for setting the NameServer instance.
649      */
650     metaonly config NameServer.Params nameSrvPrms;
652     /*!
653      *  Statically registered heaps
654      *
655      *  This configuration parameter allows the static registeration
656      *  of heaps. The index of the array corresponds to the heapId.
657      */
658     metaonly config HeapEntry staticHeaps[];
660     /*!
661      *  Statically registered transports
662      *
663      *  This configuration parameter allows the static registeration
664      *  of transports. The index of the array corresponds to the procId.
665      */
666     metaonly config TransportEntry staticTransports[];
668     /*!
669      *  Allows for the number of dynamically created message queues to grow.
670      */
671     UInt16 grow(Object *obj, Error.Block *eb);
673     struct Instance_State {
674         QueueId         queue;        /* Unique id                     */
675         ISync.Handle    synchronizer; /* completion synchronizer       */
676         List.Object     normalList;   /* Embedded List objects         */
677         List.Object     highList;     /* Embedded List objects         */
678         Ptr             nsKey;        /* unique NameServer key         */
679         SyncSem.Handle  syncSemHandle;/* for use in finalize           */
680         Bool            unblocked;    /* Whether MessageQ is unblocked */
681     };
683     struct Module_State {
684         IMessageQTransport.Handle transports[][2];
685         Handle               queues[];
686         IHeap.Handle         heaps[];
687         IGateProvider.Handle gate;
688         UInt16               numQueues;
689         UInt16               numHeaps;
690         NameServer.Handle    nameServer;
691         Bool                 canFreeQueues;
692         UInt16               seqNum;
693     };