From: kush.agrawal Date: Wed, 17 Apr 2019 14:42:06 +0000 (+0900) Subject: Adding changes in octhread related to Process Event X-Git-Tag: accepted/tizen/unified/20190418.145712~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Fiotivity.git;a=commitdiff_plain;h=eb4cf6824439d79e05685766f2d1e263abeba209 Adding changes in octhread related to Process Event https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/483 (cherry picked from a6f36988f0f0206b26837f98061e594a74dd5990) Change-Id: Ic4b846bfc46734a7ce32d193318c85afdd7d49e9 Signed-off-by: kush.agrawal Signed-off-by: DoHyun Pyun --- diff --git a/build_common/SConscript b/build_common/SConscript index f02da23..c351abe 100755 --- a/build_common/SConscript +++ b/build_common/SConscript @@ -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', diff --git a/resource/c_common/octhread/src/posix/octhread.c b/resource/c_common/octhread/src/posix/octhread.c index 7214ebf..df530b3 100755 --- a/resource/c_common/octhread/src/posix/octhread.c +++ b/resource/c_common/octhread/src/posix/octhread.c @@ -37,6 +37,7 @@ #endif #include "iotivity_config.h" +#include "iotivity_debug.h" #include "octhread.h" #ifdef HAVE_STRING_H #include @@ -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; } diff --git a/resource/c_common/octhread/src/windows/octhread.c b/resource/c_common/octhread/src/windows/octhread.c index 826a68a..daed0bd 100755 --- a/resource/c_common/octhread/src/windows/octhread.c +++ b/resource/c_common/octhread/src/windows/octhread.c @@ -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; }