Fix Linux GateMP bug by introducing new GateMP_attach(procId) API 3.36.01.10_eng 3.36.01.11
authorRobert Tivy <rtivy@ti.com>
Wed, 20 May 2015 01:17:21 +0000 (18:17 -0700)
committerRobert Tivy <rtivy@ti.com>
Wed, 20 May 2015 23:58:29 +0000 (16:58 -0700)
Previous to the introduction of Linux Ipc_attach() and NameServer_attach(),
LAD would effectively "attach" to GateMP via NameServer_setup() and
GateMP_setup(), all before opening the command FIFO and accepting commands
from clients.  This worked because NameServer_setup() had internal code
that would perform the "attach" functionality, allowing GateMP_setup() to
proceed.

Now that NameServer_attach() has been introduced, NameServer_setup() no
longer performs the "attach" functionality.  But Ipc_start() now needs to
call Ipc_attach() which, in turn, calls NameServer_attach(), but before
doing so Ipc_start must connect and communicate with LAD.  However, LAD
gets stuck in the pre-FIFO GateMP_setup() since NameServer has not yet
attached, which caused Ipc_start() to hang waiting to connect to LAD
(since there was no command FIFO yet).  In a nutshell, a deadlock.

This is fixed by introducing GateMP_attach(procId), which is called by
Ipc_attach().  GateMP_attach() performs the functionality that was
getting stuck in GateMP_setup() (and GateMP_setup() is pared down to not
need to "attach").

GateMP_detach(procId) is also introduced and called by Ipc_detach().
While these APIs can be called by the advanced user, they are considered
to be "internal" APIs.

linux/include/_GateMP.h
linux/include/_lad.h
linux/src/api/Ipc.c
linux/src/api/gates/GateMP.c
linux/src/daemon/GateMP_daemon.c
linux/src/daemon/lad.c

index 3c26db1f6deb312045381b6596b2793332c5444b..901a6a1a94577e9273be495d83c70aab37d16708 100644 (file)
@@ -89,6 +89,9 @@ Int GateMP_start(Void);
 /* Stop the GateMP module */
 Int GateMP_stop(Void);
 
+Int GateMP_attach(UInt16 procId);
+Int GateMP_detach(UInt16 procId);
+
 #if defined (__cplusplus)
 }
 #endif /* defined (__cplusplus) */
