diff --git a/linux/src/api/Ipc.c b/linux/src/api/Ipc.c
index 6dbb0b6cf622570d033405038a3e0689478c0bf2..b6290941f5180e9f9df0a50f56307bbd5496f4ea 100644 (file)
--- a/linux/src/api/Ipc.c
+++ b/linux/src/api/Ipc.c
/*
- * Copyright (c) 2012-2014, Texas Instruments Incorporated
+ * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* module.
*/
-/* Standard headers */
+/* standard headers */
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
-/* Common IPC headers: */
+/* package headers */
#include <ti/ipc/Std.h>
#include <ti/ipc/Ipc.h>
#include <ti/ipc/NameServer.h>
#include <_MessageQ.h>
#include <_NameServer.h>
-GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
+/* module definition */
+typedef struct {
+ Int refCount;
+ pthread_mutex_t gate;
+ Ipc_TransportFactoryFxns *transportFactory;
+} Ipc_Module;
+
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+static Ipc_Module Ipc_module = {
+ .refCount = 0,
+ .gate = PTHREAD_MUTEX_INITIALIZER,
+ .transportFactory = NULL
+};
+GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
static LAD_ClientHandle ladHandle;
-static void cleanup(int arg);
/** ============================================================================
* Functions
* ============================================================================
*/
-/* Function to start Ipc */
-Int Ipc_start (Void)
+static void cleanup(int arg);
+
+
+/*
+ * ======== Ipc_start ========
+ */
+Int Ipc_start(Void)
{
- MessageQ_Config msgqCfg;
- MultiProc_Config mpCfg;
+ MessageQ_Config msgqCfg;
+ MultiProc_Config mpCfg;
#if defined(GATEMP_SUPPORT)
- GateHWSpinlock_Config gateHWCfg;
+ GateHWSpinlock_Config gateHWCfg;
#endif
- Int32 status;
- LAD_Status ladStatus;
- UInt16 rprocId;
- Int32 attachedAny = 0;
+ Int status;
+ LAD_Status ladStatus;
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* ensure only first thread performs startup procedure */
+ if (++Ipc_module.refCount > 1) {
+ status = Ipc_S_ALREADYSETUP;
+ goto exit;
+ }
+
+ /* make sure transport factory has been configured */
+ if (Ipc_module.transportFactory == NULL) {
+ status = Ipc_E_INVALIDSTATE;
+ goto exit;
+ }
/* Catch ctrl-C, and cleanup: */
(void) signal(SIGINT, cleanup);
goto exit;
}
- /*
- * Get MultiProc configuration from LAD and initialize local MultiProc
- * config structure.
+ /* Get MultiProc configuration from LAD and initialize local
+ * MultiProc config structure.
*/
MultiProc_getConfig(&mpCfg);
_MultiProc_initCfg(&mpCfg);
status = NameServer_setup();
+
if (status >= 0) {
MessageQ_getConfig(&msgqCfg);
MessageQ_setup(&msgqCfg);
- /* Now attach to all remote processors, assuming they are up. */
- for (rprocId = 0; rprocId < MultiProc_getNumProcessors(); rprocId++) {
- if (0 == rprocId) {
- /* Skip host, which should always be 0th entry. */
- continue;
- }
- status = MessageQ_attach(rprocId, NULL);
- if (status == MessageQ_E_RESOURCE) {
- continue;
- }
- if (status < 0) {
- printf("Ipc_start: MessageQ_attach(%d) failed: %d\n",
- rprocId, status);
- status = Ipc_E_FAIL;
+ /* invoke the transport factory create method */
+ status = Ipc_module.transportFactory->createFxn();
- break;
- }
- else {
- attachedAny = 1;
- }
- }
- if (attachedAny) {
- status = Ipc_S_SUCCESS;
+ if (status < 0) {
+ goto exit;
}
}
else {
gatempstart_fail:
GateHWSpinlock_stop();
gatehwspinlockstart_fail:
- for (rprocId = rprocId - 1; (rprocId > 0) && (status >= 0); rprocId--) {
- MessageQ_detach(rprocId);
+#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--;
+ }
+
+ pthread_mutex_unlock(&Ipc_module.gate);
+
return (status);
}
-
-/* Function to stop Ipc */
-Int Ipc_stop (Void)
+/*
+ * ======== Ipc_stop ========
+ */
+Int Ipc_stop(Void)
{
- Int32 status = Ipc_S_SUCCESS;
- LAD_Status ladStatus;
- UInt16 rprocId;
-
- /* Now detach from all remote processors, assuming they are up. */
- for (rprocId = 0;
- (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
- rprocId++) {
- if (0 == rprocId) {
- /* Skip host, which should always be 0th entry. */
- continue;
+ Int32 status = Ipc_S_SUCCESS;
+ LAD_Status ladStatus;
+ Int i;
+ UInt16 procId;
+ UInt16 clusterSize;
+ UInt16 clusterBase;
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* ensure only last thread performs stop procedure */
+ if (--Ipc_module.refCount > 0) {
+ goto exit;
+ }
+
+ /* invoke the transport factory delete method */
+ Ipc_module.transportFactory->deleteFxn();
+
+ /* needed to enumerate processors in cluster */
+ clusterSize = MultiProc_getNumProcsInCluster();
+ clusterBase = MultiProc_getBaseIdOfCluster();
+
+ /* detach from all remote processors, assuming they are up */
+ for (i = 0, procId = clusterBase; i < clusterSize; i++, procId++) {
+
+ /* no need to detach from myself */
+ if (MultiProc_self() == procId) {
+ continue;
}
- status = MessageQ_detach(rprocId);
+#if 0
+ status = MessageQ_detach(procId);
if (status < 0) {
printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
- rprocId, status);
+ procId, status);
status = Ipc_E_FAIL;
goto exit;
}
+#endif
}
status = MessageQ_destroy();
}
exit:
+ pthread_mutex_unlock(&Ipc_module.gate);
+
+ return (status);
+}
+
+/*
+ * ======== Ipc_transportConfig ========
+ */
+Int Ipc_transportConfig(Ipc_TransportFactoryFxns *factory)
+{
+ Int status = Ipc_S_SUCCESS;
+
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* Only the first caller can actually set the transport factory.
+ * Subsequent callers (e.g. multi-threaded application) must be
+ * using the same factory. Otherwise, it is an error.
+ */
+ if (Ipc_module.transportFactory == NULL) {
+ Ipc_module.transportFactory = factory;
+ }
+ else if (Ipc_module.transportFactory != factory) {
+ status = Ipc_E_INVALIDARG;
+ goto exit;
+ }
+
+exit:
+ pthread_mutex_unlock(&Ipc_module.gate);
+
return (status);
}