MessageQ: Merge new IPC 1.25.03 MessageQ features
authorChris Ring <cring@ti.com>
Tue, 20 Aug 2013 18:59:03 +0000 (11:59 -0700)
committerChris Ring <cring@ti.com>
Tue, 20 Aug 2013 18:59:03 +0000 (11:59 -0700)
The IPC 1.25.03 patch introduced two MessageQ-related features:

SDOCM00099783: MessageQ_free needs a hook function
SDOCM00095724: MessageQ_create should allow a queueId to be
specified instaned of finding free slot

These were driven by MCU/TI-RTOS programs, but may be useful for
other use cases.

This commit brings those features into IPC 3.x.

packages/ti/ipc/MessageQ.h
packages/ti/sdo/ipc/MessageQ.c
packages/ti/sdo/ipc/MessageQ.xdc
packages/ti/sdo/ipc/MessageQ.xs
packages/ti/sdo/ipc/nsremote/NameServerMessageQ.c
packages/ti/sdo/ipc/nsremote/NameServerMessageQ.xs

index 9b23f1a0389266b8a69bbd813f284ff619a8f218..7a1becd16954a13b6e4cc144eb90773ac65e05dc 100644 (file)
@@ -410,7 +410,7 @@ typedef UInt16 MessageQ_QueueIndex;
 typedef struct MessageQ_Object *MessageQ_Handle;
 
 /*!
- *  @brief  Structure defining parameters for the MessageQ module.
+ *  @brief  Structure defining parameters for MessageQ_create().
  */
 typedef struct {
     Void *synchronizer;
@@ -424,6 +424,39 @@ typedef struct {
 
 } MessageQ_Params;
 
+/*!
+ *  @brief  Structure defining parameters for MessageQ_create2().
+ *
+ *  MessageQ_Params2 is a superset of MessageQ_Params. It is used
+ *  with MessageQ_create2().
+ */
+typedef struct {
+    Void *synchronizer;
+    /*!< Synchronizer instance used to signal IO completion
+     *
+     *  The synchronizer is used in MessageQ_put() and MessageQ_get().
+     *  The synchronizer signal is called as part of MessageQ_put().
+     *  The synchronizer waits in MessageQ_get() if there are no messages
+     *  present.
+     */
+
+     MessageQ_QueueIndex queueIndex;
+     /*!< Value used to specify the index in the MessageQ array
+      *
+      *  This parameter allows an application to specify a queueIndex to
+      *  be used for a message queue. To use this functionality, the
+      *  MessageQ.numReservedEntries static configuration parameter must be
+      *  set to one more than the highest requested queueIndex. The
+      *  MessageQ.numReservedEntries parameter reserves that number of
+      *  message queue slots starting at 0 and proceeding to
+      *  (MessageQ.numReservedEntries - 1).
+      *
+      *  The default is MessageQ_ANY, which means it is not taken from the
+      *  reserved slots.
+      */
+
+} MessageQ_Params2;
+
 /*!
  *  @brief      Required first field in every message
  */
@@ -454,10 +487,25 @@ typedef MessageQ_MsgHeader *MessageQ_Msg;
 typedef enum {
     MessageQ_NORMALPRI      = 0,    /*!< Normal Priority                  */
     MessageQ_HIGHPRI        = 1,    /*!< High Priority                    */
-    MessageQ_RESERVEDPRI    = 2,    /*!< Reserved Priority                 */
+    MessageQ_RESERVEDPRI    = 2,    /*!< Reserved Priority                */
     MessageQ_URGENTPRI      = 3     /*!< Urgent Priority                  */
 } MessageQ_Priority;
 
+/*!
+ *  @brief      Denotes any queueId is acceptable.
+ *
+ *  This constant is the default for the queueId in the MessageQ_Params2
+ *  structure.
+ */
+#define MessageQ_ANY (Bits16)~(0)
+
+/*!
+ *  @brief      Free hook prototype
+ *
+ *  @param[in]  heapId      heapId of message that was freed
+ *  @param[in]  msgId       msgId of message that was freed
+ */
+typedef Void (*MessageQ_FreeHookFxn)(Bits16 heapId, Bits16 msgId);
 
 /* =============================================================================
  *  MessageQ Module-wide Functions
@@ -471,11 +519,18 @@ typedef enum {
  */
 Void MessageQ_Params_init(MessageQ_Params *params);
 
+/*!
+ *  @brief      Initialize MessageQ_Params2
+ *
+ *  @param[in]  params      Parameters required to create a MessageQ
+ */
+Void MessageQ_Params2_init(MessageQ_Params2 *params);
+
 /*!
  *  @brief      Create a MessageQ instance
  *
  *  The name supplied here does not have to be in persistent memory.  The
- *  maximum length of the string supplied here, including the '\\0' terminator
+ *  maximum length of the string supplied here, including the '\\0' terminator,
  *  is '32' by default.
  *
  *  There are no verifications to ensure that the name supplied in
@@ -489,6 +544,24 @@ Void MessageQ_Params_init(MessageQ_Params *params);
  */
 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
 
+/*!
+ *  @brief      Create a MessageQ instance with the MessageQ_Params2 structure
+ *
+ *  The name supplied here does not have to be in persistent memory.  The
+ *  maximum length of the string supplied here, including the '\\0' terminator,
+ *  is '32' by default.
+ *
+ *  There are no verifications to ensure that the name supplied in
+ *  MessageQ_create2() is unique across all processors. Caution must be exercised
+ *  to ensure that each processor uses a unique name.
+ *
+ *  @param[in]  name        Name of the queue
+ *  @param[in]  params      Initialized MessageQ_Params2
+ *
+ *  @return     MessageQ Handle
+ */
+MessageQ_Handle MessageQ_create2(String name, const MessageQ_Params2 *params);
+
 /*!
  *  @brief      Delete a created MessageQ instance
  *
@@ -523,6 +596,41 @@ Int MessageQ_delete(MessageQ_Handle *handlePtr);
  */
 Int MessageQ_open(String name, MessageQ_QueueId *queueId);
 
+/*!
+ *  @brief      Opens a MessageQ given the queue index and remote processor id
+ *
+ *  This function can be used instead of MessageQ_open() if the queue was created
+ *  with a specified QueueIndex.
+ *
+ *      @code
+ *      #define SERVERQUEUEINDEX  1
+ *      #define SERVERMULTIPROCID 2
+ *
+ *      serverFxn() {
+ *          MessageQ_Params2 params2;
+ *
+ *          MessageQ_Params2_init(&params2);
+ *          params2.queueIndex = SERVERQUEUEINDEX;
+ *          messageQ = MessageQ_create2("server", &params2);
+ *          ...
+ *
+ *      clientFxn() {
+ *          MessageQ_QueueId serverQueue;
+ *          serverQueue = MessageQ_openQueueId(SERVERQUEUEINDEX, SERVERMULTIPROCID);
+ *      @endcode
+ *
+ *  It is up to the application to guarantee that the queue that is being opened
+ *  has already been created.  MessageQ_openQueueId() does not validate that
+ *  the queue has been created (unlike the MessageQ_open() function).
+ *
+ *  @param[in] queueIndex   QueueIndex specified in MessageQ_Params2
+ *  @param[in] remoteProcId Multiproc_Id of where the created queue resides
+ *
+ *  @return     The MessageQ_QueueId associated with the queueIndex
+ *              and remoteProcId
+ */
+MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 remoteProcId);
+
 /*!
  *  @brief      Close the opened handle
  *
@@ -655,6 +763,26 @@ Void MessageQ_setMsgTrace(MessageQ_Msg msg, Bool traceFlag);
  */
 Void MessageQ_staticMsgInit(MessageQ_Msg msg, UInt32 size);
 
