Improve MessageQ recovery on DRA7xx QNX
authorvwan@ti.com <vwan@ti.com>
Mon, 24 Aug 2015 16:59:45 +0000 (09:59 -0700)
committerAngela Stegmaier <angelabaker@ti.com>
Mon, 5 Oct 2015 19:28:14 +0000 (14:28 -0500)
Previously, after recovery, an application using MessageQ is expected to
terminate. We are now improving this by having MessageQ_get/put return
MessageQ_E_SHUTDOWN after recovery is performed, upon which the application
can cleanup, and call Ipc_stop and Ipc_start to "restart" IPC. After that the
application can use IPC again.

This commit also adds a Fault test to validate this behavior.

This is to address CQ SDOCM00116175.

Signed-off-by: VW <vwan@ti.com>
Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
17 files changed:
.gitignore
qnx/src/api/Ipc.c
qnx/src/api/MessageQ.c
qnx/src/ipc3x_dev/ti/syslink/build/Qnx/resmgr/syslink_main.c
qnx/src/ipc3x_dev/ti/syslink/inc/_NameServer_daemon.h
qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/MessageQCopy.c
qnx/src/ipc3x_dev/ti/syslink/ti-ipc/ti-ipc.c
qnx/src/ipc3x_dev/ti/syslink/ti-ipc/ti-ipc.h
qnx/src/ipc3x_dev/ti/syslink/utils/hlos/knl/MultiProc.c
qnx/src/ipc3x_dev/ti/syslink/utils/hlos/knl/NameServer_daemon.c
qnx/src/tests/Fault/Fault.c [new file with mode: 0644]
qnx/src/tests/Fault/Fault.use [new file with mode: 0644]
qnx/src/tests/Fault/Makefile [new file with mode: 0644]
qnx/src/tests/Fault/arm/Makefile [new file with mode: 0644]
qnx/src/tests/Fault/arm/o.g.le.v7/Makefile [new file with mode: 0644]
qnx/src/tests/Fault/arm/o.le.v7/Makefile [new file with mode: 0644]
qnx/src/tests/Fault/common.mk [new file with mode: 0644]

index 2046539b8fed12d869f707baad436be90068cbd4..e6efe4870b3c307742e4f61f4f839a3a2c477597 100644 (file)
@@ -78,6 +78,7 @@ packages/ti/srvmgr/omx/OmxSrvMgr.h
 /qnx/src/tests/*/arm/o.g.le.v7/MessageQMulti_g
 /qnx/src/tests/*/arm/o.g.le.v7/NameServerApp_g
 /qnx/src/tests/*/arm/o.g.le.v7/mmrpc_test_g
+/qnx/src/tests/*/arm/o.g.le.v7/Fault_g
 
 /qnx/src/tests/*/arm/o.le.v7/*.o
 /qnx/src/tests/*/arm/o.le.v7/*.map
@@ -88,6 +89,7 @@ packages/ti/srvmgr/omx/OmxSrvMgr.h
 /qnx/src/tests/*/arm/o.le.v7/MessageQMulti
 /qnx/src/tests/*/arm/o.le.v7/NameServerApp
 /qnx/src/tests/*/arm/o.le.v7/mmrpc_test
+/qnx/src/tests/*/arm/o.le.v7/Fault
 
 /qnx/src/ipc3x_dev/sharedmemallocator/resmgr/arm/le.v7/shmemallocator
 /qnx/src/ipc3x_dev/sharedmemallocator/samples/sharedMemAllocator/usr/arm/le.v7/SharedMemoryAllocatorTestApp
index 61989b8af794a3815b4715a5d85221434b7cf825..763a17b3919b42cfb429bd487aede5419ca9dd4a 100644 (file)
 #include <_GateMP.h>
 #include <_GateMP_usr.h>
 #include <_TiIpcFxns.h>
+#include <_IpcLog.h>
 #include <ti/syslink/inc/_GateHWSpinlock.h>
 #include <ti/syslink/inc/_MultiProc.h>
 
 MultiProc_Config _MultiProc_cfg;
 
+/* traces in this file are controlled via _Ipc_verbose */
+Bool _Ipc_verbose = FALSE;
+#define verbose _Ipc_verbose
 
 static void cleanup(int arg);
 
@@ -89,6 +93,7 @@ Int Ipc_start (Void)
         /* turn on tracing */
         if (getenv("IPC_DEBUG")[0] == '1') {
             /* level 1 enables typical user API tracing */
+            _Ipc_verbose = TRUE;
             _MessageQ_verbose = TRUE;
             _MultiProc_verbose = TRUE;
             _NameServer_verbose = TRUE;
@@ -101,6 +106,7 @@ Int Ipc_start (Void)
         else if ((getenv("IPC_DEBUG")[0] == '2') ||
                 (getenv("IPC_DEBUG")[0] == '3')) {
             /* levels 2 and 3 add TiIpcFxns tracing */
+            _Ipc_verbose = TRUE;
             _MessageQ_verbose = TRUE;
             _MultiProc_verbose = TRUE;
             _NameServer_verbose = TRUE;
@@ -147,6 +153,17 @@ Int Ipc_start (Void)
               goto messageqattach_fail;
            }
         }
