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
39 #include "iotivity_config.h"
40 #include "iotivity_debug.h"
54 #ifdef HAVE_SYS_TIME_H
60 #include <oic_malloc.h>
65 * Logging tag for module name
67 #define TAG PCF("UMUTEX")
71 * Android has pthread_condattr_setclock() only in version >= 5.0, older
72 * version do have a function called __pthread_cond_timedwait_relative()
73 * which waits *for* the given timespec, this function is not visible in
74 * android version >= 5.0 anymore. This is the same way as it is handled in
76 * http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/thread/qwaitcondition_unix.cpp?h=v5.5.0#n54
78 static int camutex_condattr_setclock(pthread_condattr_t *, clockid_t)
79 __attribute__ ((weakref("pthread_condattr_setclock")));
81 static int camutex_cond_timedwait_relative(pthread_cond_t*, pthread_mutex_t*, const struct timespec*)
82 __attribute__ ((weakref("__pthread_cond_timedwait_relative")));
83 #endif /* __ANDROID__ */
85 static const uint64_t USECS_PER_SEC = 1000000;
86 static const uint64_t NANOSECS_PER_USECS = 1000;
87 static const uint64_t NANOSECS_PER_SEC = 1000000000L;
89 typedef struct _tagMutexInfo_t
91 pthread_mutex_t mutex;
94 * Catch some of the incorrect mutex usage, by tracking the mutex owner,
99 uint32_t recursionCount;
103 typedef struct _tagEventInfo_t
106 pthread_condattr_t condattr;
109 typedef struct _tagThreadInfo_t
112 pthread_attr_t threadattr;
113 } oc_thread_internal;
116 static pthread_t oc_get_current_thread_id()
118 pthread_t id = pthread_self();
119 assert(OC_INVALID_THREAD_ID != id);
125 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg)
127 OCThreadResult_t oc_thread_new(oc_thread *t, void *(*start_routine)(void *), void *arg,
128 const char *task_name, int stack_size)
131 OCThreadResult_t res = OC_THREAD_SUCCESS;
132 oc_thread_internal *threadInfo = (oc_thread_internal*)OICMalloc(sizeof(oc_thread_internal));
133 if (NULL != threadInfo)
137 pthread_attr_init(&attr);
138 struct sched_param prio;
139 prio.sched_priority = 90;
140 (void)pthread_attr_setschedparam(&attr, &prio);
141 (void)pthread_attr_setstacksize(&attr, stack_size);
142 int result = pthread_create(&threadInfo->thread, &attr, start_routine, arg);
143 pthread_setname_np(threadInfo->thread, task_name);
145 int result = pthread_create(&threadInfo->thread, NULL, start_routine, arg);
149 res = OC_THREAD_CREATE_FAILURE;
152 OIC_LOG_V(ERROR, TAG, "%s: pthread_create failed", __func__);
156 *t = (oc_thread)threadInfo;
161 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate thread!", __func__);
163 res = OC_THREAD_ALLOCATION_FAILURE;
168 OCThreadResult_t oc_thread_free(oc_thread t)
170 OCThreadResult_t res = OC_THREAD_SUCCESS;
171 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
178 OIC_LOG_V(ERROR, TAG, "%s Invalid thread !", __func__);
179 res = OC_THREAD_INVALID;
184 OCThreadResult_t oc_thread_wait(oc_thread t)
186 OCThreadResult_t res = OC_THREAD_SUCCESS;
187 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
188 int joinres = pthread_join(threadInfo->thread, NULL);
191 OIC_LOG_V(ERROR, TAG, "Failed to join thread with error %d", joinres);
192 res = OC_THREAD_WAIT_FAILURE;
198 OCThreadResult_t oc_thread_detach(oc_thread t)
200 OCThreadResult_t res = OC_THREAD_SUCCESS;
202 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
203 int detachres = pthread_detach(threadInfo->thread);
206 OIC_LOG_V(ERROR, TAG, "Failed to detach thread with error %d", detachres);
207 res = OC_THREAD_DETACH_FAILURE;
214 OCThreadResult_t oc_thread_cancel(oc_thread t)
216 OCThreadResult_t res = OC_THREAD_SUCCESS;
217 oc_thread_internal *threadInfo = (oc_thread_internal*) t;
218 int ret = pthread_cancel(threadInfo->thread);
221 OIC_LOG_V(ERROR, TAG, "Failed to cancel thread with error %d", ret);
222 res = OC_THREAD_CANCEL_FAILURE;
229 oc_mutex oc_mutex_new(void)
231 oc_mutex retVal = NULL;
232 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
233 if (NULL != mutexInfo)
235 // create the mutex with the attributes set
236 int ret=pthread_mutex_init(&(mutexInfo->mutex), PTHREAD_MUTEX_DEFAULT);
240 mutexInfo->owner = OC_INVALID_THREAD_ID;
241 mutexInfo->recursionCount = 0;
243 retVal = (oc_mutex) mutexInfo;
247 OIC_LOG_V(ERROR, TAG, "%s Failed to initialize mutex !", __func__);
253 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
259 oc_mutex oc_mutex_new_recursive(void)
261 oc_mutex retVal = NULL;
264 // Allocate new mutex.
265 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) OICMalloc(sizeof(oc_mutex_internal));
266 if (NULL == mutexInfo)
268 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate mutex!", __func__);
272 // Set up the mutex attributes.
273 pthread_mutexattr_t ma;
274 ret = pthread_mutexattr_init(&ma);
277 OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutexattr_init - error %d!",
282 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
285 OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutexattr_settype - error %d!",
287 pthread_mutexattr_destroy(&ma);
291 // Initialize the mutex and destroy the attributes.
292 ret = pthread_mutex_init(&(mutexInfo->mutex), &ma);
293 OC_VERIFY(0 == pthread_mutexattr_destroy(&ma));
296 OIC_LOG_V(ERROR, TAG, "%s Failed in pthread_mutex_init - error %d!",
302 mutexInfo->owner = OC_INVALID_THREAD_ID;
303 mutexInfo->recursionCount = 0;
309 retVal = (oc_mutex) mutexInfo;
319 bool oc_mutex_free(oc_mutex mutex)
322 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
325 int ret = pthread_mutex_destroy(&mutexInfo->mutex);
333 OIC_LOG_V(ERROR, TAG, "%s Failed to free mutex !", __func__);
338 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
344 void oc_mutex_lock(oc_mutex mutex)
346 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
349 int ret = pthread_mutex_lock(&mutexInfo->mutex);
352 OIC_LOG_V(ERROR, TAG, "Pthread Mutex lock failed: %d", ret);
358 * Updating the recursionCount and owner fields must be performed
359 * while owning the lock, to solve race conditions with other
360 * threads using the same lock.
362 if (mutexInfo->recursionCount != 0)
364 oc_mutex_assert_owner(mutex, true);
368 mutexInfo->owner = oc_get_current_thread_id();
371 mutexInfo->recursionCount++;
376 OIC_LOG_V(ERROR, TAG, "%s Invalid mutex !", __func__);
380 void oc_mutex_unlock(oc_mutex mutex)
382 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
385 #if defined(__TIZENRT__)
386 if (mutexInfo->mutex.pid == 0)
393 oc_mutex_assert_owner(mutex, true);
396 * Updating the recursionCount and owner fields must be performed
397 * while owning the lock, to solve race conditions with other
398 * threads using the same lock.
400 mutexInfo->recursionCount--;
402 if (mutexInfo->recursionCount == 0)
404 mutexInfo->owner = OC_INVALID_THREAD_ID;
408 int ret = pthread_mutex_unlock(&mutexInfo->mutex);
411 OIC_LOG_V(ERROR, TAG, "Pthread Mutex unlock failed: %d", ret);
417 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex !", __func__);
421 void oc_mutex_assert_owner(const oc_mutex mutex, bool currentThreadIsOwner)
425 (void)currentThreadIsOwner;
427 assert(NULL != mutex);
428 const oc_mutex_internal *mutexInfo = (const oc_mutex_internal*) mutex;
430 pthread_t currentThreadID = oc_get_current_thread_id();
431 if (currentThreadIsOwner)
433 assert(pthread_equal(mutexInfo->owner, currentThreadID));
434 assert(mutexInfo->recursionCount != 0);
438 assert(!pthread_equal(mutexInfo->owner, currentThreadID));
443 oc_cond oc_cond_new(void)
445 oc_cond retVal = NULL;
446 oc_cond_internal *eventInfo = (oc_cond_internal*) OICMalloc(sizeof(oc_cond_internal));
447 if (NULL != eventInfo)
449 int ret = pthread_condattr_init(&(eventInfo->condattr));
452 OIC_LOG_V(ERROR, TAG, "%s: Failed to initialize condition variable attribute %d!",
458 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
460 if (camutex_condattr_setclock)
462 ret = camutex_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
465 ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC);
466 #endif /* __ANDROID__ */
469 OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!",
471 pthread_condattr_destroy(&(eventInfo->condattr));
476 #endif /* defined(__ANDROID__) || _POSIX_TIMERS > 0 */
477 ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr));
480 retVal = (oc_cond) eventInfo;
484 OIC_LOG_V(ERROR, TAG, "%s: Failed to initialize condition variable %d!", __func__, ret);
485 pthread_condattr_destroy(&(eventInfo->condattr));
491 OIC_LOG_V(ERROR, TAG, "%s: Failed to allocate condition variable!", __func__);
497 void oc_cond_free(oc_cond cond)
499 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
500 if (eventInfo != NULL)
502 int ret = pthread_cond_destroy(&(eventInfo->cond));
503 int ret2 = pthread_condattr_destroy(&(eventInfo->condattr));
504 if (0 == ret && 0 == ret2)
510 OIC_LOG_V(ERROR, TAG, "%s: Failed to destroy condition variable %d, %d",
511 __func__, ret, ret2);
516 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
520 void oc_cond_signal(oc_cond cond)
522 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
523 if (eventInfo != NULL)
525 int ret = pthread_cond_signal(&(eventInfo->cond));
528 OIC_LOG_V(ERROR, TAG, "%s: Failed to signal condition variable", __func__);
533 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
537 void oc_cond_broadcast(oc_cond cond)
539 oc_cond_internal* eventInfo = (oc_cond_internal*) cond;
540 if (eventInfo != NULL)
542 int ret = pthread_cond_broadcast(&(eventInfo->cond));
545 OIC_LOG_V(ERROR, TAG, "%s: failed to signal condition variable", __func__);
550 OIC_LOG_V(ERROR, TAG, "%s: Invalid parameter", __func__);
554 void oc_cond_wait(oc_cond cond, oc_mutex mutex)
556 oc_cond_wait_for(cond, mutex, 0L);
559 #ifndef TIMEVAL_TO_TIMESPEC
560 #define TIMEVAL_TO_TIMESPEC(tv, ts) { \
561 (ts)->tv_sec = (tv)->tv_sec; \
562 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
566 struct timespec oc_get_current_time()
568 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
570 clock_gettime(CLOCK_MONOTONIC, &ts);
574 gettimeofday(&tv, NULL);
576 TIMEVAL_TO_TIMESPEC(&tv, &ts);
581 void oc_add_microseconds_to_timespec(struct timespec* ts, uint64_t microseconds)
583 time_t secPart = microseconds/USECS_PER_SEC;
584 uint64_t nsecPart = (microseconds % USECS_PER_SEC) * NANOSECS_PER_USECS;
585 uint64_t totalNs = ts->tv_nsec + nsecPart;
586 time_t secOfNs = totalNs/NANOSECS_PER_SEC;
588 ts->tv_nsec = (totalNs)% NANOSECS_PER_SEC;
589 ts->tv_sec += secPart + secOfNs;
592 OCWaitResult_t oc_cond_wait_for(oc_cond cond, oc_mutex mutex, uint64_t microseconds)
594 OCWaitResult_t retVal = OC_WAIT_INVAL;
596 oc_cond_internal *eventInfo = (oc_cond_internal*) cond;
597 oc_mutex_internal *mutexInfo = (oc_mutex_internal*) mutex;
599 if (NULL == mutexInfo)
601 OIC_LOG_V(ERROR, TAG, "%s: Invalid mutex", __func__);
602 return OC_WAIT_INVAL;
605 if (NULL == eventInfo)
607 OIC_LOG_V(ERROR, TAG, "%s: Invalid condition", __func__);
608 return OC_WAIT_INVAL;
611 if (microseconds > 0)
614 struct timespec abstime = { .tv_sec = 0 };
617 if (camutex_cond_timedwait_relative)
619 abstime.tv_sec = microseconds / USECS_PER_SEC;
620 abstime.tv_nsec = (microseconds % USECS_PER_SEC) * NANOSECS_PER_USECS;
621 //Wait for the given time
622 ret = camutex_cond_timedwait_relative(&(eventInfo->cond), &(mutexInfo->mutex), &abstime);
626 abstime = oc_get_current_time();
627 oc_add_microseconds_to_timespec(&abstime, microseconds);
630 // Recursively-acquired locks are not supported for use with condition variables.
631 oc_mutex_assert_owner(mutex, true);
632 assert(mutexInfo->recursionCount == 1);
633 mutexInfo->recursionCount = 0;
634 mutexInfo->owner = OC_INVALID_THREAD_ID;
637 // Wait for the given time
638 ret = pthread_cond_timedwait(&(eventInfo->cond), &(mutexInfo->mutex), &abstime);
641 oc_mutex_assert_owner(mutex, false);
642 assert(mutexInfo->recursionCount == 0);
643 mutexInfo->recursionCount = 1;
644 mutexInfo->owner = oc_get_current_thread_id();
652 retVal = OC_WAIT_SUCCESS;
655 retVal = OC_WAIT_TIMEDOUT;
658 OIC_LOG_V(ERROR, TAG, "%s: condition, mutex, or abstime is Invalid", __func__);
659 retVal = OC_WAIT_INVAL;
662 OIC_LOG_V(ERROR, TAG, "%s: pthread_cond_timedwait returned %d", __func__, retVal);
663 retVal = OC_WAIT_INVAL;
670 // Recursively-acquired locks are not supported for use with condition variables.
671 oc_mutex_assert_owner(mutex, true);
672 assert(mutexInfo->recursionCount == 1);
673 mutexInfo->recursionCount = 0;
674 mutexInfo->owner = OC_INVALID_THREAD_ID;
679 // The conditional variable wait API used will atomically release the mutex, but the
680 // best we can do here is to just clear the owner info before the API is called.
681 mutexInfo->owner = OC_INVALID_THREAD_ID;
683 int ret = pthread_cond_wait(&eventInfo->cond, &mutexInfo->mutex);
684 retVal = (ret == 0) ? OC_WAIT_SUCCESS : OC_WAIT_INVAL;
687 oc_mutex_assert_owner(mutex, false);
688 assert(mutexInfo->recursionCount == 0);
689 mutexInfo->recursionCount = 1;
690 mutexInfo->owner = oc_get_current_thread_id();