Update the folder structure for Enrollee implmentation.
[platform/upstream/iotivity.git] / service / easy-setup / sdk / mediator / src / camutex_pthreads.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 //
21 //
22 //*********************************************************************
23
24 /**
25  * @file
26  * This file provides APIs related to mutex and semaphores.
27  */
28
29 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
30 // causes header files to expose definitions
31 // corresponding to the POSIX.1b, Real-time extensions
32 // (IEEE Std 1003.1b-1993) specification
33 //
34 // For this specific file, see use of clock_gettime and PTHREAD_MUTEX_DEFAULT
35 #ifndef _POSIX_C_SOURCE
36 #define _POSIX_C_SOURCE 200809L
37 #endif
38
39 #include <string.h>
40 #include <pthread.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <time.h>
44 #include <sys/time.h>
45 #include <assert.h>
46 #include <ocmalloc.h>
47
48 #include "camutex.h"
49 #include "logger.h"
50
51 /**
52  * TAG
53  * Logging tag for module name
54  */
55 #define TAG PCF("UMUTEX")
56
57 static const uint64_t USECS_PER_SEC = 1000000;
58 static const uint64_t NANOSECS_PER_USECS = 1000;
59 static const uint64_t NANOSECS_PER_SEC = 1000000000L;
60
61 typedef struct _tagMutexInfo_t {
62         pthread_mutex_t mutex;
63 } ca_mutex_internal;
64
65 typedef struct _tagEventInfo_t {
66         pthread_cond_t cond;
67         pthread_condattr_t condattr;
68 } ca_cond_internal;
69
70 ca_mutex ca_mutex_new(void) {
71         ca_mutex retVal = NULL;
72         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) OICMalloc(
73                         sizeof(ca_mutex_internal));
74         if (NULL != mutexInfo) {
75                 // create the mutex with the attributes set
76                 int ret = pthread_mutex_init(&(mutexInfo->mutex),
77                                 PTHREAD_MUTEX_DEFAULT);
78                 if (0 == ret) {
79                         retVal = (ca_mutex) mutexInfo;
80                 } else {
81                         OIC_LOG_V(ERROR, TAG, "%s Failed to initialize mutex !", __func__);
82                         OICFree(mutexInfo);
83                 }
84         }
85
86         return retVal;
87 }
88
89 bool ca_mutex_free(ca_mutex mutex) {
90         bool bRet = false;
91
92         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
93         if (mutexInfo) {
94                 int ret = pthread_mutex_destroy(&mutexInfo->mutex);
95                 if (0 == ret) {
96                         OICFree(mutexInfo);
97                         bRet = true;
98                 } else {
99                         OIC_LOG_V(ERROR, TAG, "%s Failed to free mutex !", __func__);
100                 }
101         } else {
102                 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
103         }
104
105         return bRet;
106 }
107
108 void ca_mutex_lock(ca_mutex mutex) {
109         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
110         if (mutexInfo) {
111                 int ret = pthread_mutex_lock(&mutexInfo->mutex);
112                 assert(0 == ret);
113                 (void) ret;
114         } else {
115                 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
116                 return;
117         }
118 }
119
120 bool ca_mutex_trylock(ca_mutex mutex) {
121         if (NULL == mutex) {
122                 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
123                 return false;
124         }
125
126         bool bRet = false;
127
128         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
129
130         int result = pthread_mutex_trylock(&mutexInfo->mutex);
131
132         switch (result) {
133         case 0:
134                 // Success
135                 bRet = true;
136                 break;
137         case EINVAL:
138                 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
139                 break;
140         case EBUSY:
141         default:
142                 break;
143         }
144
145         return bRet;
146 }
147
148 void ca_mutex_unlock(ca_mutex mutex) {
149         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
150         if (mutexInfo) {
151                 int ret = pthread_mutex_unlock(&mutexInfo->mutex);
152                 assert(0 == ret);
153                 (void) ret;
154         } else {
155                 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
156                 return;
157         }
158 }
159
160 ca_cond ca_cond_new(void) {
161         ca_cond retVal = NULL;
162         ca_cond_internal *eventInfo = (ca_cond_internal*) OICMalloc(
163                         sizeof(ca_cond_internal));
164         if (NULL != eventInfo) {
165                 int ret = pthread_condattr_init(&(eventInfo->condattr));
166                 if (0 != ret) {
167                         OIC_LOG_V(ERROR, TAG,
168                                         "%s: Failed to initialize condition variable attribute %d!",
169                                         __func__, ret);
170                         return retVal;
171                 }
172
173 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
174                 ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
175
176                 if(0 != ret)
177                 {
178                         OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!",
179                                         __func__, ret);
180                         return retVal;
181                 }
182 #endif
183                 ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr));
184                 if (0 == ret) {
185                         retVal = (ca_cond) eventInfo;
186                 } else {
187                         OIC_LOG_V(ERROR, TAG,
188                                         "%s: Failed to initialize condition variable %d!", __func__,
189                                         ret);
190                         OICFree(eventInfo);
191                 }
192         }
193
194         return retVal;
195 }
196
197 void ca_cond_free(ca_cond cond) {
198         ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
199         if (eventInfo != NULL) {
200                 int ret = pthread_cond_destroy(&(eventInfo->cond));
201                 int ret2 = pthread_condattr_destroy(&(eventInfo->condattr));
202                 if (0 == ret && 0 == ret2) {
203                         OICFree(cond);
204                 } else {
205                         OIC_LOG_V(ERROR, TAG,
206                                         "%s: Failed to destroy condition variable %d, %d", __func__,
207                                         ret, ret2);
208                 }
209         } else {
210                 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
211         }
212 }
213
214 void ca_cond_signal(ca_cond cond) {
215         ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
216         if (eventInfo != NULL) {
217                 int ret = pthread_cond_signal(&(eventInfo->cond));
218                 if (0 != ret) {
219                         OIC_LOG_V(ERROR, TAG, "%s: Failed to signal condition variable",
220                                         __func__);
221                 }
222         } else {
223                 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
224         }
225 }
226
227 void ca_cond_broadcast(ca_cond cond) {
228         ca_cond_internal* eventInfo = (ca_cond_internal*) cond;
229         if (eventInfo != NULL) {
230                 int ret = pthread_cond_broadcast(&(eventInfo->cond));
231                 if (0 != ret) {
232                         OIC_LOG_V(ERROR, TAG, "%s: failed to signal condition variable",
233                                         __func__);
234                 }
235         } else {
236                 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
237         }
238 }
239
240 void ca_cond_wait(ca_cond cond, ca_mutex mutex) {
241         ca_cond_wait_for(cond, mutex, 0L);
242 }
243
244 struct timespec ca_get_current_time() {
245 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
246         struct timespec ts;
247         clock_gettime(CLOCK_MONOTONIC, &ts);
248         return ts;
249 #else
250         struct timeval tv;
251         gettimeofday(&tv, NULL);
252         struct timespec ts;
253         TIMEVAL_TO_TIMESPEC(&tv, &ts);
254         return ts;
255 #endif
256 }
257
258 void ca_add_microseconds_to_timespec(struct timespec* ts,
259                 uint64_t microseconds) {
260         time_t secPart = microseconds / USECS_PER_SEC;
261         uint64_t nsecPart = (microseconds % USECS_PER_SEC) * NANOSECS_PER_USECS;
262         uint64_t totalNs = ts->tv_nsec + nsecPart;
263         time_t secOfNs = totalNs / NANOSECS_PER_SEC;
264
265         ts->tv_nsec = (totalNs) % NANOSECS_PER_SEC;
266         ts->tv_sec += secPart + secOfNs;
267 }
268
269 CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex,
270                 uint64_t microseconds) {
271         CAWaitResult_t retVal = CA_WAIT_INVAL;
272
273         ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
274         ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
275
276         if (NULL == mutexInfo) {
277                 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
278                 return CA_WAIT_INVAL;
279         }
280
281         if (NULL == eventInfo) {
282                 OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
283                 return CA_WAIT_INVAL;
284         }
285
286         if (microseconds > 0) {
287                 struct timespec abstime = ca_get_current_time();
288                 ca_add_microseconds_to_timespec(&abstime, microseconds);
289
290                 //Wait for the given time
291                 int ret = pthread_cond_timedwait(&(eventInfo->cond),
292                                 &(mutexInfo->mutex), &abstime);
293                 switch (ret) {
294                 case 0:
295                         // Success
296                         retVal = CA_WAIT_SUCCESS;
297                         break;
298                 case ETIMEDOUT:
299                         retVal = CA_WAIT_TIMEDOUT;
300                         break;
301                 case EINVAL:
302                         OIC_LOG_V(ERROR, TAG, "%s: condition, mutex, or abstime is Invalid",
303                                         __func__);
304                         retVal = CA_WAIT_INVAL;
305                         break;
306                 default:
307                         OIC_LOG_V(ERROR, TAG, "%s: pthread_cond_timedwait returned %d",
308                                         __func__, retVal);
309                         retVal = CA_WAIT_INVAL;
310                         break;
311                 }
312         } else {
313                 // Wait forever
314                 int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
315                 retVal = ret == 0 ? CA_WAIT_SUCCESS : CA_WAIT_INVAL;
316         }
317
318         return retVal;
319 }
320