+
+        /*
+         * Check if MultiProc config is valid and that
+         * MultiProc_getNumProcessors() is non-zero to make sure we are not
+         * in the middle of a recovery.
+         */
+        if (rprocId == 0) {
+            PRINTVERBOSE0("Ipc_start: MultiProc not yet configured\n")
+            status = Ipc_E_FAIL;
+            goto messageqattach_fail;
+        }
     }
     else {
         printf("Ipc_start: NameServer_setup() failed: %d\n", status);
index e512264b40b963a91ce9dd772f1a88df79be0cb4..788a60f97953a079fefdb7896da4b4b24206bd18 100644 (file)
@@ -217,6 +217,8 @@ typedef struct MessageQ_Object_tag {
     /* Unique id */
     int                     ipcFd;
     /* File Descriptors to receive from a message queue. */
+    int                     unblocked;
+    /* Is the queue unblocked and how */
     int                     unblockFdW;
     /* Write this fd to unblock the select() call in MessageQ _get() */
     int                     unblockFdR;
@@ -648,8 +650,10 @@ Int MessageQ_get (MessageQ_Handle handle, MessageQ_Msg * msg ,UInt timeout)
     /* Add one to last fd created: */
     nfds = ((maxfd > obj->unblockFdR) ? maxfd : obj->unblockFdR) + 1;
 
+    *msg = NULL;
+
     retval = select(nfds, &rfds, NULL, NULL, timevalPtr);
-    if (retval)  {
+    if (retval > 0)  {
         if (FD_ISSET(obj->unblockFdR, &rfds))  {
             /*
              * Our event was signalled by MessageQ_unblock().
@@ -659,8 +663,7 @@ Int MessageQ_get (MessageQ_Handle handle, MessageQ_Msg * msg ,UInt timeout)
              * any pending messages in the transport's queue.
              * Thus, we shall not check for nor return any messages.
              */
-            *msg = NULL;
-            status = MessageQ_E_UNBLOCKED;
+            return (obj->unblocked);
         }
         else {
             if (FD_ISSET(obj->ipcFd, &rfds)) {
@@ -668,15 +671,23 @@ Int MessageQ_get (MessageQ_Handle handle, MessageQ_Msg * msg ,UInt timeout)
                 tmpStatus = transportGet(obj->ipcFd, msg);
                 if (tmpStatus < 0) {
                     printf ("MessageQ_get: transportGet failed.\n");
-                    status = MessageQ_E_FAIL;
+                    if (tmpStatus == MessageQ_E_SHUTDOWN) {
+                        status = tmpStatus;
+                        MessageQ_shutdown(handle);
+                    }
+                    else {
+                        status = MessageQ_E_FAIL;
+                    }
                 }
             }
         }
     }
     else if (retval == 0) {
-        *msg = NULL;
         status = MessageQ_E_TIMEOUT;
     }
+    else {
+        status = MessageQ_E_FAIL;
+    }
 
     return (status);
 }
@@ -764,6 +775,20 @@ Void MessageQ_unblock (MessageQ_Handle handle)
     MessageQ_Object * obj   = (MessageQ_Object *) handle;
     char         buf = 'n';
 
+    obj->unblocked = MessageQ_E_UNBLOCKED;
+
+    /* Write to pipe to awaken any threads blocked on this messageQ: */
+    write(obj->unblockFdW, &buf, 1);
+}
+
+/* Unblocks a MessageQ that's been shutdown due to transport failure */
+Void MessageQ_shutdown(MessageQ_Handle handle)
+{
+    MessageQ_Object *obj = (MessageQ_Object *)handle;
+    char         buf = 'n';
+
+    obj->unblocked = MessageQ_E_SHUTDOWN;
+
     /* Write to pipe to awaken any threads blocked on this messageQ: */
     write(obj->unblockFdW, &buf, 1);
 }
@@ -1003,8 +1028,8 @@ static Int transportGet(int fd, MessageQ_Msg * retMsg)
     /* Get message */
     byteCount = read(fd, msg, MESSAGEQ_RPMSG_MAXSIZE);
     if (byteCount < 0) {
+        status = (errno == ESHUTDOWN ? MessageQ_E_SHUTDOWN : MessageQ_E_FAIL);
         printf("read failed: %s (%d)\n", strerror(errno), errno);
-        status = MessageQ_E_FAIL;
         goto exit;
     }
     else {
@@ -1064,9 +1089,9 @@ static Int transportPut(MessageQ_Msg msg, UInt16 dstId, UInt16 dstProcId)
     /* send response message to remote processor */
     err = write(ipcFd, msg, msg->msgSize);
     if (err < 0) {
+        status = (errno == ESHUTDOWN ? MessageQ_E_SHUTDOWN : MessageQ_E_FAIL);
         printf ("transportPut: write failed: %d, %s\n",
                   errno, strerror(errno));
-        status = MessageQ_E_FAIL;
         goto exit;
     }
 
index 376f146e0f712dea7c1ea612c3ae62ddea0b9f80..aa1a1c115392e4fc2e14e440dae6aebf95604ea2 100644 (file)
@@ -67,6 +67,7 @@
 #include <ti/ipc/NameServer.h>
 #include <_MultiProc.h>
 #include <_NameServer.h>
+#include <_NameServer_daemon.h>
 #include <_GateMP_daemon.h>
 #include <OsalSemaphore.h>
 #include <ti/syslink/utils/OsalPrint.h>
@@ -1369,7 +1370,7 @@ int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
             goto tiipcsetup_fail;
 
         /* Set up rpmsg_mq */
-        status = ti_ipc_setup();
+        status = ti_ipc_setup(recover);
         if (status < 0)
             goto tiipcsetup_fail;
 
@@ -1378,15 +1379,26 @@ int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
         if (status < 0)
             goto rpcsetup_fail;
 
-#if defined(IPC_PLATFORM_VAYU)
-        if (gatempEnabled) {
-            Int32 sr0ProcId;
-
+        if (recover) {
+            /* Notify NameServer that recovery is done */
+            status = NameServer_postRecovery();
+            if (status < 0) {
+                fprintf(stderr, "NameServer could not recover\n");
+                NameServer_destroy();
+                goto nameserversetup_fail;
+            }
+        }
+        else {
             /* Set up NameServer for resource manager process */
             status = NameServer_setup();
             if (status < 0) {
                 goto nameserversetup_fail;
             }
+        }
+
+#if defined(IPC_PLATFORM_VAYU)
+        if (gatempEnabled) {
+            Int32 sr0ProcId;
 
             /* Set up GateMP */
             status = GateMP_setup(&sr0ProcId);
@@ -1412,9 +1424,9 @@ int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
 #if defined(IPC_PLATFORM_VAYU)
 gatempsetup_fail:
     NameServer_destroy();
+#endif
 nameserversetup_fail:
     rpmsg_rpc_destroy();
-#endif
 rpcsetup_fail:
     ti_ipc_destroy(recover);
 tiipcsetup_fail:
@@ -1469,10 +1481,22 @@ int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
 #if defined(IPC_PLATFORM_VAYU)
     if (gatempEnabled) {
         GateMP_destroy(TRUE);
+    }
+#endif
 
+    if (recover) {
+        /*
+         * We do not destroy NameServer during recovery, so that all
+         * clients can continue to call its API.
+         *
+         * We will simply notify the module so that it does not
+         * attempt any remote lookups.
+         */
+        NameServer_preRecovery();
+    }
+    else {
         NameServer_destroy();
     }
-#endif
 
     rpmsg_rpc_destroy();
 
index b58baa0aa7d5642e7e23a49ceda756481a468265..7246a2fe5cd0850b78f207e4cd97619e1924d8d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Texas Instruments Incorporated
+ * Copyright (c) 2013-2015, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,14 +47,14 @@ extern "C" {
 #endif
 
 /*!
- * Setup the NameServer module.
+ * Function to prepare the NameServer module for recovery.
  */
-Int NameServer_setup(Void);
+Void NameServer_preRecovery(Void);
 
 /*!
- * Function to destroy the NameServer module.
+ * Function to notify the NameServer module of end of recovery.
  */
-Void NameServer_destroy(Void);
+Int NameServer_postRecovery(Void);
 
 #if defined (__cplusplus)
 }
index f41ec153034f1504f3358c58c9807c203778820e..c9fc272012dd07fa202434b711febc913df6280e 100644 (file)
@@ -359,12 +359,13 @@ MessageQCopy_destroy (Void)
                 MessageQCopy_module->mq[MessageQCopy_NS_PORT] = NULL;
             }
 
-            /* Check if any MessageQ instances have not been deleted so far.
-             * If not, assert.
-             */
+            /* Check if any MessageQ instances have not been deleted so far. */
             for (i = 0 ; i < MessageQCopy_MAXMQS; i++) {
-                GT_assert (curTrace,
-                           (MessageQCopy_module->mq [i] == NULL));
+                /*
+                 * This is possible if recovery is performed and the app does
+                 * not yet know about it, hence has not yet had a chance to
+                 * clean up.
+                 */
                 if (MessageQCopy_module->mq [i] != NULL) {
                     MessageQCopy_delete(&MessageQCopy_module->mq [i]);
                     MessageQCopy_module->mq [i] = NULL;
index b8706034a64289cf5f923ea96b32ab493e8d06fd..2cadae3af887f1b8dd558787341b862320d47c82 100644 (file)
@@ -81,6 +81,9 @@
 
 #define PRIORITY_REALTIME_LOW 29
 
+/* Rate (in us) at which to check if setup is completed during recovery */
+#define RECOVERY_POLL_RATE    100000
+
 #define TIIPC_DEVICE_NAME "/dev/tiipc"
 
 
@@ -837,6 +840,13 @@ _ti_ipc_cb (MessageQCopy_Handle handle, void * data, int len, void * priv,
 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
     ti_ipc_object * obj = NULL;
 
+    if (ti_ipc_state.isSetup == FALSE) {
+        /* If module is not setup (e.g. in recovery), drop the received msg */
+        GT_0trace(curTrace, GT_3CLASS,
+            "_ti_ipc_cb: Module not setup. Dropping incoming msg.");
+        return;
+    }
+
     obj = (ti_ipc_object *) priv;
 
 #if !defined(IPC_BUILD_OPTIMIZE)
@@ -877,6 +887,11 @@ ti_ipc_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
     ti_ipc_ocb_t * ocb = NULL;
     ti_ipc_object * obj = NULL;
 
+    /* Wait for module to be setup during recovery */
+    while (ti_ipc_state.isSetup == FALSE) {
+        usleep(RECOVERY_POLL_RATE);
+    }
+
     /* Allocate the OCB */
     ocb = (ti_ipc_ocb_t *) calloc (1, sizeof (ti_ipc_ocb_t));
     if (ocb == NULL){
@@ -895,6 +910,7 @@ ti_ipc_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
     }
     else if (_ti_ipc_attach(obj) < 0) {
         errno = ENOMEM;
+        Memory_free(NULL, obj, sizeof(ti_ipc_object));
         free(ocb);
         return (NULL);
     }
@@ -1064,14 +1080,29 @@ ti_ipc_ocb_free (IOFUNC_OCB_T * i_ocb)
 
     if (ocb) {
         if (ocb->ipc) {
+            pthread_mutex_lock(&ti_ipc_state.lock);
             obj = ocb->ipc;
             /* TBD: Notification to remote core of endpoint closure? */
             if (obj->mq) {
+                /* Only delete mq if recovery did not do so */
                 MessageQCopy_delete (&obj->mq);
                 obj->mq = NULL;
             }
-            _ti_ipc_detach(ocb->ipc, FALSE);
-            free (obj);
+
+            /*
+             * If recovery happened and connection is no longer valid,
+             * ti_ipc_destroy would have already performed detach. So only
+             * need to detach if it is still valid
+             */
+            if (obj->isValid) {
+                pthread_mutex_unlock(&ti_ipc_state.lock);
+                _ti_ipc_detach(ocb->ipc, FALSE);
+            }
+            else {
+                pthread_mutex_unlock(&ti_ipc_state.lock);
+            }
+
+            Memory_free (NULL, obj, sizeof(ti_ipc_object));
         }
         free (ocb);
     }
@@ -1133,11 +1164,16 @@ ti_ipc_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *i_ocb)
     if ((status = iofunc_read_verify(ctp, msg, i_ocb, &nonblock)) != EOK)
         return (status);
 
+    pthread_mutex_lock(&ti_ipc_state.lock);
+
     if (!obj->isValid) {
-        return EIO;
+        pthread_mutex_unlock(&ti_ipc_state.lock);
+        /* this connection was shutdown due to recovery */
+        return ESHUTDOWN;
     }
 
     if (obj->addr == MessageQCopy_ADDRANY) {
+        pthread_mutex_unlock(&ti_ipc_state.lock);
         return ENOTCONN;
     }
 
@@ -1154,7 +1190,6 @@ ti_ipc_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *i_ocb)
         * race conditions.
         */
         if (ti_ipc_state.eventState [i].bufList != NULL) {
-            pthread_mutex_lock(&ti_ipc_state.lock);
             item = find_nl(i);
             if (dequeue_notify_list_item(item) < 0) {
                 if (nonblock) {
@@ -1169,7 +1204,6 @@ ti_ipc_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *i_ocb)
                         return(_RESMGR_NOREPLY);
                     }
                     retVal = ENOMEM;
-                    pthread_mutex_unlock(&ti_ipc_state.lock);
                 }
             }
             else {
@@ -1180,6 +1214,8 @@ ti_ipc_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *i_ocb)
         }
     }
 
+    pthread_mutex_unlock(&ti_ipc_state.lock);
+
     /*! @retval Number-of-bytes-read Number of bytes read. */
     return retVal;
 }
