Make OCProcessEvent method.
[platform/upstream/iotivity.git] / resource / c_common / octhread / src / windows / octhread.c
1 /* *****************************************************************
2 *
3 * Copyright 2016 Intel Corporation
4 *
5 *
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
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 *
18 ******************************************************************/
19
20
21 /**
22  * @file
23  * This file provides APIs related to mutex, semaphores, and threads.
24  */
25 #include "iotivity_config.h"
26 #include "octhread.h"
27 #include <string.h>
28 #include <time.h>
29 #include <winsock2.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <oic_malloc.h>
33
34 #include "logger.h"
35
36 static const uint64_t USECS_PER_MSEC = 1000;
37
38 typedef struct _tagMutexInfo_t
39 {
40     CRITICAL_SECTION mutex;
41     DWORD owner;
42     uint32_t recursionCount;
43 } oc_mutex_internal;
44
45 static DWORD oc_get_current_thread_id()
46 {
47     DWORD id = GetCurrentThreadId();
48     assert(OC_INVALID_THREAD_ID != id);
49     return id;
50 }
51
52 typedef struct _tagEventInfo_t
53 {
54     CONDITION_VARIABLE cond;
55 } oc_cond_internal;
56
57 typedef struct _tagThreadInfo_t
58 {
59     HANDLE handle;
60 } oc_thread_internal;
61
62 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
63 {
64     OCThreadResult_t res = OC_THREAD_SUCCESS;
65     oc_thread_internal *threadInfo = (oc_thread_internal*)OICMalloc(sizeof(oc_thread_internal));
66     if (NULL != threadInfo)
67     {
68         threadInfo->handle = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
69         if (threadInfo->handle == NULL)
70         {
71             res = OC_THREAD_CREATE_FAILURE;
72             *t = NULL;
73             OICFree(threadInfo);
74             OIC_LOG_V(ERROR, TAG, "%s: CreateThread failed: %i", __func__, GetLastError());
75         }
76         else
77         {
78             *t = (oc_thread)threadInfo;
79         }
80     }
81     else
82     {
83         OIC_LOG_V(ERROR, TAG, "%s Failed to allocate thread!", __func__);
84         *t = NULL;
85         res = OC_THREAD_ALLOCATION_FAILURE;
86     }
87
88    return res;
89 }
90
91 OCThreadResult_t oc_thread_free(oc_thread t)
92 {
93     OCThreadResult_t res = OC_THREAD_INVALID_PARAMETER;
94     oc_thread_internal *threadInfo = (oc_thread_internal*) t;
95     if (threadInfo)
96     {
97         CloseHandle(threadInfo->handle);
98         OICFree(threadInfo);
99         res = OC_THREAD_SUCCESS;
100     }
101     else
102     {
103         OIC_LOG_V(ERROR, TAG, "%s Invalid thread !", __func__);
104     }
105     return res;
106 }
107
108 OCThreadResult_t oc_thread_wait(oc_thread t)
109 {
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)
114     {
115         OIC_LOG(ERROR, TAG, "Failed to join thread");
116         res = OC_THREAD_WAIT_FAILURE;
117     }
118     else
119     {
120         CloseHandle(threadInfo->handle);
121     }
122     return res;
123 }
124
125 oc_mutex oc_mutex_new(void)
126 {
127     oc_mutex retVal = NULL;
128     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
129     if (NULL != mutexInfo)
130     {
131         InitializeCriticalSection(&mutexInfo->mutex);
132         retVal = (oc_mutex)mutexInfo;
133     }
134     else
135     {
136         OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
137     }
138
139     return retVal;
140 }
141
142 bool oc_mutex_free(oc_mutex mutex)
143 {
144     bool bRet = false;
145     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
146     if (mutexInfo)
147     {
148         DeleteCriticalSection(&mutexInfo->mutex);
149         OICFree(mutexInfo);
150         bRet=true;
151     }
152     else
153     {
154         OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
155     }
156
157     return bRet;
158 }
159
160 void oc_mutex_lock(oc_mutex mutex)
161 {
162     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
163     if (mutexInfo)
164     {
165         EnterCriticalSection(&mutexInfo->mutex);
166     }
167     else
168     {
169         OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
170     }
171 }
172
173 void oc_mutex_unlock(oc_mutex mutex)
174 {
175     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
176     if (mutexInfo)
177     {
178         LeaveCriticalSection(&mutexInfo->mutex);
179     }
180     else
181     {
182         OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
183     }
184 }
185
186 void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
187 {
188     assert(NULL != mutex);
189     const oc_mutex_internal *mutexInfo = (const oc_mutex_internal*) mutex;
190
191     DWORD currentThreadID = oc_get_current_thread_id();
192     if (currentThreadIsOwner)
193     {
194         assert(mutexInfo->owner == currentThreadID);
195         assert(mutexInfo->recursionCount != 0);
196     }
197     else
198     {
199         assert(mutexInfo->owner != currentThreadID);
200     }
201 }
202
203 oc_cond oc_cond_new(void)
204 {
205     oc_cond retVal = NULL;
206     oc_cond_internal *eventInfo = (oc_cond_internal*) OICMalloc(sizeof(oc_cond_internal));
207     if (NULL != eventInfo)
208     {
209         InitializeConditionVariable(&eventInfo->cond);
210         retVal = (oc_cond) eventInfo;
211     }
212     else
213     {
214         OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
215     }
216
217     return retVal;
218 }
219
220 void oc_cond_free(oc_cond cond)
221 {
222     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
223     if (eventInfo != NULL)
224     {
225         OICFree(cond);
226     }
227     else
228     {
229         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
230     }
231 }
232
233 void oc_cond_signal(oc_cond cond)
234 {
235     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
236     if (eventInfo != NULL)
237     {
238         WakeConditionVariable(&eventInfo->cond);
239     }
240     else
241     {
242         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
243     }
244 }
245
246 void oc_cond_broadcast(oc_cond cond)
247 {
248     oc_cond_internal* eventInfo = (oc_cond_internal*) cond;
249     if (eventInfo != NULL)
250     {
251         WakeAllConditionVariable(&eventInfo->cond);
252     }
253     else
254     {
255         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
256     }
257 }
258
259 void oc_cond_wait(oc_cond cond, oc_mutex mutex)
260 {
261     oc_cond_wait_for(cond, mutex, 0L);
262 }
263
264 OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseconds)
265 {
266     OCWaitResult_t retVal = OC_WAIT_INVAL;
267
268     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
269     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
270
271     if (NULL == mutexInfo)
272     {
273         OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
274         return OC_WAIT_INVAL;
275     }
276
277     if (NULL == eventInfo)
278     {
279         OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
280         return OC_WAIT_INVAL;
281     }
282
283     DWORD milli = 0;
284     if (microseconds > 0)
285     {
286         milli = (DWORD)(microseconds / USECS_PER_MSEC);
287     }
288     else
289     {
290         milli = INFINITE;
291     }
292
293     // Wait for the given time        
294     if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
295     {
296         if (GetLastError() == ERROR_TIMEOUT)
297         {
298             retVal = OC_WAIT_TIMEDOUT;
299         }
300         else
301         {
302             OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() failed %i", GetLastError());
303             retVal = OC_WAIT_INVAL;
304         }
305     }
306     else
307     {
308         retVal = OC_WAIT_SUCCESS;
309     }
310
311     return retVal;
312 }
313