+/*!
+ *  @brief      Sets MessageQ's free hook function.
+ *
+ *  This API allows a user to specify a hook function which is called within
+ *  MessageQ_free(). The hook is called after a message is freed back to the
+ *  associated heap. The two parameters to the hook function are the heapId
+ *  and the msgId of the freed message.
+ *
+ *  The function is called within MessageQ_free(), so care must be taken to
+ *  minimize any performance or calling context impact.
+ *
+ *  MessageQ_setFreeHookFxn() is not thread safe. It should only
+ *  be called when no MessageQ_free()'s are happening.
+ *
+ *  To disable the hook function, call MessageQ_setFreeHookFxn() with NULL.
+ *
+ *  @param[in]  freeHookFxn  function to be called within MessageQ_free()
+ */
+Void MessageQ_setFreeHookFxn(MessageQ_FreeHookFxn freeHookFxn);
+
 /* =============================================================================
  *  MessageQ Per-instance Functions
  * =============================================================================
index cbc1a600cd255fce2fe246cb4ff6245406714921..a92456c9deec8aac23c04d6eb80340cfaee6b812 100644 (file)
 
 #ifdef __ti__
     #pragma FUNC_EXT_CALLED(MessageQ_Params_init);
+    #pragma FUNC_EXT_CALLED(MessageQ_Params2_init);
     #pragma FUNC_EXT_CALLED(MessageQ_alloc);
     #pragma FUNC_EXT_CALLED(MessageQ_close);
     #pragma FUNC_EXT_CALLED(MessageQ_count);
     #pragma FUNC_EXT_CALLED(MessageQ_create);
+    #pragma FUNC_EXT_CALLED(MessageQ_create2);
     #pragma FUNC_EXT_CALLED(MessageQ_delete);
     #pragma FUNC_EXT_CALLED(MessageQ_open);
+    #pragma FUNC_EXT_CALLED(MessageQ_openQueueId);
     #pragma FUNC_EXT_CALLED(MessageQ_free);
     #pragma FUNC_EXT_CALLED(MessageQ_get);
     #pragma FUNC_EXT_CALLED(MessageQ_getQueueId);
     #pragma FUNC_EXT_CALLED(MessageQ_put);
     #pragma FUNC_EXT_CALLED(MessageQ_registerHeap);
+    #pragma FUNC_EXT_CALLED(MessageQ_setFreeHookFxn);
     #pragma FUNC_EXT_CALLED(MessageQ_setReplyQueue);
     #pragma FUNC_EXT_CALLED(MessageQ_setMsgTrace);
     #pragma FUNC_EXT_CALLED(MessageQ_staticMsgInit);
@@ -118,6 +122,15 @@ Void MessageQ_Params_init(MessageQ_Params *params)
     params->synchronizer = NULL;
 }
 
+/*
+ *  ======== MessageQ_Params2_init ========
+ */
+Void MessageQ_Params2_init(MessageQ_Params2 *params)
+{
+    params->synchronizer = NULL;
+    params->queueIndex = MessageQ_ANY;
+}
+
 /*
  *  ======== MessageQ_alloc ========
  *  Allocate a message and initial the needed fields (note some
@@ -205,6 +218,26 @@ Int MessageQ_close(MessageQ_QueueId *queueId)
  *  ======== MessageQ_create ========
  */
 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params)