@@ -1217,29 +1253,38 @@ ti_ipc_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *io_ocb)
         return (status);
     }
 
+    pthread_mutex_lock(&ti_ipc_state.lock);
+
     if (!obj->isValid) {
-        return EIO;
+        pthread_mutex_unlock(&ti_ipc_state.lock);
+        /* this connection was shutdown due to recovery */
+        return ESHUTDOWN;
     }
 
     if (obj->remoteAddr == MessageQCopy_ADDRANY) {
+        pthread_mutex_unlock(&ti_ipc_state.lock);
         return ENOTCONN;
     }
 
     bytes = ((int64_t) msg->i.nbytes) > MessageQCopy_BUFSIZE ?
             MessageQCopy_BUFSIZE : msg->i.nbytes;
     if (bytes < 0) {
+        pthread_mutex_unlock(&ti_ipc_state.lock);
         return EINVAL;
     }
     _IO_SET_WRITE_NBYTES (ctp, bytes);
 
     status = resmgr_msgread(ctp, buf, bytes, sizeof(msg->i));
     if (status != bytes) {
+        pthread_mutex_unlock(&ti_ipc_state.lock);
         return (errno);
     }
 
     status = MessageQCopy_send(obj->procId, MultiProc_self(), obj->remoteAddr,
                                    obj->addr, buf, bytes, TRUE);
 
