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;
43 typedef struct _tagEventInfo_t
45 CONDITION_VARIABLE cond;
48 typedef struct _tagThreadInfo_t
53 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
55 OCThreadResult_t res = OC_THREAD_SUCCESS;
56 oc_thread_internal *threadInfo = (oc_thread_internal*)OICMalloc(sizeof(oc_thread_internal));
57 if (NULL != threadInfo)
59 threadInfo->handle = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
60 if (threadInfo->handle == NULL)
62 res = OC_THREAD_CREATE_FAILURE;
65 OIC_LOG_V(ERROR, TAG, "%s: CreateThread failed: %i", __func__, GetLastError());
69 *t = (oc_thread)threadInfo;
74 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate thread!", __func__);
76 res = OC_THREAD_ALLOCATION_FAILURE;
82 OCThreadResult_t oc_thread_free(oc_thread t)
84 OCThreadResult_t res = OC_THREAD_INVALID_PARAMETER;
85 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
88 CloseHandle(threadInfo->handle);
90 res = OC_THREAD_SUCCESS;
94 OIC_LOG_V(ERROR, TAG, "%s Invalid thread !", __func__);
99 OCThreadResult_t oc_thread_wait(oc_thread t)
101 OCThreadResult_t res = OC_THREAD_SUCCESS;
102 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
103 DWORD joinres = WaitForSingleObject(threadInfo->handle, INFINITE);
104 if (WAIT_OBJECT_0 != joinres)
106 OIC_LOG(ERROR, TAG, "Failed to join thread");
107 res = OC_THREAD_WAIT_FAILURE;
111 CloseHandle(threadInfo->handle);
116 oc_mutex oc_mutex_new(void)
118 oc_mutex retVal = NULL;
119 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
120 if (NULL != mutexInfo)
122 InitializeCriticalSection(&mutexInfo->mutex);
123 retVal = (oc_mutex)mutexInfo;
127 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
133 bool oc_mutex_free(oc_mutex mutex)
136 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
139 DeleteCriticalSection(&mutexInfo->mutex);
145 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
151 void oc_mutex_lock(oc_mutex mutex)
153 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
156 EnterCriticalSection(&mutexInfo->mutex);
160 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
164 void oc_mutex_unlock(oc_mutex mutex)
166 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
169 LeaveCriticalSection(&mutexInfo->mutex);
173 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
177 oc_cond oc_cond_new(void)
179 oc_cond retVal = NULL;
180 oc_cond_internal *eventInfo = (oc_cond_internal*) OICMalloc(sizeof(oc_cond_internal));
181 if (NULL != eventInfo)
183 InitializeConditionVariable(&eventInfo->cond);
184 retVal = (oc_cond) eventInfo;
188 OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
194 void oc_cond_free(oc_cond cond)
196 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
197 if (eventInfo != NULL)
203 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
207 void oc_cond_signal(oc_cond cond)
209 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
210 if (eventInfo != NULL)
212 WakeConditionVariable(&eventInfo->cond);
216 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
220 void oc_cond_broadcast(oc_cond cond)
222 oc_cond_internal* eventInfo = (oc_cond_internal*) cond;
223 if (eventInfo != NULL)
225 WakeAllConditionVariable(&eventInfo->cond);
229 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
233 void oc_cond_wait(oc_cond cond, oc_mutex mutex)
235 oc_cond_wait_for(cond, mutex, 0L);
238 OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseconds)
240 OCWaitResult_t retVal = OC_WAIT_INVAL;
242 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
243 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
245 if (NULL == mutexInfo)
247 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
248 return OC_WAIT_INVAL;
251 if (NULL == eventInfo)
253 OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
254 return OC_WAIT_INVAL;
258 if (microseconds > 0)
260 milli = (DWORD)(microseconds / USECS_PER_MSEC);
267 // Wait for the given time
268 if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
270 if (GetLastError() == ERROR_TIMEOUT)
272 retVal = OC_WAIT_TIMEDOUT;
276 OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() failed %i", GetLastError());
277 retVal = OC_WAIT_INVAL;
282 retVal = OC_WAIT_SUCCESS;