+{
+    MessageQ_Handle handle;
+    MessageQ_Params2 params2;
+
+    MessageQ_Params2_init(&params2);
+
+    /* Use the MessageQ_Params fields if not NULL */
+    if (params != NULL) {
+        params2.synchronizer = params->synchronizer;
+    }
+
+    handle = MessageQ_create2(name, &params2);
+
+    return ((MessageQ_Handle)handle);
+}
+
+/*
+ *  ======== MessageQ_create2 ========
+ */
+MessageQ_Handle MessageQ_create2(String name, const MessageQ_Params2 *params)
 {
     ti_sdo_ipc_MessageQ_Handle handle;
     ti_sdo_ipc_MessageQ_Params prms;
@@ -216,6 +249,7 @@ MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params)
         ti_sdo_ipc_MessageQ_Params_init(&prms);
 
         prms.synchronizer = params->synchronizer;
+        prms.queueIndex = params->queueIndex;
 
         handle = ti_sdo_ipc_MessageQ_create(name, &prms, &eb);
     }
@@ -246,6 +280,8 @@ Int MessageQ_delete(MessageQ_Handle *handlePtr)
 Int MessageQ_free(MessageQ_Msg msg)
 {
     IHeap_Handle heap;
+    Bits16 msgId;
+    Bits16 heapId;
 
     /* make sure msg is not NULL */
     Assert_isTrue((msg != NULL), ti_sdo_ipc_MessageQ_A_invalidMsg);
@@ -269,7 +305,12 @@ Int MessageQ_free(MessageQ_Msg msg)
     heap = MessageQ_module->heaps[msg->heapId];
 
     if (heap != NULL) {
+        msgId = MessageQ_getMsgId(msg);
+        heapId = msg->heapId;
         Memory_free(heap, msg, msg->msgSize);
+        if (MessageQ_module->freeHookFxn != NULL) {
+            MessageQ_module->freeHookFxn(heapId, msgId);
+        }
     }
     else {
         return (MessageQ_E_FAIL);
@@ -363,6 +404,18 @@ Int MessageQ_open(String name, MessageQ_QueueId *queueId)
     }
 }
 