+    pthread_mutex_unlock(&ti_ipc_state.lock);
+
     if (status < 0) {
         return (EIO);
     }
@@ -1456,7 +1501,7 @@ ti_ipc_devctl(resmgr_context_t *ctp, io_devctl_t *msg, IOFUNC_OCB_T *i_ocb)
     status = 0;
 
     if (!ocb->ipc->isValid) {
-        return EIO;
+        return ESHUTDOWN;
     }
 
     switch (msg->i.dcmd)
@@ -1520,16 +1565,16 @@ ti_ipc_read_unblock(resmgr_context_t *ctp, io_pulse_t *msg, iofunc_ocb_t *i_ocb)
         /* Let the check remain at run-time for handling any run-time
          * race conditions.
          */
+        pthread_mutex_lock(&ti_ipc_state.lock);
         if (ti_ipc_state.eventState [i].bufList != NULL) {
-            pthread_mutex_lock(&ti_ipc_state.lock);
             wr = find_waiting_reader(i, ctp->rcvid);
             if (wr) {
                 put_wr(wr);
                 pthread_mutex_unlock(&ti_ipc_state.lock);
                 return (EINTR);
             }
-            pthread_mutex_unlock(&ti_ipc_state.lock);
         }
+        pthread_mutex_unlock(&ti_ipc_state.lock);
     }
 
     return _RESMGR_NOREPLY;
@@ -1613,8 +1658,15 @@ ti_ipc_notify( resmgr_context_t *ctp, io_notify_t *msg, RESMGR_OCB_T *ocb)
     }
 
     pthread_mutex_lock(&ti_ipc_state.lock);
+    if (!obj->isValid) {
+         /*
+          * connection is no longer valid after recovery.
+          * unblock all select calls
+          */
+         trig |= _NOTIFY_COND_INPUT;
+    }
     /* Let the check remain at run-time. */
