其他分享
首页 > 其他分享> > pthread_mutex_timedlock没有超时

pthread_mutex_timedlock没有超时

作者:互联网

操作系统:Linux

lib:glibc

我有多个线程访问一个硬件,我通过使用互斥锁防止争用.

该软件非常复杂,由于递归调用锁定,它可能在系统中出现死锁.出于这个原因,我使用’pthread_mutex_timedlock’而不是’pthread_mutex_lock’.我宁愿打印错误消息并继续,而不是导致系统看门狗和重置.这样我就可以在不降低系统的情况下看到问题.

这里有一段代码,可以帮助您理解我想要做的事情.

pthread_mutex_t MainMutex = PTHREAD_MUTEX_INITIALIZER;

#define m_TAKE_LOCK()   { \
                          struct timespec abs_time; \
                          clock_gettime(CLOCK_REALTIME , &abs_time); \
                          abs_time.tv_sec += 5; \
                          if (pthread_mutex_timedlock (&MainMutex, &abs_time) != 0) \
                          { \
                              printf("Lock failed PID %d %s\n",  getpid(), __func__); \
                          } \
                        }

#define m_RELEASE_LOCK() pthread_mutex_unlock(&MainMutex);

void func1(void) {m_TAKE_LOCK()}
void func2(void) {m_TAKE_LOCK()}

void main(void)
{
  while (1)
  {
    func1();
    func2();
    m_RELEASE_LOCK()
    ...
  }
}

还有其他线程也采取锁定但这不是问题.我遇到的问题是锁定超时永远不会发生.它永远等待并监视系统,这正是我想要避免的.

‘abs_time.tv_sec’是正确的 – 我已经打印了它,系统时钟已经在我尝试使用它时已经初始化了.

我知道Windows会阻止对同一进程的锁定,但Linux没有这样的保护.我意识到我不应该递归调用m_TAKE_LOCK(),但使用timedlock的目的是捕获错误(打印消息并继续).

谁知道我可能做错了什么?

解决方法:

您无法尝试获取已经拥有的互斥锁.这是不允许的.您假设它将产生特定的结果,并且不能保证它会这样做.

您应该使用递归互斥锁.你应该释放它与你获得它的次数相同.

但是,从根本上说,绝对要求获取互斥锁的任何代码确实知道它在运行时保留的互斥量与函数可能直接或间接调用的代码有关. (它不需要知道调用它的代码所拥有的’更高级’互斥锁,但它可以调用的函数不会触及它.)

因此,例如,如果您创建一个名为“Foo”的类调用“Bar”,则“Foo”类的每个函数都必须知道它与“Foo”或“Bar”相关联的任何锁定.如果某个新类“Qux”调用它,那么“Foo”代码不需要知道什么是“Qux”锁定,但是如果“Qux”在对“Bar”进行锁定时调用“Foo”,则“Foo”功能必须知道这一点.您必须实现一个理智的锁定层次结构. (除非你完全理解这条规则的基本原理并确定它不适用.)否则,你的代码将永远不会正常工作,除非偶尔运气.

POSIX spec不需要超时:“如果在不等待另一个线程解锁互斥锁的情况下无法锁定互斥锁,则在指定的超时到期时应终止此等待.”没有其他线程可以等待.它也不需要错误,“pthread_mutex_timedlock()函数可能会失败,如果:
[EDEADLK]检测到死锁条件或当前线程已拥有互斥锁.“”May“表示支持是可选的错误条件,术语”如果用于表示所需行为,则应失败“.

标签:c-3,linux,embedded-linux
来源: https://codeday.me/bug/20190902/1792470.html