Merge branch 'windows-port'
[platform/upstream/iotivity.git] / resource / csdk / connectivity / common / src / camutex_pthreads.c
index 6d866ad..6c166b1 100644 (file)
 #define _POSIX_C_SOURCE 200809L
 #endif
 
+#ifdef HAVE_STRING_H
 #include <string.h>
+#endif
+#ifdef HAVE_PTHREAD_H
 #include <pthread.h>
-#include <errno.h>
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+#ifdef HAVE_TIME_H
 #include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
 #include <assert.h>
 #include <oic_malloc.h>
-
+#include "platform_features.h"
 #include "camutex.h"
 #include "logger.h"
 
@@ -76,13 +90,21 @@ static const uint64_t NANOSECS_PER_SEC      = 1000000000L;
 
 typedef struct _tagMutexInfo_t
 {
+#if defined(_WIN32)
+    CRITICAL_SECTION mutex;
+#else
     pthread_mutex_t mutex;
+#endif
 } ca_mutex_internal;
 
 typedef struct _tagEventInfo_t
 {
+#if defined(_WIN32)
+    CONDITION_VARIABLE cond;
+#else
     pthread_cond_t cond;
     pthread_condattr_t condattr;
+#endif
 } ca_cond_internal;
 
 ca_mutex ca_mutex_new(void)
@@ -91,6 +113,10 @@ ca_mutex ca_mutex_new(void)
     ca_mutex_internal *mutexInfo = (ca_mutex_internal*) OICMalloc(sizeof(ca_mutex_internal));
     if (NULL != mutexInfo)
     {
+#if defined(_WIN32)
+        InitializeCriticalSection(&mutexInfo->mutex);
+        retVal = (ca_mutex)mutexInfo;
+#else
         // create the mutex with the attributes set
         int ret=pthread_mutex_init(&(mutexInfo->mutex), PTHREAD_MUTEX_DEFAULT);
         if (0 == ret)
@@ -102,6 +128,11 @@ ca_mutex ca_mutex_new(void)
             OIC_LOG_V(ERROR, TAG, "%s Failed to initialize mutex !", __func__);
             OICFree(mutexInfo);
         }
+#endif
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
     }
 
     return retVal;