-    if (flag == TRUE) {
+    else if (flag == TRUE) {
         /* Let the check remain at run-time for handling any run-time
         * race conditions.
         */
@@ -1714,7 +1766,7 @@ _deinit_device (ti_ipc_dev_t * dev)
  *  @sa     ti_ipc_destroy
  */
 Int
-ti_ipc_setup (Void)
+ti_ipc_setup (bool recover)
 {
     UInt16 i;
     List_Params  listparams;
@@ -1728,56 +1780,57 @@ ti_ipc_setup (Void)
     Error_init(&eb);
 
     List_Params_init (&listparams);
-    ti_ipc_state.gateHandle = (IGateProvider_Handle)
+    if (!recover) {
+        ti_ipc_state.gateHandle = (IGateProvider_Handle)
                      GateSpinlock_create ((GateSpinlock_Handle) NULL, &eb);
 #if !defined(IPC_BUILD_OPTIMIZE)
-    if (ti_ipc_state.gateHandle == NULL) {
-        status = -ENOMEM;
-        GT_setFailureReason (curTrace,
+        if (ti_ipc_state.gateHandle == NULL) {
+            status = -ENOMEM;
+            GT_setFailureReason (curTrace,
                              GT_4CLASS,
                              "_ti_ipc_setup",
                              status,
                              "Failed to create spinlock gate!");
-    }
-    else {
-#endif /* if !defined(IPC_BUILD_OPTIMIZE) */
-        for (i = 0 ; i < MAX_PROCESSES ; i++) {
-            ti_ipc_state.eventState [i].bufList = NULL;
-            ti_ipc_state.eventState [i].ipc = NULL;
-            ti_ipc_state.eventState [i].refCount = 0;
-            ti_ipc_state.eventState [i].head = NULL;
-            ti_ipc_state.eventState [i].tail = NULL;
+            goto exit;
         }
+#endif /* if !defined(IPC_BUILD_OPTIMIZE) */
+    }
 
-        pthread_attr_init(&thread_attr );
-        sched_param.sched_priority = PRIORITY_REALTIME_LOW;
-        pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
-        pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
-        pthread_attr_setschedparam(&thread_attr, &sched_param);
-
-        ti_ipc_state.run = TRUE;
-        if (pthread_create(&ti_ipc_state.nt,
-                           &thread_attr, notifier_thread, NULL) == EOK) {
-            pthread_setname_np(ti_ipc_state.nt, "tiipc-notifier");
-            /* create a /dev/tiipc instance for users to open */
-            if (!ti_ipc_state.dev)
-                ti_ipc_state.dev = _init_device();
-            if (ti_ipc_state.dev == NULL) {
-                Osal_printf("Failed to create tiipc");
-                ti_ipc_state.run = FALSE;
-            }
-            else {
-                ti_ipc_state.isSetup = TRUE;
-            }
+    for (i = 0 ; i < MAX_PROCESSES ; i++) {
+        ti_ipc_state.eventState [i].bufList = NULL;
+        ti_ipc_state.eventState [i].ipc = NULL;
+        ti_ipc_state.eventState [i].refCount = 0;
+        ti_ipc_state.eventState [i].head = NULL;
+        ti_ipc_state.eventState [i].tail = NULL;
+    }
+
+    pthread_attr_init(&thread_attr );
+    sched_param.sched_priority = PRIORITY_REALTIME_LOW;
+    pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
+    pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
+    pthread_attr_setschedparam(&thread_attr, &sched_param);
+
+    ti_ipc_state.run = TRUE;
+    if (pthread_create(&ti_ipc_state.nt,
+                       &thread_attr, notifier_thread, NULL) == EOK) {
+        pthread_setname_np(ti_ipc_state.nt, "tiipc-notifier");
+        /* create a /dev/tiipc instance for users to open */
+        if (!ti_ipc_state.dev)
+            ti_ipc_state.dev = _init_device();
+        if (ti_ipc_state.dev == NULL) {
+            Osal_printf("Failed to create tiipc");
+            ti_ipc_state.run = FALSE;
         }
         else {
-            ti_ipc_state.run = FALSE;
+            ti_ipc_state.isSetup = TRUE;
         }
-        pthread_attr_destroy(&thread_attr);
-#if !defined(IPC_BUILD_OPTIMIZE)
     }
-#endif /* if !defined(IPC_BUILD_OPTIMIZE) */
+    else {
+        ti_ipc_state.run = FALSE;
+    }
+    pthread_attr_destroy(&thread_attr);
 
+exit:
     GT_0trace (curTrace, GT_LEAVE, "ti_ipc_setup");
     return status;
 }
@@ -1800,17 +1853,23 @@ ti_ipc_destroy (bool recover)
 
     GT_0trace (curTrace, GT_ENTER, "_ti_ipc_destroy");
 
-    if (!recover)
+    if (!recover) {
         _deinit_device(ti_ipc_state.dev);
+        ti_ipc_state.dev = NULL;
+    }
+
+    ti_ipc_state.isSetup = FALSE;
 
     for (i = 0 ; i < MAX_PROCESSES ; i++) {
-        obj = NULL;
-        if (ti_ipc_state.eventState [i].ipc != NULL) {
+        pthread_mutex_lock(&ti_ipc_state.lock);
+        obj = ti_ipc_state.eventState[i].ipc;
+        if (obj != NULL) {
             /* This is recovery.  Need to mark mq structures as invalid */
-            obj = ti_ipc_state.eventState[i].ipc;
-            MessageQCopy_delete(&obj->mq);
-            obj->mq = NULL;
             obj->isValid = FALSE;
+            if (obj->mq) {
+                MessageQCopy_delete(&obj->mq);
+                obj->mq = NULL;
+            }
         }
         bufList = ti_ipc_state.eventState [i].bufList;
 
@@ -1819,7 +1878,6 @@ ti_ipc_destroy (bool recover)
         ti_ipc_state.eventState [i].refCount = 0;
         if (bufList != NULL) {
             /* Dequeue waiting readers and reply to them */
-            pthread_mutex_lock(&ti_ipc_state.lock);
             while ((wr = dequeue_waiting_reader(i)) != NULL) {
                 /* Check if rcvid is still valid */
                 if (MsgInfo(wr->rcvid, &info) != -1) {
@@ -1847,6 +1905,9 @@ ti_ipc_destroy (bool recover)
             }
             List_delete (&(bufList));
         }
+        else {
+            pthread_mutex_unlock(&ti_ipc_state.lock);
+        }
     }
 
     /* Free the cached list */
@@ -1854,12 +1915,11 @@ ti_ipc_destroy (bool recover)
     flush_uBuf();
     pthread_mutex_unlock(&ti_ipc_state.lock);
 
-    if (ti_ipc_state.gateHandle != NULL) {
+    if ((!recover) && (ti_ipc_state.gateHandle != NULL)) {
         GateSpinlock_delete ((GateSpinlock_Handle *)
                                        &(ti_ipc_state.gateHandle));
     }
 
-    ti_ipc_state.isSetup = FALSE ;
     ti_ipc_state.run = FALSE;
     // run through and destroy the thread, and all outstanding
     // notify structures
index 85aef53ac783bd974086ca80aaf0b43aa4a22909..9121a003942564d0d0cfde970c7b2285507ab9d7 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  ============================================================================
  *
- *  Copyright (c) 2013, Texas Instruments Incorporated
+ *  Copyright (c) 2013-2015, Texas Instruments Incorporated
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions
@@ -99,7 +99,7 @@ typedef struct WaitingReaders {
 /*!
  *  @brief  Setup function for the ti-ipc module
  */
-int ti_ipc_setup (Void);
+int ti_ipc_setup (bool recover);
 
 /*!
  *  @brief  Destroy function for the ti-ipc module
index 5aa8281c0887b5b21f6a5f64d97b25fac7f9f823..465df4a18d120c25051bf479cb6a8d69534e0f5b 100644 (file)
@@ -98,8 +98,8 @@ typedef struct MultiProc_ModuleObject_tag {
 static
 #endif /* if !defined(IPC_BUILD_DEBUG) */
 MultiProc_ModuleObject MultiProc_state = {
-    .defCfg.numProcessors     = 1u,
-    .defCfg.id                = 0u,
+    .defCfg.numProcessors     = 0u,
+    .defCfg.id                = MultiProc_INVALIDID,
     .id                       = MultiProc_INVALIDID
 };
 
index 3159feea17216b95a0daaff94ddd081cd1520134..3a878ba26877d11ed1b366992c1c144eef1b70ea 100644 (file)
@@ -66,6 +66,7 @@
 /* Internal stuff: */
 #include <_MessageQCopy.h>
 #include <_NameServer.h>
+#include <_NameServer_daemon.h>
 #include <ti/ipc/namesrv/_NameServerRemoteRpmsg.h>
 #include <_IpcLog.h>
 
@@ -278,13 +279,28 @@ static void NameServerRemote_processMessage(NameServerRemote_Msg * msg, UInt16 p
         msg->request = NAMESERVER_RESPONSE;
         msg->reserved = NAMESERVER_MSG_TOKEN;
 
-        /* send response message to remote processor */
-        status = MessageQCopy_send(procId, MultiProc_self(),
-            MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
-            sizeof(NameServerRemote_Msg), TRUE);
-        if (status < 0) {
-            LOG0("NameServer: MessageQCopy_send failed\n")
+        pthread_mutex_lock(&NameServer_module->modGate);
+
+        /*
+         * Check if MessageQCopy object is valid. If not, we received a request
+         * but we are not able to respond to it due to recovery.
+         * We will simply drop the request.
+         */
+        if (NameServer_module->mq == NULL) {
+            LOG0("NameServerRemote_processMessage: MessageQCopy not ready. Request "
+                "dropped.\n")
         }
+        else {
+            /* send response message to remote processor */
+            status = MessageQCopy_send(procId, MultiProc_self(),
+                MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
+                sizeof(NameServerRemote_Msg), TRUE);
+            if (status < 0) {
+                LOG0("NameServer: MessageQCopy_send failed\n")
+            }
+        }
+
+        pthread_mutex_unlock(&NameServer_module->modGate);
     }
     else {
         LOG2("NameServer Reply: instanceName: %s, name: %s",
@@ -838,10 +854,20 @@ Int NameServer_getRemote(NameServer_Handle handle,
            procId, (String)nsMsg.instanceName)
     LOG1("%s...\n", (String)nsMsg.name)
 
+    /*
+     * Check if MessageQCopy object is valid. Technically we don't need it
+     * to send, but it is an indication of whether recovery is in process
+     */
+    if (NameServer_module->mq == NULL) {
+        LOG0("NameServer_getRemote: MessageQCopy not ready\n")
+        status = NameServer_E_NOTFOUND;
+        goto exit;
+    }
+
     /* send message */
     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
-        TRUE);
+            TRUE);
     if (mqcStatus < 0) {
         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
         status = NameServer_E_NOTFOUND;
@@ -1111,6 +1137,42 @@ Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
     return (status);
 }
 
+Void NameServer_preRecovery(Void)
+{
+    Int status;
+
+    pthread_mutex_lock(&NameServer_module->modGate);
+
+    if (NameServer_module->mq != NULL) {
+        status = MessageQCopy_delete(&NameServer_module->mq);
+        if (status < 0) {
+            LOG0("NameServer_preRecovery: Cannot delete MessageQCopy\n");
+        }
+        NameServer_module->mq = NULL;
+    }
+
+    pthread_mutex_unlock(&NameServer_module->modGate);
+}
+
+Int NameServer_postRecovery(Void)
+{
+    Int status = NameServer_S_SUCCESS;
+
+    pthread_mutex_lock(&NameServer_module->modGate);
+
+    /* Create the MessageQCopy for receiving messages from all remote proc */
+    NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
+        NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
+
+    if (NameServer_module->mq == NULL) {
+        status = NameServer_E_FAIL;
+        LOG0("NameServer_postRecovery: failed to create MessageQCopy instance.\n")
+    }
+
+    pthread_mutex_unlock(&NameServer_module->modGate);
+
+    return (status);
+}
 
 #if defined (__cplusplus)
 }
diff --git a/qnx/src/tests/Fault/Fault.c b/qnx/src/tests/Fault/Fault.c
new file mode 100644 (file)
index 0000000..436a570
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* =============================================================================
+ *  @file   Fault.c
+ *
+ *  @brief  Sample application for fault recovery between MPU and Remote Proc
+ *
+ *  ============================================================================
+ */
+
+/* Standard headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* IPC Headers */
+#include <ti/ipc/Std.h>
+#include <ti/ipc/Ipc.h>
+#include <ti/ipc/MessageQ.h>
+
+/* App defines:  Must match on remote proc side: */
+#define HEAPID              0u
+#define SLAVE_MESSAGEQNAME  "SLAVE"
+#define MPU_MESSAGEQNAME    "HOST"
+
+#define PROC_ID_DFLT        1     /* Host is zero, remote cores start at 1 */
+#define NUM_LOOPS_DFLT      100
+
+typedef struct SyncMsg {
+    MessageQ_MsgHeader header;
+    UInt32 numLoops;  /* also used for msgId */
+    UInt32 print;
+    Int32 faultId;
+} SyncMsg ;
+
+Int MessageQApp_execute(UInt32 numLoops, UInt16 procId, UInt32 faultId)
+{
+    Int32                    status = 0;
+    MessageQ_Msg             msg = NULL;
+    MessageQ_Params          msgParams;
+    UInt32                   i;
+    MessageQ_QueueId         queueId = MessageQ_INVALIDMESSAGEQ;
+    MessageQ_Handle          msgqHandle;
+    char                     remoteQueueName[64];
+    UInt32                   msgId;
+
+    printf("Entered MessageQApp_execute\n");
+
+    /* Create the local Message Queue for receiving. */
+    MessageQ_Params_init(&msgParams);
+    msgqHandle = MessageQ_create(MPU_MESSAGEQNAME, &msgParams);
+    if (msgqHandle == NULL) {
+        printf("Error in MessageQ_create\n");
+        goto exit;
+    }
+    else {
+        printf("Local MessageQId: 0x%x\n", MessageQ_getQueueId(msgqHandle));
+    }
+
+    sprintf(remoteQueueName, "%s_%s", SLAVE_MESSAGEQNAME,
+             MultiProc_getName(procId));
+
+    /* Poll until remote side has it's messageQ created before we send: */
+    do {
+        status = MessageQ_open(remoteQueueName, &queueId);
+        sleep (1);
+    } while (status == MessageQ_E_NOTFOUND);
+
+    if (status < 0) {
+        printf("Error in MessageQ_open [%d]\n", status);
+        goto cleanup;
+    }
+    else {
+        printf("Remote queueId  [0x%x]\n", queueId);
+    }
+
+    msg = MessageQ_alloc(HEAPID, sizeof(SyncMsg));
+    if (msg == NULL) {
+        printf("Error in MessageQ_alloc\n");
+        MessageQ_close(&queueId);
+        goto cleanup;
+    }
+
+    /* handshake with remote to set the number of loops */
+    MessageQ_setReplyQueue(msgqHandle, msg);
+    ((SyncMsg *)msg)->numLoops = numLoops;
+    ((SyncMsg *)msg)->print = FALSE;
+    MessageQ_put(queueId, msg);
+    MessageQ_get(msgqHandle, &msg, MessageQ_FOREVER);
+
+    printf("Exchanging %d messages with remote processor %s...\n",
+           numLoops, MultiProc_getName(procId));
+
+    for (i = 1 ; i <= numLoops; i++) {
+        ((SyncMsg *)msg)->numLoops = i;
+        ((SyncMsg *)msg)->faultId = faultId;
+
+        /* Have the remote proc reply to this message queue */
+        MessageQ_setReplyQueue(msgqHandle, msg);
+
+        if (faultId != 0) {
+            printf("About to send fault command, hit ENTER to continue...\n");
+            getchar();
+        }
+
+        status = MessageQ_put(queueId, msg);
+        if (status < 0) {
+            printf("Error in MessageQ_put [%d]\n", status);
+            MessageQ_free(msg);
+            break;
+        }
+
+        status = MessageQ_get(msgqHandle, &msg, MessageQ_FOREVER);
+
+        if (status < 0) {
+            printf("Error in MessageQ_get [%d]\n", status);
+            break;
+        }
+        else {
+            /* validate the returned message */
+            msgId = ((SyncMsg *)msg)->numLoops;
+            if ((msg != NULL) && (msgId != i)) {
+                printf("Data integrity failure!\n"
+                        "    Expected %d\n"
+                        "    Received %d\n",
+                        i, msgId);
+                break;
+            }
+        }
+
+        if (numLoops <= 200) {
+            printf("MessageQ_get #%d Msg = 0x%x\n", i, (UInt)msg);
+        }
+        else if ((i % 1000) == 0) {
+            printf("MessageQ_get #%d Msg = 0x%x\n", i, (UInt)msg);
+        }
+
+        if (faultId == 1) {
+            printf("About to attempt sending data, hit ENTER to continue...\n");
+            getchar();
+            /* Reset fault id for next round */
+            faultId = 0;
+        }
+    }
+
+    printf("Exchanged %d messages with remote processor %s\n",
+        (i-1), MultiProc_getName(procId));
+
+    if (status >= 0) {
+        printf("Sample application successfully completed!\n");
+        MessageQ_free(msg);
+    }
+
+    MessageQ_close(&queueId);
+
+cleanup:
+    /* Clean-up */
+    if (MessageQ_delete(&msgqHandle) < 0) {
+        printf("Error in MessageQ_delete [%d]\n", status);
+    }
+
+exit:
+    printf("Leaving MessageQApp_execute\n\n");
+
+    return (status);
+}
+
+int main (int argc, char ** argv)
+{
+    Int32 status = 0;
+    int opt;
+    UInt32 numLoops = NUM_LOOPS_DFLT;
+    UInt16 procId = PROC_ID_DFLT;
+    UInt32 faultId = 0;
+
+    while ((opt = getopt(argc, argv, "f:")) != -1) {
+        switch (opt) {
+          case 'f':
+            /*
+             * Argument for -f corresponds to remote-side "fault" commands.
+             * Negative commands cause remote fault before remote MessageQ_put.
+             * Positive commands cause remote fault after remote MessageQ_put.
+             */
+            faultId = atoi(optarg);
+            printf("fault %d will be sent in 1st msg\n", faultId);
+            break;
+
+          default:
+            fprintf(stderr, "Unknown arg '%s'\n", optarg);
+            return 1;
+        }
+    }
+
+    /* Parse Args: */
+    switch (argc - optind + 1) {
+        case 1:
+           /* use defaults */
+           break;
+        case 2:
+           numLoops   = atoi(argv[optind]);
+           break;
+        case 3:
+           numLoops   = atoi(argv[optind]);
+           procId     = atoi(argv[optind + 1]);
+           break;
+        default:
+           printf("Usage: %s [<numLoops>] [<ProcId>]\n", argv[0]);
+           printf("\tDefaults: numLoops: %d; ProcId: %d\n",
+                   NUM_LOOPS_DFLT, PROC_ID_DFLT);
+           exit(0);
+    }
+
+    /* IPC initialization */
+    status = Ipc_start();
+
+    if (status < 0) {
+        printf("Error: Ipc_start failed, error=%d\n", status);
+        goto exit;
+    }
+
+    if ((procId == 0) || (procId >= MultiProc_getNumProcessors())) {
+        printf("ProcId (%d) must be nonzero and less than %d\n",
+                procId, MultiProc_getNumProcessors());
+        Ipc_stop();
+        exit(0);
+    }
+    printf("Using numLoops: %d; procId : %d\n", numLoops, procId);
+
+    if (MessageQApp_execute(numLoops, procId, faultId) < 0) {
+        int nAttachAttempts = 1;
+
+        printf("MessageQApp_execute failed, attempting stop/start)...\n");
+        Ipc_stop();
+        while (Ipc_start() != Ipc_S_SUCCESS) {
+            nAttachAttempts++;
+            if ((nAttachAttempts % 1000) == 0) {
+                printf("Ipc_start() failed\n");
+            }
+        }
+        printf("Ipc_start() succeeded (after %d tries)\n", nAttachAttempts);
+
+        /* call without fault this time */
+        MessageQApp_execute(numLoops, procId, 0);
+    }
+
+    Ipc_stop();
+
+exit:
+    return (status);
+}
diff --git a/qnx/src/tests/Fault/Fault.use b/qnx/src/tests/Fault/Fault.use
new file mode 100644 (file)
index 0000000..aa5b7f6
--- /dev/null
@@ -0,0 +1,25 @@
+Fault Test
+
+Syntax:
+  Fault [-f<faultNum>] <num_iterations> [<procId>]
+
+    <faultNum>       can be
+                      1: MMU Fault (data read access)
+                      2: MMU Fault (data write access)
+                      3: MMU Fault (program access)
+                      4: Exception
+                      5: Watchdog timeout
+                     If faultNum is negative, the fault happens before the slave
+                     processor replies to first incoming message. Otherwise,
+                     the fault happens after the slave processor calls
+                     MessageQ_put to reply to the first incoming message.
+
+    <num_iterations> Number of messages to send
+
+    <procId>         Multiproc Id of processor to communicate with. Default
+                     of 1.
+
+Examples:
+  Fault -f 1 10        Initiate an MMU fault via an invalid data read access on
+                       slave core with procId 1, and then exchange 10 msgs with
+                       it after recovery.
diff --git a/qnx/src/tests/Fault/Makefile b/qnx/src/tests/Fault/Makefile
new file mode 100644 (file)
index 0000000..a0bc237
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2015, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+LIST=CPU
+include recurse.mk
diff --git a/qnx/src/tests/Fault/arm/Makefile b/qnx/src/tests/Fault/arm/Makefile
new file mode 100644 (file)
index 0000000..d10016f
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2015, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+LIST=VARIANT
+ifndef QRECURSE
+QRECURSE=recurse.mk
+ifdef QCONFIG
+QRDIR=$(dir $(QCONFIG))
+endif
+endif
+include $(QRDIR)$(QRECURSE)
diff --git a/qnx/src/tests/Fault/arm/o.g.le.v7/Makefile b/qnx/src/tests/Fault/arm/o.g.le.v7/Makefile
new file mode 100644 (file)
index 0000000..3ec7774
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2015, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+include ../../common.mk
+
+$(PROJECT_ROOT)/arm/o.g.le.v7/Fault_g: $(IPC_REPO)/qnx/src/api/arm/a.g.le.v7/libipc_g.a
+$(PROJECT_ROOT)/arm/o.g.le.v7/Fault_g: $(IPC_REPO)/qnx/src/utils/arm/a.g.le.v7/libutils_g.a
+$(PROJECT_ROOT)/arm/o.g.le.v7/Fault_g: $(IPC_REPO)/qnx/src/ipc3x_dev/ti/syslink/build/Qnx/lib/arm/so.le.v7/libipc_clientS.a
+
+# link with ipc static library, dynamic for others
+LIBPREF_ipc_g = -Bstatic
+LIBPOST_ipc_g = -Bdynamic
+LIBPREF_utils_g = -Bstatic
+LIBPOST_utils_g = -Bdynamic
+LIBPREF_ipc_client = -Bstatic
+LIBPOST_ipc_client = -Bdynamic
+
+# add libpath and libs
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/api/arm/a.g.le.v7
+LIBS += ipc_g
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/utils/arm/a.g.le.v7
+LIBS += utils_g
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/ipc3x_dev/ti/syslink/build/Qnx/lib/arm/so.le.v7
+LIBS += ipc_clientS
diff --git a/qnx/src/tests/Fault/arm/o.le.v7/Makefile b/qnx/src/tests/Fault/arm/o.le.v7/Makefile
new file mode 100644 (file)
index 0000000..8811c1c
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2015, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+include ../../common.mk
+
+CCFLAGS += -O3
+
+$(PROJECT_ROOT)/arm/o.le.v7/Fault: $(IPC_REPO)/qnx/src/api/arm/a.le.v7/libipc.a
+$(PROJECT_ROOT)/arm/o.le.v7/Fault: $(IPC_REPO)/qnx/src/utils/arm/a.le.v7/libutils.a
+$(PROJECT_ROOT)/arm/o.le.v7/Fault: $(IPC_REPO)/qnx/src/ipc3x_dev/ti/syslink/build/Qnx/lib/arm/so.le.v7/libipc_clientS.a
+
+# link with ipc static library, dynamic for others
+LIBPREF_ipc = -Bstatic
+LIBPOST_ipc = -Bdynamic
+LIBPREF_utils = -Bstatic
+LIBPOST_utils = -Bdynamic
+LIBPREF_ipc_client = -Bstatic
+LIBPOST_ipc_client = -Bdynamic
+
+# add libpath and libs
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/api/arm/a.le.v7
+LIBS += ipc
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/utils/arm/a.le.v7
+LIBS += utils
+EXTRA_LIBVPATH += $(IPC_REPO)/qnx/src/ipc3x_dev/ti/syslink/build/Qnx/lib/arm/so.le.v7
+LIBS += ipc_clientS
diff --git a/qnx/src/tests/Fault/common.mk b/qnx/src/tests/Fault/common.mk
new file mode 100644 (file)
index 0000000..99655ce
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2015, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+ifndef QCONFIG
+QCONFIG=qconfig.mk
+endif
+include $(QCONFIG)
+
+NAME = Fault
+
+define PINFO
+PINFO DESCRIPTION=IPC QNX FAULT TEST
+endef
+
+INSTALLDIR = bin/tests
+
+# source path
+EXTRA_SRCVPATH += \
+        $(IPC_REPO)/qnx/src/tests/Fault \
+
+EXCLUDE_OBJS =
+
+# include path
+EXTRA_INCVPATH += \
+        $(IPC_REPO)/packages \
+        $(IPC_REPO)/qnx/include
+
+include $(MKFILES_ROOT)/qtargets.mk
+
+LDFLAGS += -M
+
+# Quiet the build output
+include $(IPC_REPO)/qnx/quiet.mk