From: Hauke Mehrtens Date: Tue, 15 Sep 2015 13:47:44 +0000 (+0200) Subject: ca: fix android KitKat 4.4 support X-Git-Tag: 1.2.0+RC1~1051 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a3a8bfd5a5cb887f10a2a2b55a8bf86b7fa0edad;p=platform%2Fupstream%2Fiotivity.git ca: fix android KitKat 4.4 support pthread_condattr_setclock() was added in Android 5.0 and IoTivity used it unconditionally which cause linkage errors on older android versions. With this patch pthread_condattr_setclock() is only accessed when it is available with a weak reference. In addition android < 5.0 provides a private function __pthread_cond_timedwait_relative() which is similar to pthread_cond_timedwait() use that when available instead. This should make IoTivity compatible with KitKat devices. This was tested backported to IoTivity 0.9.2 on an Intel based Android 4.4 Phone and an Arm based Android 5.0 Phone. Change-Id: Ibae6613a4ae52e230b7850ef1a2bad0b5fd530df Signed-off-by: Hauke Mehrtens Reviewed-on: https://gerrit.iotivity.org/gerrit/2565 Tested-by: jenkins-iotivity Reviewed-by: Patrick Lankswert --- diff --git a/resource/csdk/connectivity/common/src/camutex_pthreads.c b/resource/csdk/connectivity/common/src/camutex_pthreads.c index fea62f2..7132f42 100644 --- a/resource/csdk/connectivity/common/src/camutex_pthreads.c +++ b/resource/csdk/connectivity/common/src/camutex_pthreads.c @@ -54,6 +54,22 @@ */ #define TAG PCF("UMUTEX") +#ifdef __ANDROID__ +/** + * Android has pthread_condattr_setclock() only in version >= 5.0, older + * version do have a function called __pthread_cond_timedwait_relative() + * which waits *for* the given timespec, this function is not visible in + * android version >= 5.0 anymore. This is the same way as it is handled in + * QT 5.5.0 in + * http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/thread/qwaitcondition_unix.cpp?h=v5.5.0#n54 + */ +static int camutex_condattr_setclock(pthread_condattr_t *, clockid_t) + __attribute__ ((weakref("pthread_condattr_setclock"))); + +static int camutex_cond_timedwait_relative(pthread_cond_t*, pthread_mutex_t*, const struct timespec*) + __attribute__ ((weakref("__pthread_cond_timedwait_relative"))); +#endif /* __ANDROID__ */ + static const uint64_t USECS_PER_SEC = 1000000; static const uint64_t NANOSECS_PER_USECS = 1000; static const uint64_t NANOSECS_PER_SEC = 1000000000L; @@ -206,17 +222,23 @@ ca_cond ca_cond_new(void) } #if defined(__ANDROID__) || _POSIX_TIMERS > 0 - ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC); - - if(0 != ret) +#ifdef __ANDROID__ + if (camutex_condattr_setclock) { + ret = camutex_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC); +#else { - OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!", - __func__, ret); - pthread_condattr_destroy(&(eventInfo->condattr)); - OICFree(eventInfo); - return retVal; + ret = pthread_condattr_setclock(&(eventInfo->condattr), CLOCK_MONOTONIC); +#endif /* __ANDROID__ */ + if(0 != ret) + { + OIC_LOG_V(ERROR, TAG, "%s: Failed to set condition variable clock %d!", + __func__, ret); + pthread_condattr_destroy(&(eventInfo->condattr)); + OICFree(eventInfo); + return retVal; + } } -#endif +#endif /* defined(__ANDROID__) || _POSIX_TIMERS > 0 */ ret = pthread_cond_init(&(eventInfo->cond), &(eventInfo->condattr)); if (0 == ret) { @@ -342,11 +364,25 @@ CAWaitResult_t ca_cond_wait_for(ca_cond cond, ca_mutex mutex, uint64_t microseco if (microseconds > 0) { - struct timespec abstime = ca_get_current_time(); - ca_add_microseconds_to_timespec(&abstime, microseconds); + int ret; + struct timespec abstime; + +#ifdef __ANDROID__ + if (camutex_cond_timedwait_relative) { + abstime.tv_sec = microseconds / USECS_PER_SEC; + abstime.tv_nsec = (microseconds % USECS_PER_SEC) * NANOSECS_PER_USECS; + //Wait for the given time + ret = camutex_cond_timedwait_relative(&(eventInfo->cond), &(mutexInfo->mutex), &abstime); + } else +#endif + { + abstime = ca_get_current_time(); + ca_add_microseconds_to_timespec(&abstime, microseconds); + + //Wait for the given time + ret = pthread_cond_timedwait(&(eventInfo->cond), &(mutexInfo->mutex), &abstime); + } - //Wait for the given time - int ret = pthread_cond_timedwait(&(eventInfo->cond), &(mutexInfo->mutex), &abstime); switch (ret) { case 0: