Adding changes in octhread related to Process Event 90/203790/1
authorkush.agrawal <kush.agrawal@samsung.com>
Wed, 17 Apr 2019 14:42:06 +0000 (23:42 +0900)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Thu, 18 Apr 2019 00:52:37 +0000 (09:52 +0900)
https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/483
(cherry picked from a6f36988f0f0206b26837f98061e594a74dd5990)

Change-Id: Ic4b846bfc46734a7ce32d193318c85afdd7d49e9
Signed-off-by: kush.agrawal <kush.agrawal@samsung.com>
Signed-off-by: DoHyun Pyun <dh79.pyun@samsung.com>
build_common/SConscript
resource/c_common/octhread/src/posix/octhread.c
resource/c_common/octhread/src/windows/octhread.c

index f02da23..c351abe 100755 (executable)
@@ -138,7 +138,7 @@ help_vars.Add(EnumVariable('TIZEN_4', 'Build with tizen 4.0 api', 'False', allow
 help_vars.Add(PathVariable('TIZENRT_OS_DIR', 'Absolute Path to TizenRT OS directory', None, PathVariable.PathAccept))
 help_vars.Add(EnumVariable('PLATFORM_TLS', 'Use platform tls instead of local mbedtls', '0', allowed_values=('0', '1')))
 help_vars.Add(EnumVariable('OIC_SUPPORT_TIZEN_TRACE', 'Tizen Trace(T-trace) api availability', 'False', allowed_values=('True', 'False')))
-help_vars.Add(EnumVariable('WITH_PROCESS_EVENT','Build including procee event logics in ocstack', 'False', allowed_values=('True', 'False')))
+help_vars.Add(BoolVariable('WITH_PROCESS_EVENT','Build including process event logics in ocstack', 'False'))
 AddOption('--prefix',
                   dest='prefix',
                   type='string',
index 7214ebf..df530b3 100755 (executable)
@@ -37,6 +37,7 @@
 #endif
 
 #include "iotivity_config.h"
+#include "iotivity_debug.h"
 #include "octhread.h"
 #ifdef HAVE_STRING_H
 #include <string.h>
@@ -88,8 +89,15 @@ static const uint64_t NANOSECS_PER_SEC      = 1000000000L;
 typedef struct _tagMutexInfo_t
 {
     pthread_mutex_t mutex;
+
+    /**
+     * Catch some of the incorrect mutex usage, by tracking the mutex owner,
+     * on Debug builds.
+     */
+#ifndef NDEBUG
     pthread_t owner;
     uint32_t recursionCount;
+#endif
 } oc_mutex_internal;
 
 typedef struct _tagEventInfo_t
@@ -104,12 +112,14 @@ typedef struct _tagThreadInfo_t
     pthread_attr_t  threadattr;
 } oc_thread_internal;
 
+#ifndef NDEBUG
 static pthread_t oc_get_current_thread_id()
 {
     pthread_t id = pthread_self();
     assert(OC_INVALID_THREAD_ID != id);
     return id;
 }
+#endif
 
 #ifndef __TIZENRT__
 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
@@ -226,6 +236,10 @@ oc_mutex oc_mutex_new(void)
         int ret=pthread_mutex_init(&(mutexInfo->mutex), PTHREAD_MUTEX_DEFAULT);
         if (0 == ret)
         {
+#ifndef NDEBUG
+            mutexInfo->owner = OC_INVALID_THREAD_ID;
+            mutexInfo->recursionCount = 0;
+#endif
             retVal = (oc_mutex) mutexInfo;
         }
         else
@@ -242,6 +256,66 @@ oc_mutex oc_mutex_new(void)
     return retVal;
 }
 
+oc_mutex oc_mutex_new_recursive(void)
+{
+    oc_mutex retVal = NULL;
+    int ret = -1;
+
+    // Allocate new mutex.
+    oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
+    if (NULL == mutexInfo)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
+        goto exit;
+    }
+
+    // Set up the mutex attributes.
+    pthread_mutexattr_t ma;
+    ret = pthread_mutexattr_init(&ma);
+    if (0 != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutexattr_init - error %d!",
+            __func__, ret);
+        goto exit;
+    }
+
+    ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
+    if (0 != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutexattr_settype - error %d!",
+            __func__, ret);
+        pthread_mutexattr_destroy(&ma);
+        goto exit;
+    }
+
+    // Initialize the mutex and destroy the attributes.
+    ret = pthread_mutex_init(&(mutexInfo->mutex), &ma);
+    OC_VERIFY(0 == pthread_mutexattr_destroy(&ma));
+    if (0 != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutex_init - error %d!",
+            __func__, ret);
+        goto exit;
+    }
+
+#ifndef NDEBUG
+    mutexInfo->owner = OC_INVALID_THREAD_ID;
+    mutexInfo->recursionCount = 0;
+#endif
+
+exit:
+    if (0 == ret)
+    {
+        retVal = (oc_mutex) mutexInfo;
+    }
+    else
+    {
+        OICFree(mutexInfo);
+    }
+
+    return retVal;
+}
+
 bool oc_mutex_free(oc_mutex mutex)
 {
     bool bRet=false;
@@ -278,6 +352,24 @@ void oc_mutex_lock(oc_mutex mutex)
             OIC_LOG_V(ERROR, TAG, "Pthread Mutex lock failed: %d", ret);
             exit(ret);
         }
