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