static void _dbus_pthread_mutex_lock (DBusMutex *mutex) { DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); pthread_t self = pthread_self (); /* If the count is > 0 then someone had the lock, maybe us. If it is * 0, then it might immediately change right after we read it, * but it will be changed by another thread; i.e. if we read 0, * we assume that this thread doesn't have the lock. * * Not 100% sure this is safe, but ... seems like it should be. */ if (pmutex->count == 0) { /* We know we don't have the lock; someone may have the lock. */ PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&pmutex->lock)); /* We now have the lock. Count must be 0 since it must be 0 when * the lock is released by another thread, and we just now got * the lock. */ _dbus_assert (pmutex->count == 0); pmutex->holder = self; pmutex->count = 1; } else { /* We know someone had the lock, possibly us. Thus * pmutex->holder is not pointing to junk, though it may not be * the lock holder anymore if the lock holder is not us. If the * lock holder is us, then we definitely have the lock. */ if (pthread_equal (pmutex->holder, self)) { /* We already have the lock. */ _dbus_assert (pmutex->count > 0); } else { /* Wait for the lock */ PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&pmutex->lock)); pmutex->holder = self; _dbus_assert (pmutex->count == 0); } pmutex->count += 1; } }
static DBusMutex* _dbus_pthread_mutex_new (void) { DBusMutexPThread *pmutex; int result; pmutex = dbus_new (DBusMutexPThread, 1); if (pmutex == NULL) return NULL; result = pthread_mutex_init (&pmutex->lock, NULL); if (result == ENOMEM || result == EAGAIN) { dbus_free (pmutex); return NULL; } else { PTHREAD_CHECK ("pthread_mutex_init", result); } /* Only written */ pmutex->count = 0; /* There's no portable way to have a "null" pthread afaik so we * can't set pmutex->holder to anything sensible. We only access it * once the lock is held (which means we've set it). */ return DBUS_MUTEX (pmutex); }
DBusRMutex * _dbus_platform_rmutex_new (void) { DBusRMutex *pmutex; pthread_mutexattr_t mutexattr; int result; pmutex = dbus_new (DBusRMutex, 1); if (pmutex == NULL) return NULL; pthread_mutexattr_init (&mutexattr); pthread_mutexattr_settype (&mutexattr, PTHREAD_MUTEX_RECURSIVE); result = pthread_mutex_init (&pmutex->lock, &mutexattr); pthread_mutexattr_destroy (&mutexattr); if (result == ENOMEM || result == EAGAIN) { dbus_free (pmutex); return NULL; } else { PTHREAD_CHECK ("pthread_mutex_init", result); } return pmutex; }
static void _dbus_pthread_condvar_wake_one (DBusCondVar *cond) { DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&pcond->cond)); }
static void _dbus_pthread_condvar_wake_all (DBusCondVar *cond) { DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); PTHREAD_CHECK ("pthread_cond_broadcast", pthread_cond_broadcast (&pcond->cond)); }
static DBusCondVar * _dbus_pthread_condvar_new (void) { DBusCondVarPThread *pcond; pthread_condattr_t attr; int result; pcond = dbus_new (DBusCondVarPThread, 1); if (pcond == NULL) return NULL; pthread_condattr_init (&attr); #ifdef HAVE_MONOTONIC_CLOCK if (have_monotonic_clock) pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); #endif result = pthread_cond_init (&pcond->cond, &attr); pthread_condattr_destroy (&attr); if (result == EAGAIN || result == ENOMEM) { dbus_free (pcond); return NULL; } else { PTHREAD_CHECK ("pthread_cond_init", result); } return DBUS_COND_VAR (pcond); }
static void _dbus_pthread_condvar_free (DBusCondVar *cond) { DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&pcond->cond)); dbus_free (pcond); }
static void _dbus_pthread_mutex_free (DBusMutex *mutex) { DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); _dbus_assert (pmutex->count == 0); PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&pmutex->lock)); dbus_free (pmutex); }
static dbus_bool_t _dbus_pthread_condvar_wait_timeout (DBusCondVar *cond, DBusMutex *mutex, int timeout_milliseconds) { DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); struct timeval time_now; struct timespec end_time; int result; int old_count; _dbus_assert (pmutex->count > 0); _dbus_assert (pthread_equal (pmutex->holder, pthread_self ())); #ifdef HAVE_MONOTONIC_CLOCK if (have_monotonic_clock) { struct timespec monotonic_timer; clock_gettime (CLOCK_MONOTONIC,&monotonic_timer); time_now.tv_sec = monotonic_timer.tv_sec; time_now.tv_usec = monotonic_timer.tv_nsec / 1000; } else /* This else falls through to gettimeofday */ #endif gettimeofday (&time_now, NULL); end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000; end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000; if (end_time.tv_nsec > 1000*1000*1000) { end_time.tv_sec += 1; end_time.tv_nsec -= 1000*1000*1000; } old_count = pmutex->count; pmutex->count = 0; result = pthread_cond_timedwait (&pcond->cond, &pmutex->lock, &end_time); if (result != ETIMEDOUT) { PTHREAD_CHECK ("pthread_cond_timedwait", result); } _dbus_assert (pmutex->count == 0); pmutex->count = old_count; pmutex->holder = pthread_self(); /* other threads may have locked the mutex in the meantime */ /* return true if we did not time out */ return result != ETIMEDOUT; }
static void _dbus_pthread_mutex_unlock (DBusMutex *mutex) { DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); _dbus_assert (pmutex->count > 0); pmutex->count -= 1; if (pmutex->count == 0) PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&pmutex->lock)); /* We leave pmutex->holder set to ourselves, its content is undefined if count is 0 */ }
static void _dbus_pthread_condvar_wait (DBusCondVar *cond, DBusMutex *mutex) { DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); int old_count; _dbus_assert (pmutex->count > 0); _dbus_assert (pthread_equal (pmutex->holder, pthread_self ())); old_count = pmutex->count; pmutex->count = 0; /* allow other threads to lock */ PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&pcond->cond, &pmutex->lock)); _dbus_assert (pmutex->count == 0); pmutex->count = old_count; pmutex->holder = pthread_self(); /* other threads may have locked the mutex in the meantime */ }
dbus_bool_t _dbus_platform_condvar_wait_timeout (DBusCondVar *cond, DBusCMutex *mutex, int timeout_milliseconds) { struct timeval time_now; struct timespec end_time; int result; #ifdef HAVE_MONOTONIC_CLOCK if (have_monotonic_clock) { struct timespec monotonic_timer; clock_gettime (CLOCK_MONOTONIC,&monotonic_timer); time_now.tv_sec = monotonic_timer.tv_sec; time_now.tv_usec = monotonic_timer.tv_nsec / 1000; } else /* This else falls through to gettimeofday */ #endif gettimeofday (&time_now, NULL); end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000; end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000; if (end_time.tv_nsec > 1000*1000*1000) { end_time.tv_sec += 1; end_time.tv_nsec -= 1000*1000*1000; } result = pthread_cond_timedwait (&cond->cond, &mutex->lock, &end_time); if (result != ETIMEDOUT) { PTHREAD_CHECK ("pthread_cond_timedwait", result); } /* return true if we did not time out */ return result != ETIMEDOUT; }
DBusCMutex * _dbus_platform_cmutex_new (void) { DBusCMutex *pmutex; int result; pmutex = dbus_new (DBusCMutex, 1); if (pmutex == NULL) return NULL; result = pthread_mutex_init (&pmutex->lock, NULL); if (result == ENOMEM || result == EAGAIN) { dbus_free (pmutex); return NULL; } else { PTHREAD_CHECK ("pthread_mutex_init", result); } return pmutex; }
void _dbus_platform_rmutex_free (DBusRMutex *mutex) { PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock)); dbus_free (mutex); }
void _dbus_platform_condvar_wake_one (DBusCondVar *cond) { PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&cond->cond)); }
void _dbus_platform_condvar_wait (DBusCondVar *cond, DBusCMutex *mutex) { PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&cond->cond, &mutex->lock)); }
void _dbus_platform_condvar_free (DBusCondVar *cond) { PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&cond->cond)); dbus_free (cond); }
void _dbus_platform_rmutex_unlock (DBusRMutex *mutex) { PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock)); }