+
+#ifndef NDEBUG
+        /**
+         * Updating the recursionCount and owner fields must be performed
+         * while owning the lock, to solve race conditions with other
+         * threads using the same lock.
+         */
+        if (mutexInfo->recursionCount != 0)
+        {
+            oc_mutex_assert_owner(mutex, true);
+        }
+        else
+        {
+            mutexInfo->owner = oc_get_current_thread_id();
+        }
+
+        mutexInfo->recursionCount++;
+#endif
     }
     else
     {
@@ -296,6 +388,23 @@ void oc_mutex_unlock(oc_mutex mutex)
             return;
         }
 #endif
+
+#ifndef NDEBUG
+        oc_mutex_assert_owner(mutex, true);
+
+        /**
+         * Updating the recursionCount and owner fields must be performed
+         * while owning the lock, to solve race conditions with other
+         * threads using the same lock.
+         */
+        mutexInfo->recursionCount--;
+
+        if (mutexInfo->recursionCount == 0)
+        {
+            mutexInfo->owner = OC_INVALID_THREAD_ID;
+        }
+#endif
+
         int ret = pthread_mutex_unlock(&mutexInfo->mutex);
         if (ret != 0)
         {
@@ -311,6 +420,10 @@ void oc_mutex_unlock(oc_mutex mutex)
 
 void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
 {
+#ifdef NDEBUG
+    (void)mutex;
+    (void)currentThreadIsOwner;
+#else
     assert(NULL != mutex);
     const oc_mutex_internal *mutexInfo = (const oc_mutex_internal*) mutex;
 
@@ -324,6 +437,7 @@ void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
     {
         assert(!pthread_equal(mutexInfo->owner, currentThreadID));
     }
+#endif
 }
 
 oc_cond oc_cond_new(void)
@@ -512,8 +626,23 @@ OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseco
              abstime = oc_get_current_time();
             oc_add_microseconds_to_timespec(&abstime, microseconds);
 
-            //Wait for the given time
+#ifndef NDEBUG
+            // Recursively-acquired locks are not supported for use with condition variables.
+            oc_mutex_assert_owner(mutex, true);
+            assert(mutexInfo->recursionCount == 1);
+            mutexInfo->recursionCount = 0;
+            mutexInfo->owner = OC_INVALID_THREAD_ID;
+#endif
+
+            // Wait for the given time
             ret = pthread_cond_timedwait(&(eventInfo->cond), &(mutexInfo->mutex), &abstime);
+
+#ifndef NDEBUG
+            oc_mutex_assert_owner(mutex, false);
+            assert(mutexInfo->recursionCount == 0);
+            mutexInfo->recursionCount = 1;
+            mutexInfo->owner = oc_get_current_thread_id();
+#endif
         }
 
         switch (ret)
@@ -537,9 +666,29 @@ OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseco
     }
     else
     {
+#ifndef NDEBUG
+        // Recursively-acquired locks are not supported for use with condition variables.
+        oc_mutex_assert_owner(mutex, true);
+        assert(mutexInfo->recursionCount == 1);
+        mutexInfo->recursionCount = 0;
+        mutexInfo->owner = OC_INVALID_THREAD_ID;
+#endif
+
         // Wait forever
+#ifndef NDEBUG
+        // The conditional variable wait API used will atomically release the mutex, but the
+        // best we can do here is to just clear the owner info before the API is called.
+        mutexInfo->owner = OC_INVALID_THREAD_ID;
+#endif
         int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
-        retVal = ret == 0 ? OC_WAIT_SUCCESS : OC_WAIT_INVAL;
+        retVal = (ret == 0) ? OC_WAIT_SUCCESS : OC_WAIT_INVAL;
+
+#ifndef NDEBUG
+        oc_mutex_assert_owner(mutex, false);
+        assert(mutexInfo->recursionCount == 0);
+        mutexInfo->recursionCount = 1;
+        mutexInfo->owner = oc_get_current_thread_id();
+#endif
     }
     return retVal;
 }
