SDOCM114476 Ipc_start is not thread safe (Linux)
authorRamsey Harris <ramsey@ti.com>
Wed, 14 Jan 2015 00:21:35 +0000 (16:21 -0800)
committerRobert Tivy <rtivy@ti.com>
Thu, 15 Jan 2015 18:44:21 +0000 (10:44 -0800)
Added a Posix mutex and a reference count to serialize the Ipc_start
and Ipc_stop methods. Added a module object to hold the mutex and
reference count.

linux/src/api/Ipc.c

index ffad32bb5ce97ffb67c19e64c4ac41b1b3a049a8..a828e58dd785ad4fb981aa0e6669f2a8e6623248 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -29,6 +29,7 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /*!
  *  @file       Ipc.c
  *
  *              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_Module;
 
+
+/* =============================================================================
+ *  Globals
+ * =============================================================================
+ */
+static Ipc_Module Ipc_module = {
+    .refCount   = 0,
+    .gate       = PTHREAD_MUTEX_INITIALIZER
+};
+
+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)
 {
     TransportRpmsg_Handle  transport;
     TransportRpmsg_Params  params;
@@ -87,6 +108,15 @@ Int Ipc_start (Void)
     UInt16                 rprocId;
     Int32                  attachedAny;
 
+    /* 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;
+    }
+
     /* Catch ctrl-C, and cleanup: */
     (void) signal(SIGINT, cleanup);
 
@@ -231,17 +261,33 @@ gatehwspinlockstart_fail:
 #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;
 
+    /* function must be serialized */
+    pthread_mutex_lock(&Ipc_module.gate);
+
+    /* ensure only last thread performs stop procedure */
+    if (--Ipc_module.refCount > 0) {
+        goto exit;
+    }
+
     /* Now detach from all remote processors, assuming they are up. */
     for (rprocId = 0;
          (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
@@ -283,6 +329,8 @@ Int Ipc_stop (Void)
     }
 
 exit:
+    pthread_mutex_unlock(&Ipc_module.gate);
+
     return (status);
 }