1 /* *****************************************************************
3 * Copyright 2016 Intel Corporation
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 ******************************************************************/
23 * This file provides APIs related to mutex, semaphores, and threads.
25 #include "iotivity_config.h"
32 #include <oic_malloc.h>
36 static const uint64_t USECS_PER_MSEC = 1000;
38 typedef struct _tagMutexInfo_t
40 CRITICAL_SECTION mutex;
42 uint32_t recursionCount;
45 static DWORD oc_get_current_thread_id()
47 DWORD id = GetCurrentThreadId();
48 assert(OC_INVALID_THREAD_ID != id);
52 typedef struct _tagEventInfo_t
54 CONDITION_VARIABLE cond;
57 typedef struct _tagThreadInfo_t
62 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
64 OCThreadResult_t res = OC_THREAD_SUCCESS;
65 oc_thread_internal *threadInfo = (oc_thread_internal*)OICMalloc(sizeof(oc_thread_internal));
66 if (NULL != threadInfo)
68 threadInfo->handle = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
69 if (threadInfo->handle == NULL)
71 res = OC_THREAD_CREATE_FAILURE;
74 OIC_LOG_V(ERROR, TAG, "%s: CreateThread failed: %i", __func__, GetLastError());
78 *t = (oc_thread)threadInfo;
83 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate thread!", __func__);
85 res = OC_THREAD_ALLOCATION_FAILURE;
91 OCThreadResult_t oc_thread_free(oc_thread t)
93 OCThreadResult_t res = OC_THREAD_INVALID_PARAMETER;
94 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
97 CloseHandle(threadInfo->handle);
99 res = OC_THREAD_SUCCESS;
103 OIC_LOG_V(ERROR, TAG, "%s Invalid thread !", __func__);
108 OCThreadResult_t oc_thread_wait(oc_thread t)
110 OCThreadResult_t res = OC_THREAD_SUCCESS;
111 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
112 DWORD joinres = WaitForSingleObject(threadInfo->handle, INFINITE);
113 if (WAIT_OBJECT_0 != joinres)
115 OIC_LOG(ERROR, TAG, "Failed to join thread");
116 res = OC_THREAD_WAIT_FAILURE;
120 CloseHandle(threadInfo->handle);
125 oc_mutex oc_mutex_new(void)
127 oc_mutex retVal = NULL;
128 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
129 if (NULL != mutexInfo)
131 InitializeCriticalSection(&mutexInfo->mutex);
132 retVal = (oc_mutex)mutexInfo;
136 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
142 bool oc_mutex_free(oc_mutex mutex)
145 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
148 DeleteCriticalSection(&mutexInfo->mutex);
154 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
160 void oc_mutex_lock(oc_mutex mutex)
162 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
165 EnterCriticalSection(&mutexInfo->mutex);
169 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
173 void oc_mutex_unlock(oc_mutex mutex)
175 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
178 LeaveCriticalSection(&mutexInfo->mutex);
182 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
186 void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
188 assert(NULL != mutex);
189 const oc_mutex_internal *mutexInfo = (const oc_mutex_internal*) mutex;
191 DWORD currentThreadID = oc_get_current_thread_id();
192 if (currentThreadIsOwner)
194 assert(mutexInfo->owner == currentThreadID);
195 assert(mutexInfo->recursionCount != 0);
199 assert(mutexInfo->owner != currentThreadID);
203 oc_cond oc_cond_new(void)
205 oc_cond retVal = NULL;
206 oc_cond_internal *eventInfo = (oc_cond_internal*) OICMalloc(sizeof(oc_cond_internal));
207 if (NULL != eventInfo)
209 InitializeConditionVariable(&eventInfo->cond);
210 retVal = (oc_cond) eventInfo;
214 OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
220 void oc_cond_free(oc_cond cond)
222 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
223 if (eventInfo != NULL)
229 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
233 void oc_cond_signal(oc_cond cond)
235 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
236 if (eventInfo != NULL)
238 WakeConditionVariable(&eventInfo->cond);
242 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
246 void oc_cond_broadcast(oc_cond cond)
248 oc_cond_internal* eventInfo = (oc_cond_internal*) cond;
249 if (eventInfo != NULL)
251 WakeAllConditionVariable(&eventInfo->cond);
255 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
259 void oc_cond_wait(oc_cond cond, oc_mutex mutex)
261 oc_cond_wait_for(cond, mutex, 0L);
264 OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseconds)
266 OCWaitResult_t retVal = OC_WAIT_INVAL;
268 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
269 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
271 if (NULL == mutexInfo)
273 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
274 return OC_WAIT_INVAL;
277 if (NULL == eventInfo)
279 OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
280 return OC_WAIT_INVAL;
284 if (microseconds > 0)
286 milli = (DWORD)(microseconds / USECS_PER_MSEC);
293 // Wait for the given time
294 if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
296 if (GetLastError() == ERROR_TIMEOUT)
298 retVal = OC_WAIT_TIMEDOUT;
302 OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() failed %i", GetLastError());
303 retVal = OC_WAIT_INVAL;
308 retVal = OC_WAIT_SUCCESS;