index 3cffe83a52c14991a06dd9b244c4a68d645694f0..b0a9c821cf15391df93732dc9c92897d04ae656e 100644 (file)
@@ -187,6 +187,8 @@ typedef enum {
     LAD_MESSAGEQ_DELETE,
     LAD_MESSAGEQ_MSGINIT,
     LAD_MULTIPROC_GETCONFIG,
+    LAD_GATEMP_ATTACH,
+    LAD_GATEMP_DETACH,
     LAD_GATEMP_START,
     LAD_GATEMP_GETNUMRESOURCES,
     LAD_GATEMP_GETFREERESOURCE,
index 42ac0cbe415ad0a8d75f71e7fd5dc3a81d60cbbd..e81700c6762a388ab40b77b614dad93b6dab87fa 100644 (file)
@@ -400,6 +400,9 @@ Int Ipc_attach(UInt16 procId)
 {
     Int status = Ipc_S_SUCCESS;
     UInt16 clusterId;
+#if defined(GATEMP_SUPPORT)
+    Int ret;
+#endif
 
     /* cannot attach to yourself */
     if (MultiProc_self() == procId) {
@@ -443,6 +446,18 @@ Int Ipc_attach(UInt16 procId)
     /* hack: bind all existing message queues to remote processor */
     MessageQ_bind(procId);
 
+#if defined(GATEMP_SUPPORT)
+    if (GateMP_isSetup()) {
+        /* establish GateMP connection to remote processor */
+        ret = GateMP_attach(procId);
+
+        if (ret < 0) {
+            PRINTVERBOSE1("Ipc_attach: failed to GateMP_attach to procId %d\n",
+                          procId);
+        }
+    }
+#endif
+
     /* getting here means we have successfully attached */
     Ipc_module.attached[clusterId]++;
 
@@ -459,6 +474,9 @@ Int Ipc_detach(UInt16 procId)
 {
     Int status = Ipc_S_SUCCESS;
     UInt16 clusterId;
+#if defined(GATEMP_SUPPORT)
+    Int ret;
+#endif
 
     /* cannot detach from yourself */
     if (MultiProc_self() == procId) {
@@ -486,6 +504,18 @@ Int Ipc_detach(UInt16 procId)
         goto done;
     }
 
+#if defined(GATEMP_SUPPORT)
+    if (GateMP_isSetup()) {
+        /* establish GateMP connection to remote processor */
+        ret = GateMP_detach(procId);
+
+        if (ret < 0) {
+            PRINTVERBOSE1("Ipc_detach: failed to GateMP_detach from procId %d\n",
+                          procId);
+        }
+    }
+#endif
+
     /* hack: unbind all existing message queues from remote processor */
     MessageQ_unbind(procId);
 
index e9d17c2b0adcd18de9a805cf57a4a3399ac5169d..e71629dd1dbfec212fe47dcd7df062a268bdd36f 100644 (file)
@@ -124,6 +124,86 @@ static GateMP_Params GateMP_defInstParams =
     .remoteProtect  = GateMP_RemoteProtect_SYSTEM
 };
 
+/*
+ *  ======== GateMP_attach ========
+ *  Internal function.
+ */
+Int GateMP_attach(UInt16 procId)
+{
+    Int status;
+    LAD_ClientHandle clHandle;
+    struct LAD_CommandObj cmd;
+    union LAD_ResponseObj rsp;
+
+    clHandle = LAD_findHandle();
+
+    if (clHandle == LAD_MAXNUMCLIENTS) {
+        PRINTVERBOSE0("GateMP_attach: not connected to LAD\n");
+        return (GateMP_E_RESOURCE);
+    }
+
+    cmd.cmd = LAD_GATEMP_ATTACH;
+    cmd.clientId = clHandle;
+    cmd.args.attach.procId = procId;
+
+    if ((status = LAD_putCommand(&cmd)) != LAD_SUCCESS) {
+        PRINTVERBOSE1("GateMP_attach: sending LAD command failed, "
+                "status=%d\n", status);
+        return (GateMP_E_FAIL);
+    }
+
+    if ((status = LAD_getResponse(clHandle, &rsp)) != LAD_SUCCESS) {
+        PRINTVERBOSE1("GateMP_attach: no LAD response, status=%d\n",
+                status);
+        return (GateMP_E_FAIL);
+    }
+
+    status = rsp.status;
+    PRINTVERBOSE1("GateMP_attach: LAD response, status=%d\n", status)
+
+    return (status);
+}
+
+/*
+ *  ======== GateMP_detach ========
+ *  Internal function.
+ */
+Int GateMP_detach(UInt16 procId)
+{
+    Int status;
+    LAD_ClientHandle clHandle;
+    struct LAD_CommandObj cmd;
+    union LAD_ResponseObj rsp;
+
+    clHandle = LAD_findHandle();
+
+    if (clHandle == LAD_MAXNUMCLIENTS) {
+        PRINTVERBOSE0("GateMP_detach: not connected to LAD\n");
+        return (GateMP_E_RESOURCE);
+    }
+
+    cmd.cmd = LAD_GATEMP_DETACH;
+    cmd.clientId = clHandle;
+    cmd.args.detach.procId = procId;
+
+    if ((status = LAD_putCommand(&cmd)) != LAD_SUCCESS) {
+        PRINTVERBOSE1("GateMP_detach: sending LAD command failed, "
+                "status=%d\n", status);
+        return (GateMP_E_FAIL);
+    }
+
+    if ((status = LAD_getResponse(clHandle, &rsp)) != LAD_SUCCESS) {
+        PRINTVERBOSE1("GateMP_detach: no LAD response, status=%d\n",
+                status);
+        return (GateMP_E_FAIL);
+    }
+
+    status = rsp.status;
+    PRINTVERBOSE1("GateMP_detach: LAD response, status=%d\n", status)
+
+    return (status);
+}
+
 Int GateMP_start(Void)
 {
     Int status;
index d2db25d3bed18809991fd4058ad5ef34ed658f03..7e689d1634e06a11f2b3176205ff67bf5c1b370d 100644 (file)
@@ -92,10 +92,12 @@ typedef struct {
     GateMP_Handle     defaultGate;
     NameServer_Handle nameServer;
     Bool              isSetup;
+    Int               refCount[MultiProc_MAXPROCESSORS];
+    UInt16            attachedProcId;
 } GateMP_ModuleObject;
 
 /* Internal functions */
-static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr);
+static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[]);
 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
 
 /* =============================================================================
@@ -114,7 +116,9 @@ static GateMP_ModuleObject GateMP_state = {
     .remoteCustom2InUse              = NULL,
     .defaultGate                     = NULL,
     .nameServer                      = NULL,
-    .isSetup                         = FALSE
+    .isSetup                         = FALSE,
+    .refCount                        = {0},
+    .attachedProcId                  = MultiProc_INVALIDID,
 };
 
 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
@@ -124,17 +128,15 @@ static GateMP_ModuleObject * GateMP_module = &GateMP_state;
  * =============================================================================
  */
 
-/* Function to setup the gatemp module. */
+/*
+ * Function to setup the gatemp module.
+ *
+ * No need to refCount this since it's not callable by user.
+ */
 Int GateMP_setup(Void)
 {
     Int               status = GateMP_S_SUCCESS;
     NameServer_Params params;
-    UInt32            nsValue[NUM_INFO_FIELDS];
-    UInt32            len;
-    UInt32            size;
-    UInt32            alignDiff;
-    UInt32            offset;
-    Int32             fdMem;
 
     NameServer_Params_init(&params);
     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
@@ -150,38 +152,81 @@ Int GateMP_setup(Void)
         status = GateMP_E_FAIL;
         LOG0("GateMP_setup: NameServer_create failed\n");
     }
+    else {
+        GateMP_module->isSetup = TRUE;
+    }
 
-    if (status == GateMP_S_SUCCESS) {
-        do {
-            sleep(1);   /* Give the slaves some time to get NameServer ready */
-            status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
-        } while (status == GateMP_E_NOTFOUND);
+    return status;
+}
 
+Int GateMP_attach(UInt16 procId)
+{
+    GateMP_Handle     deflateGate;  /* that's right, Pats fan here */
+    Int               status = GateMP_S_SUCCESS;
+    UInt32            nsValue[NUM_INFO_FIELDS];
+    UInt32            len;
+    UInt32            size;
+    UInt32            alignDiff;
+    UInt32            offset;
+    Int32             fdMem;
+    UInt16            procList[2];
+    UInt16            clId;
+
+    /* procId already validated in API layer */
+    clId = procId - MultiProc_getBaseIdOfCluster();
+    if (clId >= MultiProc_getNumProcsInCluster()) {
+        LOG1("GateMP_attach: procId %d not in range for local cluster\n",
+             procId);
+        return GateMP_E_INVALIDARG;
+    }
 
-        if (status < 0) {
-            LOG0("GateMP_setup: failed to open default gate\n");
-            status = GateMP_E_FAIL;
-        }
+    /* must reference count because we have multiple clients */
+    if (GateMP_module->refCount[clId] > 0) {
+        GateMP_module->refCount[clId]++;
+        goto done;
+    }
+
+    procList[0] = procId;
+    procList[1] = MultiProc_INVALIDID;
+    status = GateMP_openDefaultGate(&deflateGate, procList);
+
+    if (status < 0) {
+        LOG1("GateMP_attach: failed to open default gate on procId %d\n",
+             procId);
+        goto done;
     }
 
     if (status == GateMP_S_SUCCESS) {
+        if (GateMP_module->attachedProcId != MultiProc_INVALIDID) {
+            LOG1("GateMP_attach: can't attach to procId %d\n", procId);
+            LOG1("               already attached to %d\n",
+                 GateMP_module->attachedProcId);
+            status = GateMP_E_ALREADYEXISTS;
+            goto done;
+        }
+
+        GateMP_module->attachedProcId = procId;
+        GateMP_module->defaultGate = deflateGate;
+
+        GateMP_module->refCount[clId]++;
+
         /* Process global info NameServer entry */
         len = sizeof(nsValue);
 
         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
-            &nsValue, &len, NULL);
+            &nsValue, &len, procList);
 
         if (status < 0) {
-            LOG0("GateMP_setup: failed to find info entry\n");
+            LOG0("GateMP_attach: failed to find info entry\n");
             status = GateMP_E_NOTFOUND;
         }
         else {
             fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
 
             if (fdMem < 0){
-                LOG0("GateMP_setup: failed to open the /dev/mem!\n");
-                status = GateMP_E_FAIL;
-                goto cleanup;
+                LOG0("GateMP_attach: failed to open the /dev/mem!\n");
+                status = GateMP_E_OSFAILURE;
+                goto done;
             }
 
             GateMP_module->numRemoteSystem = nsValue[3];
@@ -272,19 +317,33 @@ Int GateMP_setup(Void)
 
     /* TODO: setup the proxy map */
 
-cleanup:
-    /* clean up if error */
-    if (status < 0) {
-        GateMP_destroy();
-    }
-
-    GateMP_module->isSetup = TRUE;
+done:
 
     return (status);
 }
 
-Void GateMP_destroy(Void)
+Int GateMP_detach(UInt16 procId)
 {
+    UInt16 clId;
+
+    if (procId != GateMP_module->attachedProcId) {
+        return GateMP_E_NOTFOUND;
+    }
+
+    /* procId already validated in API layer */
+    clId = procId - MultiProc_getBaseIdOfCluster();
+    if (clId >= MultiProc_getNumProcsInCluster()) {
+        LOG1("GateMP_detach: procId %d not in range for local cluster\n",
+             procId);
+        return GateMP_E_INVALIDARG;
+    }
+
+
+    /* decrement reference count regardless of outcome below */
+    if (--GateMP_module->refCount[clId] > 0) {
+        goto done;
+    }
+
     if (GateMP_module->remoteSystemInUse) {
         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
             GateMP_module->numRemoteSystem * sizeof (UInt8));
@@ -305,8 +364,16 @@ Void GateMP_destroy(Void)
 
     if (GateMP_module->defaultGate) {
         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
+        GateMP_module->attachedProcId = MultiProc_INVALIDID;
     }
 
+done:
+
+    return GateMP_S_SUCCESS;
+}
+
+Void GateMP_destroy(Void)
+{
     if (GateMP_module->nameServer) {
         NameServer_delete(&GateMP_module->nameServer);
         GateMP_module->nameServer = NULL;
@@ -317,8 +384,8 @@ Void GateMP_destroy(Void)
     return;
 }
 
-/* Open default gate during GateMP_setup. Should only be called once */
-static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
+/* Open default gate during GateMP_attach. Should only be called once */
+static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[])
 {
     Int             status = GateMP_S_SUCCESS;
     UInt32          len;
@@ -326,13 +393,12 @@ static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
     GateMP_Object * obj = NULL;
     UInt32          arg;
     UInt32          mask;
-    UInt32          creatorProcId;
 
     GateMP_RemoteSystemProxy_Params     systemParams;
 
     /* assert that a valid pointer has been supplied */
     if (handlePtr == NULL) {
-        LOG0("GateMP_open: argument cannot be null\n");
+        LOG0("GateMP_openDefaultGate: argument cannot be null\n");
         status = GateMP_E_INVALIDARG;
     }
 
@@ -340,7 +406,7 @@ static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
         len = sizeof(nsValue);
 
         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
-            &nsValue, &len, NULL);
+            &nsValue, &len, procId);
 
         if (status < 0) {
             *handlePtr = NULL;
@@ -349,7 +415,6 @@ static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
         else {
             arg = nsValue[2];
             mask = nsValue[3];
-            creatorProcId = nsValue[1] >> 16;
         }
     }
 
index 170c3ec6c783ae402b8cff9a869a8b8052375e1c..b9c740e2a69ee38d576c6c3c8b37cf94b37e7f5c 100644 (file)
@@ -127,6 +127,7 @@ int main(int argc, char * argv[])
     Int c;
 #if defined(GATEMP_SUPPORT)
     Int status;
+    UInt16 procId;
 #endif
     String tmpString;
 #if DAEMON
@@ -686,11 +687,33 @@ opencommandFIFO:
             break;
 
 #if defined(GATEMP_SUPPORT)
+          case LAD_GATEMP_ATTACH:
+            procId = cmd.args.attach.procId;
+            LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
+
+            rsp.status = GateMP_attach(procId);
+
+            LOG1("    status = %d\n", rsp.status)
+            LOG0("DONE\n")
+
+            break;
+
+          case LAD_GATEMP_DETACH:
+            procId = cmd.args.detach.procId;
+            LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
+
+            rsp.status = GateMP_detach(procId);
+
+            LOG1("    status = %d\n", rsp.status)
+            LOG0("DONE\n")
+
+            break;
+
           case LAD_GATEMP_START:
             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
 
             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
-            rsp.gateMPStart.status = GateMP_S_SUCCESS;;
+            rsp.gateMPStart.status = GateMP_S_SUCCESS;
 
             LOG1("    status = %d\n", rsp.gateMPStart.status)
             LOG0("DONE\n")
@@ -797,6 +820,8 @@ opencommandFIFO:
           case LAD_MESSAGEQ_MSGINIT:
           case LAD_MULTIPROC_GETCONFIG:
 #if defined(GATEMP_SUPPORT)
+          case LAD_GATEMP_ATTACH:
+          case LAD_GATEMP_DETACH:
           case LAD_GATEMP_START:
           case LAD_GATEMP_GETNUMRESOURCES:
           case LAD_GATEMP_GETFREERESOURCE: