1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //*********************************************************************
26 * This file provides APIs related to mutex and semaphores.
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
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
53 * Logging tag for module name
55 #define TAG PCF("UMUTEX")
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;
61 typedef struct _tagMutexInfo_t {
62 pthread_mutex_t mutex;
65 typedef struct _tagEventInfo_t {
67 pthread_condattr_t condattr;
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);
79 retVal = (ca_mutex) mutexInfo;
81 OIC_LOG_V(ERROR, TAG, "%s Failed to initialize mutex !", __func__);
89 bool ca_mutex_free(ca_mutex mutex) {
92 ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
94 int ret = pthread_mutex_destroy(&mutexInfo->mutex);
99 OIC_LOG_V(ERROR, TAG, "%s Failed to free mutex !", __func__);
102 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
108 void ca_mutex_lock(ca_mutex mutex) {
109 ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
111 int ret = pthread_mutex_lock(&mutexInfo->mutex);
115 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
120 bool ca_mutex_trylock(ca_mutex mutex) {
122 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
128 ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
130 int result = pthread_mutex_trylock(&mutexInfo->mutex);
138 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
148 void ca_mutex_unlock(ca_mutex mutex) {
149 ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
151 int ret = pthread_mutex_unlock(&mutexInfo->mutex);
155 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
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));
167 OIC_LOG_V(ERROR, TAG,
168 "%s: Failed to initialize condition variable attribute %d!",
173 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
174 ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
178 OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!",
183 ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr));
185 retVal = (ca_cond) eventInfo;
187 OIC_LOG_V(ERROR, TAG,
188 "%s: Failed to initialize condition variable %d!", __func__,
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) {
205 OIC_LOG_V(ERROR, TAG,
206 "%s: Failed to destroy condition variable %d, %d", __func__,
210 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
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));
219 OIC_LOG_V(ERROR, TAG, "%s: Failed to signal condition variable",
223 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
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));
232 OIC_LOG_V(ERROR, TAG, "%s: failed to signal condition variable",
236 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
240 void ca_cond_wait(ca_cond cond, ca_mutex mutex) {
241 ca_cond_wait_for(cond, mutex, 0L);
244 struct timespec ca_get_current_time() {
245 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
247 clock_gettime(CLOCK_MONOTONIC, &ts);
251 gettimeofday(&tv, NULL);
253 TIMEVAL_TO_TIMESPEC(&tv, &ts);
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;
265 ts->tv_nsec = (totalNs) % NANOSECS_PER_SEC;
266 ts->tv_sec += secPart + secOfNs;
269 CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex,
270 uint64_t microseconds) {
271 CAWaitResult_t retVal = CA_WAIT_INVAL;
273 ca_cond_internal *eventInfo = (ca_cond_internal*) cond;
274 ca_mutex_internal *mutexInfo = (ca_mutex_internal*) mutex;
276 if (NULL == mutexInfo) {
277 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
278 return CA_WAIT_INVAL;
281 if (NULL == eventInfo) {
282 OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
283 return CA_WAIT_INVAL;
286 if (microseconds > 0) {
287 struct timespec abstime = ca_get_current_time();
288 ca_add_microseconds_to_timespec(&abstime, microseconds);
290 //Wait for the given time
291 int ret = pthread_cond_timedwait(&(eventInfo->cond),
292 &(mutexInfo->mutex), &abstime);
296 retVal = CA_WAIT_SUCCESS;
299 retVal = CA_WAIT_TIMEDOUT;
302 OIC_LOG_V(ERROR, TAG, "%s: condition, mutex, or abstime is Invalid",
304 retVal = CA_WAIT_INVAL;
307 OIC_LOG_V(ERROR, TAG, "%s: pthread_cond_timedwait returned %d",
309 retVal = CA_WAIT_INVAL;
314 int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
315 retVal = ret == 0 ? CA_WAIT_SUCCESS : CA_WAIT_INVAL;