@@ -114,6 +145,11 @@ bool ca_mutex_free(ca_mutex mutex)
     ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
     if (mutexInfo)
     {
+#if defined(_WIN32)
+        DeleteCriticalSection(&mutexInfo->mutex);
+        OICFree(mutexInfo);
+        bRet=true;
+#else
         int ret = pthread_mutex_destroy(&mutexInfo->mutex);
         if (0 == ret)
         {
@@ -124,6 +160,7 @@ bool ca_mutex_free(ca_mutex mutex)
         {
             OIC_LOG_V(ERROR, TAG, "%s Failed to free mutex !", __func__);
         }
+#endif
     }
     else
     {
@@ -138,12 +175,16 @@ void ca_mutex_lock(ca_mutex mutex)
     ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
     if (mutexInfo)
     {
+#if defined(_WIN32)
+        EnterCriticalSection(&mutexInfo->mutex);
+#else
         int ret = pthread_mutex_lock(&mutexInfo->mutex);
         if(ret != 0)
         {
             OIC_LOG_V(ERROR, TAG, "Pthread Mutex lock failed: %d", ret);
             exit(ret);
         }
+#endif
     }
     else
     {
@@ -157,6 +198,9 @@ void ca_mutex_unlock(ca_mutex mutex)
     ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
     if (mutexInfo)
     {
+#if defined(_WIN32)
+        LeaveCriticalSection(&mutexInfo->mutex);
+#else
         int ret = pthread_mutex_unlock(&mutexInfo->mutex);
         if(ret != 0)
         {
@@ -164,11 +208,12 @@ void ca_mutex_unlock(ca_mutex mutex)
             exit(ret);
         }
         (void)ret;
+#endif
     }
     else
     {
-          OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
-          return;
+        OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
+        return;
     }
 }
 
@@ -178,6 +223,10 @@ ca_cond ca_cond_new(void)
     ca_cond_internal *eventInfo = (ca_cond_internal*) OICMalloc(sizeof(ca_cond_internal));
     if (NULL != eventInfo)
     {
+#if defined(_WIN32)
+        InitializeConditionVariable(&eventInfo->cond);
+        retVal = (ca_cond) eventInfo;
+#else
         int ret = pthread_condattr_init(&(eventInfo->condattr));
         if(0 != ret)
         {
@@ -187,15 +236,15 @@ ca_cond ca_cond_new(void)
             return retVal;
         }
 
-#if defined(__ANDROID__) || _POSIX_TIMERS > 0
-#ifdef __ANDROID__
+ #if defined(__ANDROID__) || _POSIX_TIMERS > 0
+  #ifdef __ANDROID__
         if (camutex_condattr_setclock)
         {
             ret = camutex_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
-#else
+  #else
         {
             ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
-#endif /*  __ANDROID__ */
+  #endif /*  __ANDROID__ */
             if(0 != ret)
             {
                 OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!",
@@ -205,7 +254,7 @@ ca_cond ca_cond_new(void)
                 return retVal;
             }
         }
-#endif /* defined(__ANDROID__) || _POSIX_TIMERS > 0 */
+ #endif /* defined(__ANDROID__) || _POSIX_TIMERS > 0 */
         ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr));
         if (0 == ret)
         {
@@ -217,6 +266,11 @@ ca_cond ca_cond_new(void)
             pthread_condattr_destroy(&(eventInfo->condattr));
             OICFree(eventInfo);
         }
+#endif
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
     }
 
     return retVal;
@@ -227,6 +281,9 @@ void ca_cond_free(ca_cond cond)
     ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
     if (eventInfo != NULL)
     {
+#if defined(_WIN32)
+        OICFree(cond);
+#else
         int ret = pthread_cond_destroy(&(eventInfo->cond));
         int ret2 = pthread_condattr_destroy(&(eventInfo->condattr));
         if (0 == ret && 0 == ret2)
@@ -238,6 +295,7 @@ void ca_cond_free(ca_cond cond)
             OIC_LOG_V(ERROR, TAG, "%s: Failed to destroy condition variable %d, %d",
                     __func__, ret, ret2);
         }
+#endif
     }
     else
     {
@@ -250,11 +308,15 @@ void ca_cond_signal(ca_cond cond)
     ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
     if (eventInfo != NULL)
     {
+#if defined(_WIN32)
+        WakeConditionVariable(&eventInfo->cond);
+#else
         int ret = pthread_cond_signal(&(eventInfo->cond));
         if (0 != ret)
         {
             OIC_LOG_V(ERROR, TAG, "%s: Failed to signal condition variable", __func__);
         }
+#endif
     }
     else
     {
@@ -267,11 +329,15 @@ void ca_cond_broadcast(ca_cond cond)
     ca_cond_internal* eventInfo = (ca_cond_internal*) cond;
     if (eventInfo != NULL)
     {
+#if defined(_WIN32)
+        WakeAllConditionVariable(&eventInfo->cond);
+#else
         int ret = pthread_cond_broadcast(&(eventInfo->cond));
         if (0 != ret)
         {
             OIC_LOG_V(ERROR, TAG, "%s: failed to signal condition variable", __func__);
         }
+#endif
     }
     else
     {
@@ -284,6 +350,14 @@ void ca_cond_wait(ca_cond cond, ca_mutex mutex)
     ca_cond_wait_for(cond, mutex, 0L);
 }
 
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) {               \
+    (ts)->tv_sec = (tv)->tv_sec;                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;           \
+}
+#endif
+
+#if !defined(_WIN32)
 struct timespec ca_get_current_time()
 {
 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
@@ -309,6 +383,7 @@ void ca_add_microseconds_to_timespec(struct timespec* ts, uint64_t microseconds)
     ts->tv_nsec = (totalNs)% NANOSECS_PER_SEC;
     ts->tv_sec += secPart + secOfNs;
 }
+#endif
 
 CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex, uint64_t microseconds)
 {
@@ -331,6 +406,25 @@ CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex, uint64_t microseco
 
     if (microseconds > 0)
     {
+#if defined(_WIN32)
+        // Wait for the given time
+        DWORD milli = (DWORD)(microseconds / 1000);
+        if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
+        {
+            if (GetLastError() == ERROR_TIMEOUT)
+            {
+                retVal = CA_WAIT_TIMEDOUT;
+            }
+            else
+            {
+                OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() with Timeout failed %i", GetLastError());
+                retVal = CA_WAIT_INVAL;
+            }
+        }else
+        {
+            retVal = CA_WAIT_SUCCESS;
+        }
+#else
         int ret;
         struct timespec abstime;
 
@@ -369,14 +463,26 @@ CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex, uint64_t microseco
                 retVal = CA_WAIT_INVAL;
                 break;
         }
+#endif
     }
     else
     {
+#if defined(_WIN32)
+        // Wait forever
+        if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, INFINITE))
+        {
+            OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() w/o Timeout failed %i", GetLastError());
+            retVal = CA_WAIT_INVAL;
+        }else
+        {
+            retVal = CA_WAIT_SUCCESS;
+        }
+#else
         // Wait forever
         int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
         retVal = ret == 0 ? CA_WAIT_SUCCESS : CA_WAIT_INVAL;
+#endif
     }
-
     return retVal;
 }