#include "eina_inlist.h"
#endif
-/* To be removed once we can use _eina_time_get() here*/
-#ifndef _WIN32
-# include <time.h>
-# include <sys/time.h>
-#else
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# undef WIN32_LEAN_AND_MEAN
-#endif /* _WIN2 */
-/* End of to be removed */
+/* For cond_timedwait */
+#include <time.h>
+#include <sys/time.h>
typedef struct _Eina_Lock Eina_Lock;
typedef struct _Eina_RWLock Eina_RWLock;
{
Eina_Lock *lock; /**< The lock for this condition */
pthread_cond_t condition; /**< The condition variable */
+ clockid_t clkid; /**< The attached clock for timedwait */
};
struct _Eina_RWLock
static inline Eina_Bool
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
{
+ pthread_condattr_t attr;
+
#ifdef EINA_HAVE_DEBUG_THREADS
assert(mutex != NULL);
if (!_eina_threads_activated)
memset(cond, 0, sizeof (Eina_Condition));
#endif
+ pthread_condattr_init(&attr);
+ cond->clkid = (clockid_t) 0;
+
+ /* We try here to chose the best clock for cond_timedwait */
+#if defined(CLOCK_MONOTONIC_RAW)
+ if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC_RAW))
+ cond->clkid = CLOCK_MONOTONIC_RAW;
+#endif
+#if defined(CLOCK_MONOTONIC)
+ if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
+ cond->clkid = CLOCK_MONOTONIC;
+#endif
+#if defined(CLOCK_REALTIME)
+ if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_REALTIME))
+ cond->clkid = CLOCK_REALTIME;
+#endif
+
cond->lock = mutex;
- if (pthread_cond_init(&cond->condition, NULL) != 0)
+ if (pthread_cond_init(&cond->condition, cond->clkid ? &attr : NULL) != 0)
{
+ pthread_condattr_destroy(&attr);
#ifdef EINA_HAVE_DEBUG_THREADS
if (errno == EBUSY)
printf("eina_condition_new on already initialized Eina_Condition\n");
return EINA_FALSE;
}
+ pthread_condattr_destroy(&attr);
return EINA_TRUE;
}
static inline Eina_Bool
eina_condition_timedwait(Eina_Condition *cond, double t)
{
- struct timespec tv;
- Eina_Bool r;
+ struct timespec ts;
time_t sec;
long nsec;
+ int err;
if (t < 0)
{
return EINA_FALSE;
}
+ if (cond->clkid)
+ {
+ if (clock_gettime(cond->clkid, &ts) != 0)
+ return EINA_FALSE;
+ }
+ else
+ {
+ /* Obsolete - this probably will never happen */
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) != 0)
+ return EINA_FALSE;
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000L;
+ }
+
#ifdef EINA_HAVE_DEBUG_THREADS
assert(_eina_threads_activated);
assert(cond->lock != NULL);
pthread_mutex_unlock(&_eina_tracking_lock);
#endif
-/* To be removed once we can use _eina_time_get() here*/
-#ifndef _WIN32
-# if defined(CLOCK_PROCESS_CPUTIME_ID)
- if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv))
- return EINA_FALSE;
-# endif
-# if defined(CLOCK_PROF)
- if (!clock_gettime(CLOCK_PROF, &tv))
- return EINA_FALSE;
-# endif
-# if defined(CLOCK_REALTIME)
- if (!clock_gettime(CLOCK_REALTIME, &tv))
- return EINA_FALSE;
-# endif
-#endif
-
- struct timeval tp;
-
- if (gettimeofday(&tp, NULL))
- return EINA_FALSE;
-
- tv.tv_sec = tp.tv_sec;
- tv.tv_nsec = tp.tv_usec * 1000L;
-/* End of to be removed */
-
sec = (time_t)t;
nsec = (t - (double) sec) * 1000000000L;
- tv.tv_sec += sec;
- tv.tv_nsec += nsec;
- if (tv.tv_nsec > 1000000000L)
+ ts.tv_sec += sec;
+ ts.tv_nsec += nsec;
+ if (ts.tv_nsec > 1000000000L)
{
- tv.tv_sec++;
- tv.tv_nsec -= 1000000000L;
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
}
- r = pthread_cond_timedwait(&(cond->condition),
- &(cond->lock->mutex),
- &tv) == 0 ?
- EINA_TRUE : EINA_FALSE;
+ err = pthread_cond_timedwait(&(cond->condition),
+ &(cond->lock->mutex),
+ &ts);
#ifdef EINA_HAVE_DEBUG_THREADS
pthread_mutex_lock(&_eina_tracking_lock);
pthread_mutex_unlock(&_eina_tracking_lock);
#endif
- return r;
+ return (!err) ? EINA_TRUE : EINA_FALSE;
}
static inline Eina_Bool
START_TEST(eina_test_rwlock)
{
+ struct timespec ts, ts2;
+ long delay;
+
fail_if(!eina_init());
fail_if(!eina_rwlock_new(&mutex));
fail_if(counter != 7200);
fail_if(eina_rwlock_release(&mutex) != EINA_LOCK_SUCCEED);
- eina_condition_timedwait(&cond, 0.01);
+#ifndef _WIN32
+ fail_if(eina_lock_take(&mtcond) != EINA_LOCK_SUCCEED);
+ clock_gettime(CLOCK_REALTIME, &ts);
+ eina_condition_timedwait(&cond, 0.050);
+ clock_gettime(CLOCK_REALTIME, &ts2);
+ delay = (ts2.tv_sec - ts.tv_sec) * 1000L + (ts2.tv_nsec - ts.tv_nsec) / 1000000L;
+ fail_if(delay < 50);
+ fail_if(delay > 200);
+ fail_if(eina_lock_release(&mtcond) != EINA_LOCK_SUCCEED);
+#endif
+
eina_thread_join(thread);
eina_condition_free(&cond);