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 }
186 /*!
187 * ======== MessagesView ========
188 * @_nodoc
189 */
190 metaonly struct MessagesView {
191 Int seqNum;
192 Int msgSize;
193 String priority;
194 String srcProc;
195 String replyProc;
196 String replyId;
197 Int msgId;
198 String heap;
199 Bool traceEnabled;
200 Int version;
201 }
203 /*!
204 * ======== ModuleView ========
205 * @_nodoc
206 */
207 metaonly struct ModuleView {
208 String heaps[];
209 String gate;
210 UInt16 nextSeqNum;
211 String freeHookFxn[];
212 }
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 });
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
350 /*!
351 * ======== FreeHookFxn ========
352 * Function prototype for the MessageQ_free callback
353 *
354 * @param(Bits16) heapId of message that was freed
355 * @param(Bits16) msgId of message that was freed
356 */
357 typedef Void (*FreeHookFxn)(Bits16, Bits16);
359 /*!
360 * ======== PutHookFxn ========
361 * Function prototype for the MessageQ_put callback
362 *
363 * @param(Bits32) queueId of the destination message queue
364 * @param(Ptr) pointer to a message header structure
365 */
366 typedef Void (*PutHookFxn)(Bits32, Ptr);
368 /*! MessageQ ID */
369 typedef UInt32 QueueId;
371 /*!
372 * ======== SetupTransportProxy ========
373 * MessageQ transport setup proxy
374 */
375 proxy SetupTransportProxy inherits ti.sdo.ipc.interfaces.ITransportSetup;
377 /*!
378 * Message priority values. These must match the values defined in
379 * ti/ipc/MessageQ.h but are needed here for ROV.
380 */
381 const UInt NORMALPRI = 0;
382 const UInt HIGHPRI = 1;
383 const UInt RESERVEDPRI = 2;
384 const UInt URGENTPRI = 3;
386 /*!
387 * Denotes any queueId is acceptable
388 *
389 * This constant is the default for the {@link #queueId} parameter.
390 * This value must match ti/ipc/MessageQ.h but is needed to initialize
391 * queueId.
392 */
393 const Bits16 ANY = ~(0);
395 /*!
396 * Assert raised when calling API with wrong handle
397 *
398 * Some APIs can only be called with an opened handle (e.g.
399 * {@link #close}. Some can only be called with a created handle
400 * (e.g. {@link #get}).
401 */
402 config Assert.Id A_invalidContext = {
403 msg: "A_invalidContext: Cannot call with an open/create handle"
404 };
406 /*!
407 * Assert raised when attempting to free a static message
408 */
409 config Assert.Id A_cannotFreeStaticMsg = {
410 msg: "A_cannotFreeStaticMsg: Cannot call MessageQ_free with static msg"
411 };
413 /*!
414 * Assert raised when an invalid message is supplied
415 */
416 config Assert.Id A_invalidMsg = {
417 msg: "A_invalidMsg: Invalid message"
418 };
420 /*!
421 * Assert raised when an invalid queueId is supplied
422 */
423 config Assert.Id A_invalidQueueId = {
424 msg: "A_invalidQueueId: Invalid queueId is used"
425 };
427 /*!
428 * Assert raised when using an invalid heapId
429 */
430 config Assert.Id A_heapIdInvalid = {
431 msg: "A_heapIdInvalid: heapId is invalid"
432 };
434 /*!
435 * Assert raised when using an invalid procId
436 */
437 config Assert.Id A_procIdInvalid = {
438 msg: "A_procIdInvalid: procId is invalid"
439 };
441 /*!
442 * Assert raised for an invalid MessageQ object
443 */
444 config Assert.Id A_invalidObj = {
445 msg: "A_invalidObj: an invalid obj is used"
446 };
448 /*!
449 * Assert raised for an invalid parameter
450 */
451 config Assert.Id A_invalidParam = {
452 msg: "A_invalidParam: an invalid parameter was passed in"
453 };
455 /*!
456 * Assert raised when attempting to send a message to a core
457 * where a transport has not been registered.
458 */
459 config Assert.Id A_unregisteredTransport = {
460 msg: "A_unregisteredTransport: transport is not registered"
461 };
463 /*!
464 * Assert raised when attempting to unblock a remote MessageQ or one that
465 * has been configured with a non-blocking synchronizer
466 */
467 config Assert.Id A_invalidUnblock = {
468 msg: "A_invalidUnblock: Trying to unblock a remote MessageQ or a queue with non-blocking synchronizer"
469 };
471 /*!
472 * Error raised if all the message queue objects are taken
473 */
474 config Error.Id E_maxReached = {
475 msg: "E_maxReached: All objects in use. MessageQ.maxRuntimeEntries is %d"
476 };
478 /*!
479 * Error raised when heapId has not been registered
480 */
481 config Error.Id E_unregisterHeapId = {
482 msg: "E_unregisterHeapId: Heap id %d not registered"
483 };
485 /*!
486 * Error raised in a create call when a name fails to be added
487 * to the NameServer table. This can be because the name already
488 * exists, the table has reached its max length, or out of memory.
489 */
490 config Error.Id E_nameFailed = {
491 msg: "E_nameFailed: '%s' name failed to be added to NameServer"
492 };
494 /*!
495 * Error raised if the requested queueIndex is not available
496 */
497 config Error.Id E_indexNotAvailable = {
498 msg: "E_indexNotAvailable: queueIndex %d not available"
499 };
501 /*!
502 * Trace setting
503 *
504 * This flag allows the configuration of the default module trace
505 * settings.
506 */
507 config Bool traceFlag = false;
509 /*!
510 * Number of heapIds in the system
511 *
512 * This allows MessageQ to pre-allocate the heaps table.
513 * The heaps table is used when registering heaps.
514 *
515 * There is no default heap, so unless the system is only using
516 * {@link #staticMsgInit}, the application must register a heap.
517 */
518 config UInt16 numHeaps = 8;
520 /*!
521 * Maximum number of MessageQs that can be dynamically created
522 */
523 config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
525 /*!
526 * Number of reserved MessageQ indexes
527 *
528 * An application can request the first N message queue indexes be
529 * reserved to be used by MessageQ_create2. MessageQ_create will
530 * not use these slots. The application can use any index less than
531 * the value of numReservedEntries for the queueIndex field in the
532 * MessageQ_Params2 structure.
533 *
534 * numReservedEntries must be equal or less than
535 * {@link #maxRuntimeEntries}.
536 */
537 config UInt numReservedEntries = 0;
539 /*!
540 * Gate used to make the name table thread safe
541 *
542 * This gate is used when accessing the name table during
543 * a {@link #create}, {@link #delete}, and {@link #open}.
544 *
545 * This gate is also used to protect MessageQ when growing
546 * internal tables in the {@link #create}.
547 *
548 * The table is in local memory, not shared memory. So a
549 * single processor gate will work.
550 *
551 * The default will be {@link xdc.runtime.knl.GateThread}
552 * instance.
553 */
554 config IGateProvider.Handle nameTableGate = null;
556 /*!
557 * Maximum length for Message queue names
558 */
559 config UInt maxNameLen = 32;
561 /*!
562 * Section name is used to place the names table
563 */
564 metaonly config String tableSection = null;
566 /*!
567 * ======== freeHookFxn ========
568 * Free function in MessageQ_free after message was freed back to the heap
569 */
570 config FreeHookFxn freeHookFxn = null;
572 /*!
573 * ======== putHookFxn ========
574 * Put function hook
575 */
576 config PutHookFxn putHookFxn = null;
578 /*!
579 * ======== registerHeapMeta ========
580 * Statically register a heap with MessageQ
581 *
582 * Build error if heapId is in use.
583 *
584 * @param(heap) Heap to register
585 * @param(heapId) heapId associated with the heap
586 */
587 metaonly Void registerHeapMeta(IHeap.Handle heap, UInt16 heapId);
589 /*!
590 * ======== registerTransportMeta ========
591 * Statically register a transport with MessageQ
592 *
593 * Build error if remote processor already has a transport
594 * registered.
595 *
596 * @param(transport) transport to register
597 * @param(procId) procId that transport communicaties with
598 * @param(priority) priority of transport
599 */
600 metaonly Void registerTransportMeta(IMessageQTransport.Handle transport,
601 UInt16 procId, UInt priority);
603 /*!
604 * ======== registerTransport ========
605 * Register a transport with MessageQ
606 *
607 * This API is called by the transport when it is created.
608 *
609 * @param(transport) transport to register
610 * @param(procId) MultiProc id that transport communicates with
611 * @param(priority) priority of transport
612 *
613 * @b(returns) Whether the register was successful.
614 */
615 Bool registerTransport(IMessageQTransport.Handle transport, UInt16 procId,
616 UInt priority);
618 /*!
619 * ======== unregisterTransport ========
620 * Unregister a transport with MessageQ
621 *
622 * @param(procId) unregister transport that communicates with
623 * this remote processor
624 * @param(priority) priority of transport
625 */
626 Void unregisterTransport(UInt16 procId, UInt priority);
628 instance:
630 /*!
631 * ISync handle used to signal IO completion
632 *
633 * The ISync instance is used in the {@link #get} and {@link #put}.
634 * The {@link xdc.runtime.knl.ISync#signal} is called as part
635 * of the {@link #put} call. The {@link xdc.runtime.knl.ISync#wait} is
636 * called in the {@link #get} if there are no messages present.
637 */
638 config ISync.Handle synchronizer = null;
640 /*!
641 * Requested MessageQ_QueueIndex
642 *
643 * This parameter allows an application to specify the queueIndex to
644 * be used for a message queue. To use this functionality, the
645 * MessageQ.numReservedEntries static configuration parameter must be
646 * set to a specific value.
647 *
648 * The default is {@link #ANY}. This means do that you are not asking for
649 * an explicit index. MessageQ will find the first available one which is
650 * equal or greater than MessageQ.numReservedEntries.
651 */
652 config UInt16 queueIndex = ANY;
654 /*! @_nodoc
655 * ======== create ========
656 * Create a message queue
657 *
658 * @param(name) Name of the message queue.
659 */
660 create(String name);
662 internal:
663 /*
664 * The following describes the usage of the flag field
665 * ---------------------------------
666 * |V V V|T| reserved |t t t|P P|
667 * ---------------------------------
668 * F E D C B A 9 8 7 6 5 4 3 2 1 0
669 *
670 * [15:13] V = version
671 * [12] T = trace flag
672 * [11:5] reserved
673 * [4:2] t = transport Id, zero = default
674 * [1:0] P = priority
675 */
677 /*! Mask to extract version setting */
678 const UInt VERSIONMASK = 0xE000;
680 /*! Version setting */
681 const UInt HEADERVERSION = 0x2000;
683 /*! Mask to extract Trace setting */
684 const UInt TRACEMASK = 0x1000;
686 /*! Shift for Trace setting */
687 const UInt TRACESHIFT = 12;
689 /*!
690 * Mask to extract priority setting.
691 * This is needed here for ROV but must match
692 * the value defined in ti/ipc/MessageQ.h
693 */
694 const UInt PRIORITYMASK = 0x3;
696 /*! Mask to extract priority setting */
697 const UInt TRANSPORTPRIORITYMASK = 0x1;
699 /*! return code for Instance_init */
700 const Int PROXY_FAILURE = 1;
702 /*
703 * Used to denote a message that was initialized
704 * with the MessageQ_staticMsgInit function.
705 */
706 const UInt16 STATICMSG = 0xFFFF;
708 /*! Required first field in every message */
709 @Opaque struct MsgHeader {
710 Bits32 reserved0; /* reserved for List.elem->next */
711 Bits32 reserved1; /* reserved for List.elem->prev */
712 Bits32 msgSize; /* message size */
713 Bits16 flags; /* bitmask of different flags */
714 Bits16 msgId; /* message id */
715 Bits16 dstId; /* destination queue id */
716 Bits16 dstProc; /* destination processor id */
717 Bits16 replyId; /* reply queue id */
718 Bits16 replyProc; /* reply processor id */
719 Bits16 srcProc; /* proc who initialized the msg */
720 Bits16 heapId; /* heap id */
721 Bits16 seqNum; /* sequence number */
722 Bits16 reserved; /* reserved */
723 };
725 struct HeapEntry {
726 IHeap.Handle heap;
727 UInt16 heapId;
728 };
730 struct TransportEntry {
731 IMessageQTransport.Handle transport;
732 UInt16 procId;
733 };
735 enum TransportType {
736 TransportType_IMessageQTransport,
737 TransportType_INetworkTransport,
738 TransportType_Invalid
739 };
741 struct RegisteredTransport {
742 ITransport.Handle transport;
743 TransportType type;
744 };
746 /*!
747 * ======== nameSrvPrms ========
748 * This Params object is used for temporary storage of the
749 * module wide parameters that are for setting the NameServer instance.
750 */
751 metaonly config NameServer.Params nameSrvPrms;
753 /*!
754 * Statically registered heaps
755 *
756 * This configuration parameter allows the static registeration
757 * of heaps. The index of the array corresponds to the heapId.
758 */
759 metaonly config HeapEntry staticHeaps[];
761 /*!
762 * Statically registered transports
763 *
764 * This configuration parameter allows the static registeration
765 * of transports. The index of the array corresponds to the procId.
766 */
767 metaonly config TransportEntry staticTransports[];
769 /*!
770 * Allows for the number of dynamically created message queues to grow.
771 */
772 UInt16 grow(Object *obj, Error.Block *eb);
774 struct Instance_State {
775 QueueId queue; /* Unique id */
776 ISync.Handle synchronizer; /* completion synchronizer */
777 List.Object normalList; /* Embedded List objects */
778 List.Object highList; /* Embedded List objects */
779 Ptr nsKey; /* unique NameServer key */
780 SyncSem.Handle syncSemHandle;/* for use in finalize */
781 Bool unblocked; /* Whether MessageQ is unblocked */
782 };
784 struct Module_State {
785 IMessageQTransport.Handle transports[length][2];
786 Handle queues[];
787 IHeap.Handle heaps[];
788 IGateProvider.Handle gate;
789 UInt16 numQueues;
790 UInt16 numHeaps;
791 NameServer.Handle nameServer;
792 FreeHookFxn freeHookFxn;
793 PutHookFxn putHookFxn;
794 Bool canFreeQueues;
795 UInt16 seqNum;
796 RegisteredTransport regTrans[8];
797 };
798 }