index 826a68a..daed0bd 100755 (executable)
@@ -38,16 +38,25 @@ static const uint64_t USECS_PER_MSEC = 1000;
 typedef struct _tagMutexInfo_t
 {
     CRITICAL_SECTION mutex;
+
+    /**
+     * Catch some of the incorrect mutex usage, by tracking the mutex owner,
+     * on Debug builds.
+     */
+#ifndef NDEBUG
     DWORD owner;
     uint32_t recursionCount;
+#endif
 } oc_mutex_internal;
 
+#ifndef NDEBUG
 static DWORD oc_get_current_thread_id()
 {
     DWORD id = GetCurrentThreadId();
     assert(OC_INVALID_THREAD_ID != id);
     return id;
 }
+#endif
 
 typedef struct _tagEventInfo_t
 {
@@ -94,7 +103,7 @@ OCThreadResult_t oc_thread_free(oc_thread t)
     oc_thread_internal *threadInfo = (oc_thread_internal*) t;
     if (threadInfo)
     {
-        CloseHandle(threadInfo->handle);
+        OC_VERIFY(CloseHandle(threadInfo->handle));
         OICFree(threadInfo);
         res = OC_THREAD_SUCCESS;
     }
@@ -128,6 +137,10 @@ oc_mutex oc_mutex_new(void)
     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
     if (NULL != mutexInfo)
     {
+#ifndef NDEBUG
+        mutexInfo->owner = OC_INVALID_THREAD_ID;
+        mutexInfo->recursionCount = 0;
+#endif
         InitializeCriticalSection(&mutexInfo->mutex);
         retVal = (oc_mutex)mutexInfo;
     }
@@ -139,6 +152,11 @@ oc_mutex oc_mutex_new(void)
     return retVal;
 }
 
+oc_mutex oc_mutex_new_recursive(void)
+{
+    return oc_mutex_new();
+}
+
 bool oc_mutex_free(oc_mutex mutex)
 {
     bool bRet = false;
@@ -163,6 +181,24 @@ void oc_mutex_lock(oc_mutex mutex)
     if (mutexInfo)
     {
         EnterCriticalSection(&mutexInfo->mutex);
+
+#ifndef NDEBUG
+        /**
+         * Updating the recursionCount and owner fields must be performed
+         * while owning the lock, to solve race conditions with other
+         * threads using the same lock.
+         */
+        if (mutexInfo->recursionCount != 0)
+        {
+            oc_mutex_assert_owner(mutex, true);
+        }
+        else
+        {
+            mutexInfo->owner = oc_get_current_thread_id();
+        }
+
+        mutexInfo->recursionCount++;
+#endif
     }
     else
     {
@@ -175,6 +211,22 @@ void oc_mutex_unlock(oc_mutex mutex)
     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
     if (mutexInfo)
     {
+#ifndef NDEBUG
+        oc_mutex_assert_owner(mutex, true);
+
+        /**
+         * Updating the recursionCount and owner fields must be performed
+         * while owning the lock, to solve race conditions with other
+         * threads using the same lock.
+         */
+        mutexInfo->recursionCount--;
+
+        if (mutexInfo->recursionCount == 0)
+        {
+            mutexInfo->owner = OC_INVALID_THREAD_ID;
+        }
+#endif
+
         LeaveCriticalSection(&mutexInfo->mutex);
     }
     else
@@ -185,6 +237,10 @@ void oc_mutex_unlock(oc_mutex mutex)
 
 void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
 {
+#ifdef NDEBUG
+    (void)(mutex);
+    (void)(currentThreadIsOwner);
+#else
     assert(NULL != mutex);
     const oc_mutex_internal *mutexInfo = (const oc_mutex_internal*) mutex;
 
@@ -198,6 +254,7 @@ void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
     {
         assert(mutexInfo->owner != currentThreadID);
     }
+#endif
 }
 
 oc_cond oc_cond_new(void)
@@ -290,6 +347,14 @@ OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseco
         milli = INFINITE;
     }
 
+#ifndef NDEBUG
+    // Recursively-acquired locks are not supported for use with condition variables.
+    oc_mutex_assert_owner(mutex, true);
+    assert(mutexInfo->recursionCount == 1);
+    mutexInfo->recursionCount = 0;
+    mutexInfo->owner = OC_INVALID_THREAD_ID;
+#endif
+
     // Wait for the given time        
     if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
     {
@@ -308,6 +373,14 @@ OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseco
         retVal = OC_WAIT_SUCCESS;
     }
 
+
+#ifndef NDEBUG
+    oc_mutex_assert_owner(mutex, false);
+    assert(mutexInfo->recursionCount == 0);
+    mutexInfo->recursionCount = 1;
+    mutexInfo->owner = oc_get_current_thread_id();
+#endif
+
     return retVal;
 }