Приветствую!
Собственно хотел услышать несколько слов об особенностях применения функции 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)
McQwerty wrote:
Может стоит проверить возвращаемые значения всех упомянутых вызовов?
--
Maxim YegorushkinPosted via RSDN NNTP Server 1.9
Здравствуйте, 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;
}
<...хрум...>
}
...зато бисплатна....