+/*
+ *  ======== MessageQ_openQueueId ========
+ */
+MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 remoteProcId)
+{
+    MessageQ_QueueId queueId;
+
+    queueId = ((MessageQ_QueueId)(remoteProcId) << 16) | queueIndex;
+
+    return (queueId);
+}
+
 /*
  *  ======== MessageQ_put ========
  */
@@ -508,6 +561,14 @@ Int MessageQ_registerHeap(Ptr heap, UInt16 heapId)
     return (status);
 }
 
+/*
+ *  ======== MessageQ_setFreeHookFxn ========
+ */
+Void MessageQ_setFreeHookFxn(MessageQ_FreeHookFxn freeHookFxn)
+{
+    MessageQ_module->freeHookFxn = freeHookFxn;
+}
+
 /*
  *  ======== MessageQ_setMsgTrace ========
  */
@@ -703,15 +764,31 @@ Int ti_sdo_ipc_MessageQ_Instance_init(ti_sdo_ipc_MessageQ_Object *obj, String na
     /* lock */
     key = IGateProvider_enter(MessageQ_module->gate);
 
-    start = ti_sdo_ipc_MessageQ_Object_count();
-    count = MessageQ_module->numQueues;
+    if (params->queueIndex != MessageQ_ANY) {
+        queueIndex = params->queueIndex;
+
+        if ((queueIndex >= ti_sdo_ipc_MessageQ_numReservedEntries) ||
+            (MessageQ_module->queues[queueIndex] != NULL)) {
+            IGateProvider_leave(MessageQ_module->gate, key);
+            Error_raise(eb, ti_sdo_ipc_MessageQ_E_indexNotAvailable,
+                queueIndex, 0);
+            return (5);
+        }
+        MessageQ_module->queues[queueIndex] = obj;
+        found = TRUE;
+    }
+    else {
+
+        start = ti_sdo_ipc_MessageQ_numReservedEntries;
+        count = MessageQ_module->numQueues;
 
-    /* Search the dynamic array for any holes */
-    for (i = start; (i < count) && (found == FALSE); i++) {
-        if (MessageQ_module->queues[i] == NULL) {
-            MessageQ_module->queues[i] = obj;
-            queueIndex = i;
-            found = TRUE;
+        /* Search the dynamic array for any holes */
+        for (i = start; (i < count) && (found == FALSE); i++) {
+            if (MessageQ_module->queues[i] == NULL) {
+                MessageQ_module->queues[i] = obj;
+                queueIndex = i;
+                found = TRUE;
+            }
         }
     }
 
@@ -800,6 +877,11 @@ Void ti_sdo_ipc_MessageQ_Instance_finalize(
     MessageQ_QueueIndex index = (MessageQ_QueueIndex)(obj->queue);
     List_Handle listHandle;
 
+    /* Requested queueId was not available. Nothing was done in the init */
+    if (status == 5) {
+        return;
+    }
+
     if (obj->syncSemHandle != NULL) {
         SyncSem_delete(&obj->syncSemHandle);
     }
index 0b8e105844067fcc4b8de4dd18dd8d35d23ffece..d822f7bb797a4fde0f687f4581d9d1244ce09a16 100644 (file)
@@ -196,6 +196,7 @@ module MessageQ
         String               heaps[];
         String               gate;
         UInt16               nextSeqNum;
+        String               freeHookFxn[];
     }
 
     /*!
@@ -334,6 +335,15 @@ module MessageQ
         msg: "LM_get: Message 0x%x (seqNum = %d, srcProc = %d) was received by queue 0x%x"
     };
 
+    /*!
+     *  ======== FreeHookFxn ========
+     *  Function prototype for the MessageQ_free callback
+     *
+     *  @param(Bits16)  heapId of message that was freed
+     *  @param(Bits16)  msgId of message that was freed
+     */
+    typedef Void (*FreeHookFxn)(Bits16, Bits16);
+
     /*! MessageQ ID */
     typedef UInt32 QueueId;
 
@@ -352,6 +362,15 @@ module MessageQ
     const UInt RESERVEDPRI = 2;
     const UInt URGENTPRI   = 3;
 
+    /*!
+     *  Denotes any queueId is acceptable
+     *
+     *  This constant is the default for the {@link #queueId} parameter.
+     *  This value must match ti/ipc/MessageQ.h but is needed to initialize
+     *  queueId.
+     */
+    const Bits16 ANY = ~(0);
+
     /*!
      *  Assert raised when calling API with wrong handle
      *
@@ -451,6 +470,13 @@ module MessageQ
         msg: "E_nameFailed: '%s' name failed to be added to NameServer"
     };
 
+    /*!
+     *  Error raised if the requested queueIndex is not available
+     */
+    config Error.Id E_indexNotAvailable  = {
+        msg: "E_indexNotAvailable: queueIndex %d not available"
+    };
+
     /*!
      *  Trace setting
      *
@@ -475,6 +501,20 @@ module MessageQ
      */
     config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
 
+    /*!
+     *  Number of reserved MessageQ indexes
+     *
+     *  An application can request the first N message queue indexes be
+     *  reserved to be used by MessageQ_create2. MessageQ_create will
+     *  not use these slots. The application can use any index less than
+     *  the value of numReservedEntries for the queueIndex field in the
+     *  MessageQ_Params2 structure.
+     *
+     *  numReservedEntries must be equal or less than
+     *  {@link #maxRuntimeEntries}.
+     */
+    config UInt numReservedEntries = 0;
+
     /*!
      *  Gate used to make the name table thread safe
      *
@@ -502,6 +542,12 @@ module MessageQ
      */
     metaonly config String tableSection = null;
 
+    /*!
+     *  ======== freeHookFxn ========
+     *  Free function in MessageQ_free after message was freed back to the heap
+     */
+    config FreeHookFxn freeHookFxn = null;
+
     /*!
      *  ======== registerHeapMeta ========
      *  Statically register a heap with MessageQ
@@ -563,6 +609,20 @@ instance:
      */
     config ISync.Handle synchronizer = null;
 
+    /*!
+     *  Requested MessageQ_QueueIndex
+     *
+     *  This parameter allows an application to specify the queueIndex to
+     *  be used for a message queue. To use this functionality, the
+     *  MessageQ.numReservedEntries static configuration parameter must be set to
+     *  a specific value.
+     *
+     *  The default is {@link #ANY}. This means do that you are not asking for
+     *  an explicit index. MessageQ will find the first available one which is
+     *  equal or greater than MessageQ.numReservedEntries.
+     */
+    config UInt16 queueIndex = ANY;
+
     /*! @_nodoc
      *  ======== create ========
      *  Create a message queue
@@ -688,6 +748,7 @@ internal:
         UInt16               numQueues;
         UInt16               numHeaps;
         NameServer.Handle    nameServer;
+        FreeHookFxn          freeHookFxn;
         Bool                 canFreeQueues;
         UInt16               seqNum;
     };
index 2f1854a05bedd8f7ecf633fa033f7f2d51e12bd8..6e760bd070e85d2667c2259e55851df3df97ff58 100644 (file)
@@ -119,13 +119,20 @@ function module$static$init(mod, params)
 
     /*
      *  If no growth allowed, pre-allocate the max length
+     *  Also pre-allocate if numReservedEntries is not zero.
+     *  maxRuntimeEntries < numReservedEntries is caught in validate.
      */
     mod.numQueues = this.$instances.length;
     if (params.maxRuntimeEntries != NameServer.ALLOWGROWTH) {
         mod.numQueues += params.maxRuntimeEntries;
     }
+    else if (params.numReservedEntries != 0){
+        mod.numQueues += params.numReservedEntries;
+    }
+
     mod.queues.length = mod.numQueues;
     mod.canFreeQueues = false;
+    mod.freeHookFxn   = params.freeHookFxn;
 
     if (params.nameTableGate == null) {
          mod.gate = null;
@@ -484,4 +491,20 @@ function viewInitModule(view, mod)
      * that will be used.
      */
     view.nextSeqNum = mod.seqNum;
+
+    /* Display the freeHookFxn if there is one. */
+    if (Number(mod.freeHookFxn) != 0 ) {
+        view.freeHookFxn = Program.lookupFuncName(Number(mod.freeHookFxn));
+    }
+}
+
+function module$validate()
+{
+    if ((MessageQ.maxRuntimeEntries != NameServer.ALLOWGROWTH) &&
+        (MessageQ.maxRuntimeEntries < MessageQ.numReservedEntries)) {
+        MessageQ.$logFatal(
+            "If MessageQ.maxRuntimeEntries is not NameServer.ALLOWGROWTH, " +
+            "it cannot be less than MessageQ.numReservedEntries.",
+            MessageQ);
+    }
 }
index 156310be09419ece0053d20f0625eba6b1a90d2d..b4007658110dc2e7ab932736a7d75be08bc27179 100644 (file)
@@ -63,6 +63,8 @@
                         (xdc_target__bitsPerChar / 8))
 #define NAMEARRAYSZIE   (((MAXNAMEINCHAR - 1) / sizeof(Bits32)) + 1)
 
+#define MESSAGEQ_INDEX 0
+
 /* message sent to remote procId */
 typedef struct NameServerMsg {
     MessageQ_MsgHeader header;  /* message header                   */
@@ -117,7 +119,7 @@ Void NameServerMessageQ_Instance_finalize(NameServerMessageQ_Object *obj)
  */
 Int NameServerMessageQ_Module_startup(Int phase)
 {
-    MessageQ_Params  messageQParams;
+    MessageQ_Params2  messageQParams;
 
     /* Ensure MessageQ and SyncSwi Module_startup() have completed */
     if ((ti_sdo_ipc_MessageQ_Module_startupDone() == FALSE) ||
@@ -126,10 +128,11 @@ Int NameServerMessageQ_Module_startup(Int phase)
     }
 
     /* Create the message queue for NameServer using SyncSwi */
-    MessageQ_Params_init(&messageQParams);
+    MessageQ_Params2_init(&messageQParams);
     messageQParams.synchronizer = NameServerMessageQ_module->syncSwiHandle;
+    messageQParams.queueIndex = MESSAGEQ_INDEX;
     NameServerMessageQ_module->msgHandle =
-        (ti_sdo_ipc_MessageQ_Handle)MessageQ_create(NULL, &messageQParams);
+        (ti_sdo_ipc_MessageQ_Handle)MessageQ_create2(NULL, &messageQParams);
 
     /* assert msgHandle is not null */
     Assert_isTrue(NameServerMessageQ_module->msgHandle != NULL,
@@ -137,7 +140,7 @@ Int NameServerMessageQ_Module_startup(Int phase)
 
     /* assert this is the first MessageQ created */
     Assert_isTrue((MessageQ_getQueueId((MessageQ_Handle)
-        NameServerMessageQ_module->msgHandle) & 0xffff) == 0,
+        NameServerMessageQ_module->msgHandle) & 0xffff) == MESSAGEQ_INDEX,
         NameServerMessageQ_A_reservedMsgQueueId);
 
     return (Startup_DONE);
@@ -252,7 +255,7 @@ Int NameServerMessageQ_get(NameServerMessageQ_Object *obj,
     strncpy((Char *)msg->name, name, len);
 
     /* determine the queueId based upon the processor */
-    queueId = (UInt32)obj->remoteProcId << 16;
+    queueId = MessageQ_openQueueId(MESSAGEQ_INDEX, obj->remoteProcId);
 
     /* set the reply procId */
     MessageQ_setReplyQueue(
index f05e66a1955d2752da4babbc2cbc930fd8e62f56..0af0896415f96b8b15b189fc5bd74fa318bcb43d 100644 (file)
@@ -41,6 +41,7 @@ var Clock = null;
 var Ipc = null;
 var SyncSwi = null;
 var GateMutex = null;
+var MessageQ = null;
 
 /*
  *  ======== module$use ========
@@ -55,6 +56,7 @@ function module$use()
     Ipc             = xdc.useModule("ti.sdo.ipc.Ipc");
     SyncSwi         = xdc.useModule("ti.sysbios.syncs.SyncSwi");
     GateMutex       = xdc.useModule("ti.sysbios.gates.GateMutex");
+    MessageQ        = xdc.useModule("ti.sdo.ipc.MessageQ");
 }
 
 /*
@@ -91,3 +93,14 @@ function module$static$init(mod, params)
     /* create GateMutex */
     mod.gateMutex = GateMutex.create();
 }
+
+function module$validate()
+{
+    if (MessageQ.numReservedEntries == 0) {
+        NameServerMessageQ.$logFatal(
+            "NameServerMessageQ is using MessageQ_create2 and requesting " +
+            "queueIndex 0. However MessageQ.numReservedEntries is zero. " +
+            "MessageQ.numReservedEntries must be increased to at least 1",
+            NameServerMessageQ);
+    }
+}