diff --git a/linux/src/api/Ipc.c b/linux/src/api/Ipc.c
index b6290941f5180e9f9df0a50f56307bbd5496f4ea..96804660ab401ba5489188d970224552f6f49794 100644 (file)
--- a/linux/src/api/Ipc.c
+++ b/linux/src/api/Ipc.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <string.h>
/* package headers */
#include <ti/ipc/Std.h>
#include <ti/ipc/MultiProc.h>
#include <GateHWSpinlock.h>
#include <_GateMP.h>
+#include <_Ipc.h>
#include <_MultiProc.h>
#include <_MessageQ.h>
#include <_NameServer.h>
Int refCount;
pthread_mutex_t gate;
Ipc_TransportFactoryFxns *transportFactory;
+ Ipc_Config config;
+ Int attached[MultiProc_MAXPROCESSORS];
} Ipc_Module;
*/
static Ipc_Module Ipc_module = {
.refCount = 0,
- .gate = PTHREAD_MUTEX_INITIALIZER,
- .transportFactory = NULL
+#if defined(IPC_BUILDOS_ANDROID)
+ .gate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
+#else
+// only _NP (non-portable) type available in CG tools which we're using
+ .gate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
+#endif
+ .transportFactory = NULL,
+ .config.procSync = Ipc_ProcSync_NONE
};
GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
static LAD_ClientHandle ladHandle;
+/* traces in this file are controlled via _Ipc_verbose */
+Bool _Ipc_verbose = FALSE;
+#define verbose _Ipc_verbose
/** ============================================================================
* Functions
#endif
Int status;
LAD_Status ladStatus;
+ UInt16 procId;
+ UInt16 clusterSize;
+ UInt16 baseId;
+ UInt16 clusterId;
+ Int i;
/* function must be serialized */
pthread_mutex_lock(&Ipc_module.gate);
/* ensure only first thread performs startup procedure */
- if (++Ipc_module.refCount > 1) {
+ if (Ipc_module.refCount >= 1) {
+ Ipc_module.refCount++;
status = Ipc_S_ALREADYSETUP;
goto exit;
}
goto exit;
}
+ /* initialize module object */
+ for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
+ Ipc_module.attached[i] = 0;
+ }
+
/* Catch ctrl-C, and cleanup: */
(void) signal(SIGINT, cleanup);
}
}
+ /* establish a communication link to the LAD daemon */
ladStatus = LAD_connect(&ladHandle);
+
if (ladStatus != LAD_SUCCESS) {
printf("Ipc_start: LAD_connect() failed: %d\n", ladStatus);
status = Ipc_E_FAIL;
goto exit;
}
- /* Get MultiProc configuration from LAD and initialize local
- * MultiProc config structure.
- */
+ /* get global configuration from LAD */
+ Ipc_getConfig(&Ipc_module.config);
+
+ /* get global configuration from LAD */
MultiProc_getConfig(&mpCfg);
_MultiProc_initCfg(&mpCfg);
+ /* setup name server thread in LAD daemon */
status = NameServer_setup();
- if (status >= 0) {
- MessageQ_getConfig(&msgqCfg);
- MessageQ_setup(&msgqCfg);
+ if (status < 0) {
+ printf("Ipc_start: NameServer_setup() failed: %d\n", status);
+ status = Ipc_E_FAIL;
+ goto exit;
+ }
+
+ /* get global configuration from LAD */
+ MessageQ_getConfig(&msgqCfg);
+ MessageQ_setup(&msgqCfg);
- /* invoke the transport factory create method */
- status = Ipc_module.transportFactory->createFxn();
+ /* invoke the transport factory create method */
+ status = Ipc_module.transportFactory->createFxn();
- if (status < 0) {
- goto exit;
- }
+ if (status < 0) {
+ goto exit;
}
- else {
- printf("Ipc_start: NameServer_setup() failed: %d\n", status);
- status = Ipc_E_FAIL;
+
+ /* if using ProcSync_ALL, then attach to all processors in the cluster */
+ if (Ipc_module.config.procSync == Ipc_ProcSync_ALL) {
+ clusterSize = MultiProc_getNumProcsInCluster();
+ baseId = MultiProc_getBaseIdOfCluster();
+
+ for (clusterId = 0; clusterId < clusterSize; clusterId++) {
+ procId = baseId + clusterId;
+
+ if (procId == MultiProc_self()) {
+ continue;
+ }
+
+ status = Ipc_attach(procId);
+
+ /* For backward compatibility, it is okay for attach to fail.
+ * We don't expect all remote processors to be running.
+ */
+ if (status < 0) {
+ status = 0;
+ /* do nothing */
+ }
+ }
}
/* Start GateMP only if device has support */
status = GateHWSpinlock_start();
if (status < 0) {
- printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
- status);
+ printf("Ipc_start: GateHWSpinlock_start failed: %d\n", status);
status = Ipc_E_FAIL;
- goto gatehwspinlockstart_fail;
+ goto exit;
}
- else {
- status = GateMP_start();
- if (status < 0) {
- printf("Ipc_start: GateMP_start failed: %d\n",
- status);
- status = Ipc_E_FAIL;
- goto gatempstart_fail;
- }
+
+ status = GateMP_start();
+ if (status < 0) {
+ printf("Ipc_start: GateMP_start failed: %d\n", status);
+ status = Ipc_E_FAIL;
+ GateHWSpinlock_stop();
+ goto exit;
}
}
-#endif
- /* Success */
- goto exit;
-#if defined(GATEMP_SUPPORT)
-gatempstart_fail:
- GateHWSpinlock_stop();
-gatehwspinlockstart_fail:
-#if 0
- for (procId = procId - 1; (procId > 0) && (status >= 0); procId--) {
- MessageQ_detach(procId);
- }
-#endif
#endif
-exit:
- /* if error, must decrement reference count */
- if (status < 0) {
- Ipc_module.refCount--;
- }
+ /* getting here means we have successfully started */
+ Ipc_module.refCount++;
+exit:
pthread_mutex_unlock(&Ipc_module.gate);
return (status);
{
Int32 status = Ipc_S_SUCCESS;
LAD_Status ladStatus;
- Int i;
UInt16 procId;
UInt16 clusterSize;
- UInt16 clusterBase;
+ UInt16 baseId;
+ UInt16 clusterId;
/* function must be serialized */
pthread_mutex_lock(&Ipc_module.gate);
+ if (Ipc_module.refCount == 0) {
+ status = Ipc_E_INVALIDSTATE;
+ goto exit;
+ }
+
/* ensure only last thread performs stop procedure */
if (--Ipc_module.refCount > 0) {
goto exit;
}
- /* invoke the transport factory delete method */
- Ipc_module.transportFactory->deleteFxn();
+ /* if using ProcSync_ALL, then detach from all processors in the cluster */
+ if (Ipc_module.config.procSync == Ipc_ProcSync_ALL) {
+ clusterSize = MultiProc_getNumProcsInCluster();
+ baseId = MultiProc_getBaseIdOfCluster();
- /* needed to enumerate processors in cluster */
- clusterSize = MultiProc_getNumProcsInCluster();
- clusterBase = MultiProc_getBaseIdOfCluster();
+ for (clusterId = 0; clusterId < clusterSize; clusterId++) {
+ procId = baseId + clusterId;
- /* detach from all remote processors, assuming they are up */
- for (i = 0, procId = clusterBase; i < clusterSize; i++, procId++) {
+ if (MultiProc_self() == procId) {
+ continue;
+ }
- /* no need to detach from myself */
- if (MultiProc_self() == procId) {
- continue;
+ /* For backward compatibility, we might not be attached to
+ * all cluster members. Skip unattached processors.
+ */
+ if (!Ipc_isAttached(procId)) {
+ continue;
+ }
+
+ status = Ipc_detach(procId);
+
+ if (status < 0) {
+ /* Should we keep going or stop? */
+ }
}
-#if 0
- status = MessageQ_detach(procId);
- if (status < 0) {
- printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
- procId, status);
- status = Ipc_E_FAIL;
- goto exit;
- }
-#endif
}
+ Ipc_module.transportFactory->deleteFxn();
+
status = MessageQ_destroy();
if (status < 0) {
printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status);
Ipc_stop();
exit(0);
}
+
+/*
+ * ======== Ipc_attach ========
+ */
+Int Ipc_attach(UInt16 procId)
+{
+ Int status = Ipc_S_SUCCESS;
+ UInt16 clusterId;
+
+ /* cannot attach to yourself */
+ if (MultiProc_self() == procId) {
+ status = Ipc_E_INVALIDARG;
+ goto done;
+ }
+
+ /* processor must be a member of the cluster */
+ clusterId = procId - MultiProc_getBaseIdOfCluster();
+
+ if (clusterId >= MultiProc_getNumProcsInCluster()) {
+ status = Ipc_E_INVALIDARG;
+ goto done;
+ }
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* if already attached, just increment reference count */
+ if (Ipc_module.attached[clusterId] > 0) {
+ Ipc_module.attached[clusterId]++;
+ goto done;
+ }
+
+ /* establish name server connection to remote processor */
+ status = NameServer_attach(procId);
+
+ if (status < 0) {
+ status = Ipc_E_FAIL;
+ goto done;
+ }
+
+ /* attach the transport to remote processor */
+ status = Ipc_module.transportFactory->attachFxn(procId);
+
+ if (status < 0) {
+ status = Ipc_E_FAIL;
+ goto done;
+ }
+
+ /* getting here means we have successfully attached */
+ Ipc_module.attached[clusterId]++;
+
+done:
+ pthread_mutex_unlock(&Ipc_module.gate);
+
+ return (status);
+}
+
+/*
+ * ======== Ipc_detach ========
+ */
+Int Ipc_detach(UInt16 procId)
+{
+ Int status = Ipc_S_SUCCESS;
+ UInt16 clusterId;
+
+ /* cannot detach from yourself */
+ if (MultiProc_self() == procId) {
+ status = Ipc_E_INVALIDARG;
+ goto done;
+ }
+
+ /* processor must be a member of the cluster */
+ clusterId = procId - MultiProc_getBaseIdOfCluster();
+
+ if (clusterId >= MultiProc_getNumProcsInCluster()) {
+ status = Ipc_E_INVALIDARG;
+ goto done;
+ }
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ if (Ipc_module.attached[clusterId] == 0) {
+ status = Ipc_E_INVALIDSTATE;
+ goto done;
+ }
+
+ if (--Ipc_module.attached[clusterId] > 0) {
+ goto done;
+ }
+
+ /* detach transport from remote processor */
+ status = Ipc_module.transportFactory->detachFxn(procId);
+
+ if (status < 0) {
+ status = Ipc_E_FAIL;
+ /* report the error */
+ goto done;
+ }
+
+ /* remove connection to remote processor */
+ status = NameServer_detach(procId);
+
+ if (status < 0) {
+ status = Ipc_E_FAIL;
+ /* report the error */
+ goto done;
+ }
+
+done:
+ if (status < 0) {
+ /* report error */
+ printf("Ipc_detach: Error %d, procId %d\n", status, procId);
+ }
+ pthread_mutex_unlock(&Ipc_module.gate);
+
+ return (status);
+}
+
+/*
+ * ======== Ipc_isAttached ========
+ */
+Bool Ipc_isAttached(UInt16 procId)
+{
+ Bool attached;
+ UInt16 clusterId;
+
+ /* cannot be attached to yourself */
+ if (MultiProc_self() == procId) {
+ return (FALSE);
+ }
+
+ /* processor must be a member of the cluster */
+ clusterId = procId - MultiProc_getBaseIdOfCluster();
+
+ if (clusterId >= MultiProc_getNumProcsInCluster()) {
+ return (FALSE);
+ }
+
+ attached = (Ipc_module.attached[clusterId] > 0 ? TRUE : FALSE);
+ return (attached);
+}
+
+/*
+ * ======== Ipc_getConfig ========
+ * Get the run-time configuration for the Ipc module
+ *
+ * This is an IPC internal function. It is used to acquire
+ * the global Ipc module configuration values from LAD.
+ */
+Void Ipc_getConfig(Ipc_Config *cfg)
+{
+ Int status;
+ LAD_ClientHandle handle;
+ struct LAD_CommandObj cmd;
+ union LAD_ResponseObj rsp;
+
+ handle = LAD_findHandle();
+ if (handle == LAD_MAXNUMCLIENTS) {
+ PRINTVERBOSE0("Ipc_getConfig: no connection to LAD\n");
+ return;
+ }
+
+ cmd.cmd = LAD_IPC_GETCONFIG;
+ cmd.clientId = handle;
+
+ if ((status = LAD_putCommand(&cmd)) != LAD_SUCCESS) {
+ PRINTVERBOSE1("Ipc_getConfig: sending LAD command failed, "
+ "status=%d\n", status);
+ return;
+ }
+
+ if ((status = LAD_getResponse(handle, &rsp)) != LAD_SUCCESS) {
+ PRINTVERBOSE1("Ipc_getConfig: no LAD response, status=%d\n", status);
+ return;
+ }
+
+ memcpy(cfg, &rsp.ipcConfig, sizeof(Ipc_Config));
+ return;
+}