예제 #1
0
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;
    }
}
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #4
0
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));
}
예제 #5
0
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));
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
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);
}
예제 #9
0
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;
}
예제 #10
0
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 */
}
예제 #11
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 */
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
void
_dbus_platform_rmutex_free (DBusRMutex *mutex)
{
  PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock));
  dbus_free (mutex);
}
예제 #15
0
void
_dbus_platform_condvar_wake_one (DBusCondVar *cond)
{
  PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&cond->cond));
}
예제 #16
0
void
_dbus_platform_condvar_wait (DBusCondVar *cond,
                             DBusCMutex  *mutex)
{
  PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&cond->cond, &mutex->lock));
}
예제 #17
0
void
_dbus_platform_condvar_free (DBusCondVar *cond)
{
  PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&cond->cond));
  dbus_free (cond);
}
예제 #18
0
void
_dbus_platform_rmutex_unlock (DBusRMutex *mutex)
{
  PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock));
}