О функции pthread_mutex_timedlock
От: McQwerty Россия  
Дата: 18.02.05 10:13
Оценка:
Приветствую!

Собственно хотел услышать несколько слов об особенностях применения функции pthread_mutex_timedlock. В моём приложении эта функция никогда не выходит с таймаутом. Вот пример использования:

Объявления переменных:
pthread_mutexattr_t m_MutexAttributes;
pthread_mutex_t        m_Mutex;

Создание мутанта:
pthread_mutexattr_init( &m_MutexAttributes );
    
// Мьютекс будет действовать внутри одного процесса 
// ( в принципе так должно быть и по умолчанию)
pthread_mutexattr_setpshared(&m_MutexAttributes, PTHREAD_PROCESS_PRIVATE);

// Мьютекс будет рекурсивный
pthread_mutexattr_settype( &m_MutexAttributes, PTHREAD_MUTEX_RECURSIVE );

pthread_mutex_init ( &m_Mutex, &m_MutexAttributes );

Ожидание (timeout — параметр функции, микросекунды):
int iRes        = 0;

if ( timeout == infinite )
{
    iRes        = pthread_mutex_lock( &m_Mutex );
}
else
{
    timespec tim;
    clock_gettime( CLOCK_REALTIME, &tim );

    unsigned long lsec    = timeout / ONE_SECOND;
    tim.tv_sec    += lsec;
    // Проблема с потенциальным переполнением поля tv_nsec
    // существует, но в данном случае не проявляется, так как
    // timeout в тесте - целое число секунд.
    tim.tv_nsec    += (timeout % ONE_SECOND) * 1000;

    iRes        = pthread_mutex_timedlock(&m_Mutex, &tim);
}


Проблема заключается в том, что выделенная болдом строка никогда не вываливается
по таймауту. В момент вызова мутант стопудово занят другим потоком (это и есть суть теста).

Вопрос в том, что мне нужно сделать, чтобы я вывалился по таймауту?

Среда: Mandrake Linux на двухпроцессорной машине (Intel)
Re: О функции pthread_mutex_timedlock
От: MaximE Великобритания  
Дата: 18.02.05 14:27
Оценка: +1
McQwerty wrote:

Может стоит проверить возвращаемые значения всех упомянутых вызовов?

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re: О функции pthread_mutex_timedlock
От: McQwerty Россия  
Дата: 18.05.06 12:42
Оценка:
(up)
Re[2]: О функции pthread_mutex_timedlock
От: McQwerty Россия  
Дата: 18.05.06 12:43
Оценка:
при этом всём если использовать нерекурсивные мьютексы — тайм-аут будет!
при рекурсивных — никак!
Re[3]: О функции pthread_mutex_timedlock
От: McQwerty Россия  
Дата: 19.05.06 10:23
Оценка: 82 (3) :)
Здравствуйте, McQwerty, Вы писали:

MQ>при этом всём если использовать нерекурсивные мьютексы — тайм-аут будет!

MQ>при рекурсивных — никак!
Дело оказалось в бобине!!
Вот кусочек из mutex.c (выделения мои):
/* Linuxthreads - a simple clone()-based implementation of Posix        */
/* threads for Linux.                                                   */
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
/*                                                                      */
/* This program is free software; you can redistribute it and/or        */
/* modify it under the terms of the GNU Library General Public License  */
/* as published by the Free Software Foundation; either version 2       */
/* of the License, or (at your option) any later version.               */
/*                                                                      */
/* This program is distributed in the hope that it will be useful,      */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
/* GNU Library General Public License for more details.                 */

int __pthread_mutex_timedlock (pthread_mutex_t *mutex,
                               const struct timespec *abstime)
{
  pthread_descr self;
  int res;

  if (__builtin_expect (abstime->tv_nsec, 0) < 0
      || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000)
    return EINVAL;

  switch(mutex->__m_kind) {
  case PTHREAD_MUTEX_ADAPTIVE_NP:
    __pthread_lock(&mutex->__m_lock, NULL);
    return 0;
  case PTHREAD_MUTEX_RECURSIVE_NP:
    self = thread_self();
    if (mutex->__m_owner == self) {
      mutex->__m_count++;
      return 0;
    }
    __pthread_lock(&mutex->__m_lock, self);
    mutex->__m_owner = self;
    mutex->__m_count = 0;
    return 0;
  case PTHREAD_MUTEX_ERRORCHECK_NP:
    self = thread_self();
    if (mutex->__m_owner == self) return EDEADLK;
    res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime);
    if (res != 0)
      {
        mutex->__m_owner = self;
        return 0;
      }
    return ETIMEDOUT;
  case PTHREAD_MUTEX_TIMED_NP:
    /* Only this type supports timed out lock. */
    return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime)
            ? 0 : ETIMEDOUT);
  default:
    return EINVAL;
  }
}


При ожидании рекурсивного мутанта время вообще не используется

При рассмотрении соседней функции __pthread_mutex_lock, оказалось, что методом квадратно-гнездового копирования код ожидания из неё перекочевал в __pthread_mutex_timedlock.

int __pthread_mutex_lock(pthread_mutex_t * mutex)
{
<...хрум...>
  case PTHREAD_MUTEX_RECURSIVE_NP:
    self = thread_self();
    if (mutex->__m_owner == self) {
      mutex->__m_count++;
      return 0;
    }
    __pthread_lock(&mutex->__m_lock, self);
    mutex->__m_owner = self;
    mutex->__m_count = 0;
    return 0;
  }
<...хрум...>
}

...зато бисплатна....
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.