【问题标题】:Why WaitForMultipleObjectsEx acquires mutex during APC?为什么 WaitForMultipleObjectsEx 在 APC 期间获取互斥锁?
【发布时间】:2013-05-08 20:38:09
【问题描述】:

我有 5 个线程(在多核系统上)同时等待:

  1. 要获取的互斥锁 M
  2. 要发出事件 E 的信号

我正在使用WaitForMultipleObjectsEx(..., TRUE, INFINITE, TRUE),因为线程使用 APC。
请注意,APC以任何方式使用/触摸/更改/观察互斥体或事件。

我正在使用 Visual Studio 和 Process Hacker 进行调试,我正在目睹一个奇怪的现象:
通常,应该运行的线程(称为线程 A)仍在等待这两个对象。

我说“应该运行”是因为:

  1. 我已经多次验证(包括通过 Process Hacker)E 确实处于信号状态
  2. 没有其他线程获得 M 的所有权。事实上,3 其他线程也在等待获得 M。

不过,根据 Process Hacker(使用 NtQueryMutant to retrieve the count)的说法,在这种情况下,M 的“计数”值低得离谱,例如 -618。

当然,我不会忘记打电话给ReleaseMutex(是的,我也在检查返回值);事实上,一旦有人后来获得了互斥锁,Count 就会重新增加。

所以这就引出了一个问题:如果其他 4 个线程中有 3 个正在休眠,那么最后一个线程 (B) 在做什么?

答案是 B 在 WaitForMultipleObjectsEx 调用中执行 APC
无论我在 Visual Studio 中“逐步”通过 B 多远(甚至一路备份RtlDispatchAPC),没有其他线程唤醒。
只有在 APC 完成执行之后 才会唤醒任何线程!

我觉得这很奇怪,WaitForMultipleObjectEx's documentation says:

bWaitAllTRUE时,只有当所有对象的状态都设置为signaled时,函数的等待操作才完成。 该函数不会修改指定对象的状态,直到所有对象的状态都设置为已发出信号。例如,一个互斥锁可以发出信号,但线程没有获得所有权 直到其他对象的状态也设置为已发出信号。与此同时,其他一些线程可能会获得互斥锁的所有权,从而将其状态设置为非信号。

是文档错误,还是我的错误?

为什么WaitForMultipleObjectsEx 在执行 APC 期间获取互斥锁,即使它知道无论如何它永远不会获取互斥锁(因为执行 APC 意味着它将返回 WAIT_IO_COMPLETE,永远不会获取互斥体)?

【问题讨论】:

  • 互斥量上的大负数意味着同一个线程已经多次获取它,可能以某种递归方式。为什么会发生这种情况?您的 APC 是否执行警报等待?
  • @arx:这很有趣——我的 APC 进行警报等待。 APC 的最大嵌套是 1。(我已经在代码和 Process Hacker 中验证了这一点。)

标签: winapi visual-c++ mutex apc waitformultipleobjects


【解决方案1】:

我无法发表评论,所以我使用答案...

您没有显示任何代码,但 APC 不应该在正在运行的线程中触发带有 WAIT_IO_COMPLETION 代码的 WaitForMultipleObjectsEx 返回吗??

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 2014-02-28
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2012-03-12
    • 2011-04-13
    相关资源
    最近更新 更多