replace : iotivity -> iotivity-sec
[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 } oc_mutex_internal;
42
43 typedef struct _tagEventInfo_t
44 {
45     CONDITION_VARIABLE cond;
46 } oc_cond_internal;
47
48 typedef struct _tagThreadInfo_t
49 {
50     HANDLE handle;
51 } oc_thread_internal;
52
53 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
54 {
55     OCThreadResult_t res = OC_THREAD_SUCCESS;
56     oc_thread_internal *threadInfo = (oc_thread_internal*)OICMalloc(sizeof(oc_thread_internal));
57     if (NULL != threadInfo)
58     {
59         threadInfo->handle = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
60         if (threadInfo->handle == NULL)
61         {
62             res = OC_THREAD_CREATE_FAILURE;
63             *t = NULL;
64             OICFree(threadInfo);
65             OIC_LOG_V(ERROR, TAG, "%s: CreateThread failed: %i", __func__, GetLastError());
66         }
67         else
68         {
69             *t = (oc_thread)threadInfo;
70         }
71     }
72     else
73     {
74         OIC_LOG_V(ERROR, TAG, "%s Failed to allocate thread!", __func__);
75         *t = NULL;
76         res = OC_THREAD_ALLOCATION_FAILURE;
77     }
78
79    return res;
80 }
81
82 OCThreadResult_t oc_thread_free(oc_thread t)
83 {
84     OCThreadResult_t res = OC_THREAD_INVALID_PARAMETER;
85     oc_thread_internal *threadInfo = (oc_thread_internal*) t;
86     if (threadInfo)
87     {
88         CloseHandle(threadInfo->handle);
89         OICFree(threadInfo);
90         res = OC_THREAD_SUCCESS;
91     }
92     else
93     {
94         OIC_LOG_V(ERROR, TAG, "%s Invalid thread !", __func__);
95     }
96     return res;
97 }
98
99 OCThreadResult_t oc_thread_wait(oc_thread t)
100 {
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)
105     {
106         OIC_LOG(ERROR, TAG, "Failed to join thread");
107         res = OC_THREAD_WAIT_FAILURE;
108     }
109     else
110     {
111         CloseHandle(threadInfo->handle);
112     }
113     return res;
114 }
115
116 oc_mutex oc_mutex_new(void)
117 {
118     oc_mutex retVal = NULL;
119     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
120     if (NULL != mutexInfo)
121     {
122         InitializeCriticalSection(&mutexInfo->mutex);
123         retVal = (oc_mutex)mutexInfo;
124     }
125     else
126     {
127         OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
128     }
129
130     return retVal;
131 }
132
133 bool oc_mutex_free(oc_mutex mutex)
134 {
135     bool bRet = false;
136     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
137     if (mutexInfo)
138     {
139         DeleteCriticalSection(&mutexInfo->mutex);
140         OICFree(mutexInfo);
141         bRet=true;
142     }
143     else
144     {
145         OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
146     }
147
148     return bRet;
149 }
150
151 void oc_mutex_lock(oc_mutex mutex)
152 {
153     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
154     if (mutexInfo)
155     {
156         EnterCriticalSection(&mutexInfo->mutex);
157     }
158     else
159     {
160         OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
161     }
162 }
163
164 void oc_mutex_unlock(oc_mutex mutex)
165 {
166     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
167     if (mutexInfo)
168     {
169         LeaveCriticalSection(&mutexInfo->mutex);
170     }
171     else
172     {
173         OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
174     }
175 }
176
177 oc_cond oc_cond_new(void)
178 {
179     oc_cond retVal = NULL;
180     oc_cond_internal *eventInfo = (oc_cond_internal*) OICMalloc(sizeof(oc_cond_internal));
181     if (NULL != eventInfo)
182     {
183         InitializeConditionVariable(&eventInfo->cond);
184         retVal = (oc_cond) eventInfo;
185     }
186     else
187     {
188         OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
189     }
190
191     return retVal;
192 }
193
194 void oc_cond_free(oc_cond cond)
195 {
196     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
197     if (eventInfo != NULL)
198     {
199         OICFree(cond);
200     }
201     else
202     {
203         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
204     }
205 }
206
207 void oc_cond_signal(oc_cond cond)
208 {
209     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
210     if (eventInfo != NULL)
211     {
212         WakeConditionVariable(&eventInfo->cond);
213     }
214     else
215     {
216         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
217     }
218 }
219
220 void oc_cond_broadcast(oc_cond cond)
221 {
222     oc_cond_internal* eventInfo = (oc_cond_internal*) cond;
223     if (eventInfo != NULL)
224     {
225         WakeAllConditionVariable(&eventInfo->cond);
226     }
227     else
228     {
229         OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
230     }
231 }
232
233 void oc_cond_wait(oc_cond cond, oc_mutex mutex)
234 {
235     oc_cond_wait_for(cond, mutex, 0L);
236 }
237
238 OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseconds)
239 {
240     OCWaitResult_t retVal = OC_WAIT_INVAL;
241
242     oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
243     oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
244
245     if (NULL == mutexInfo)
246     {
247         OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
248         return OC_WAIT_INVAL;
249     }
250
251     if (NULL == eventInfo)
252     {
253         OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
254         return OC_WAIT_INVAL;
255     }
256
257     DWORD milli = 0;
258     if (microseconds > 0)
259     {
260         milli = (DWORD)(microseconds / USECS_PER_MSEC);
261     }
262     else
263     {
264         milli = INFINITE;
265     }
266
267     // Wait for the given time        
268     if (!SleepConditionVariableCS(&eventInfo->cond, &mutexInfo->mutex, milli))
269     {
270         if (GetLastError() == ERROR_TIMEOUT)
271         {
272             retVal = OC_WAIT_TIMEDOUT;
273         }
274         else
275         {
276             OIC_LOG_V(ERROR, TAG, "SleepConditionVariableCS() failed %i", GetLastError());
277             retVal = OC_WAIT_INVAL;
278         }
279     }
280     else
281     {
282         retVal = OC_WAIT_SUCCESS;
283     }
284
285     return retVal;
286 }
287